我刚刚在Webfaction上部署了一个Flask应用,我注意到request.remote_addr
总是127.0.0.1
。这当然没什么用。
如何在Webfaction上的Flask中获取用户的真实IP地址?
谢谢!
答案 0 :(得分:32)
如果Flask面前有代理,那么像这样的东西将在Flask中得到真正的IP:
if request.headers.getlist("X-Forwarded-For"):
ip = request.headers.getlist("X-Forwarded-For")[0]
else:
ip = request.remote_addr
更新: Eli在评论中提到的非常好的观点。如果您只是使用它,可能会出现一些安全问题。阅读Eli's post以获取更多详细信息。
答案 1 :(得分:4)
Flask的文档非常具体about recommended reverse proxy server setup:
如果使用HTTP [反向]代理后面的这些[WSGI]服务器之一部署应用程序,则您将需要重写一些标头才能使该应用程序正常运行。 WSGI环境中的两个有问题的值通常是
REMOTE_ADDR
和HTTP_HOST
... Werkzeug附带了一个可解决一些常见设置的修复程序,但是您可能想为特定设置编写自己的WSGI中间件。 / p>
还有安全方面的考虑:
请记住,在非代理设置中使用这样的中间件是一个安全问题,因为它会盲目地信任可能由恶意客户端伪造的传入标头。
将使request.remote_addr
返回客户端IP地址的建议代码(安装中间件)为:
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)
请注意,num_proxies
默认为1
。这是应用程序前面的代理服务器的数量。
实际代码如下(在撰写本文时,最新的werkzeug==0.14.1
):
def get_remote_addr(self, forwarded_for):
if len(forwarded_for) >= self.num_proxies:
return forwarded_for[-self.num_proxies]
Webfaction关于Accessing REMOTE_ADDR
的文档说:
...该IP地址可用作
HTTP_X_FORWARDED_FOR
标头中逗号分隔列表中的第一个IP地址。
当客户请求中已经包含X-Forwarded-For
标头时,他们不会说什么,但是按照常识,我认为他们会替换标头。因此,对于Webfaction,num_proxies
应该设置为0
。
Nginx的$proxy_add_x_forwarded_for
更明确:
附加了
$remote_addr
变量的“ X-Forwarded-For”客户端请求标头字段,以逗号分隔。如果客户端请求标头中不存在“ X-Forwarded-For”字段,则$proxy_add_x_forwarded_for
变量等于$remote_addr
变量。
对于应用前的Nginx,num_proxies
应该保留为默认值1
。
答案 2 :(得分:3)
问题是在Flask面前可能有某种代理。在这种情况下,“真实”IP地址通常可以在request.headers['X-Forwarded-For']
中找到。
答案 3 :(得分:3)
重写Ignas的回答:
headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr
请务必阅读有关欺骗注意事项的Eli's post。
答案 4 :(得分:2)
您可以使用request.access_route
访问ip列表:
if len(request.access_route) > 1:
return request.access_route[-1]
else:
return request.access_route[0]
更新
你可以这样写:
return request.access_route[-1]