由于 Tornado 部署在 Nginx 后面,通过 self.request.remote_ip
总是只能拿到 Nginx 地址。
服务器上的 Nginx 配置如下:
upstream markjour {
server 192.168.64.101:8081;
server 192.168.64.101:8082;
check interval=5000 rise=1 fall=3 timeout=5000;
}
这样,同一台机器上的 Tornado 中拿到的都是 Nginx 访问 Tornado 时使用的地址:192.168.64.101。
看到很多人都在说需要在 Nginx 中设置 X-Forwarded-For
,这是废话,当然设置了,比如我的服务器环境是这样的:
http {
...
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
...
}
通过 Bing 搜到 SO 上有一个回答,挺好的。
除了上面的步骤之外,还需要在启动服务时传入一个特殊参数:
server = httpserver.HTTPServer(application, xheaders=True)
或者直接读 HTTP Header:
self.request.headers.get('X-Real-Ip', '')
其他
顺便了解到一个小知识点:
- 第一版配置:
proxy_set_header X-Forwarded-For $remote_addr;
如上配置只能增加负载均衡 IP 地址,丢失了客户端真实 IP 和任意中间代理 IP - 第二版配置:
proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $remote_addr";
如上配置在原有请求头X-Forwarded-For
字段的基础上增加了连接 Nginx 的服务器 IP 地址 - 第三版配置(最为简单):
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
$proxy_add_x_forwarded_for
已经实现了第二版的功能,直接使用该内置变量即可
具体地址参见:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#var_proxy_add_x_forwarded_for
如果要获取用户端的真实IP,应该从请求头中的X-Forwarded-For
字段中取第一个英文逗号前的 IP 地址。