Flask request.remote_addr在webfaction上是错误的,并且没有显示真实的用户IP

Ign*_*nas 19 python webfaction flask

我刚刚在Webfaction上部署了一个Flask应用程序,我注意到它request.remote_addr始终是127.0.0.1.这当然没什么用处.

如何在Webfaction上的Flask中获取用户的真实IP地址?

谢谢!

Ign*_*nas 39

如果在Flask前面有代理,那么像这样的东西将获得Flask中的真实IP:

if request.headers.getlist("X-Forwarded-For"):
   ip = request.headers.getlist("X-Forwarded-For")[0]
else:
   ip = request.remote_addr
Run Code Online (Sandbox Code Playgroud)

更新: Eli在评论中提到的非常好的观点.如果您只是使用它,可能会出现一些安全问题.阅读Eli的帖子以获取更多详细信息.

  • 您不希望直接访问`x-forwarded-for`.Flask和werkzeug提供[`request.access_route`](http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.BaseRequest.access_route),其中包含该标题中已经拆分的IP列表. (10认同)
  • 这是危险的建议.Webfaction*将实际地址附加到X-Forwarded-For,因此使用此代码(选择列表中的第一个地址)允许恶意用户将其IP地址欺骗为*任意字符串*.请参阅http://esd.io/blog/flask-apps-heroku-real-ip-spoofing.html,以便进行更长时间的讨论并尝试解决方案. (8认同)

Sha*_*bus 7

重写伊格纳斯的回答:

headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr
Run Code Online (Sandbox Code Playgroud)

请记住阅读Eli关于欺骗注意事项的帖子


itm*_*ard 7

您可以使用request.access_route访问 ip 列表:

if len(request.access_route) > 1:
    return request.access_route[-1]
else:
    return request.access_route[0]
Run Code Online (Sandbox Code Playgroud)

更新:

你可以这样写:

    return request.access_route[-1]
Run Code Online (Sandbox Code Playgroud)

  • 正如@tristan 指出的那样,长度检查的使用毫无用处。仅当长度为 1 时,“else”才会匹配(Flask 将始终返回至少一个结果。),其中“request.access_route[-1]”仍然有效。 (5认同)
  • 您实际上不需要此处的长度检查 - 单长度列表上的“some_list[-1] == some_list[0]” (2认同)

saa*_*aaj 7

Werkzeug 中间件

Flask 的文档非常具体地介绍了推荐的反向代理服务器设置

如果您在 HTTP [反向] 代理后面使用这些 [WSGI] 服务器之一部署您的应用程序,您将需要重写一些标头,以便应用程序 [正确] 工作。WSGI 环境中的两个有问题的值通常是REMOTE_ADDRand HTTP_HOST... Werkzeug 提供了一个修复程序来解决一些常见的设置,但您可能想为特定设置编写自己的 WSGI 中间件。

还有关于安全考虑:

请记住,在非代理设置中使用此类中间件是一个安全问题,因为它会盲目信任可能由恶意客户端伪造的传入标头。

request.remote_addr返回客户端 IP 地址的建议代码(安装中间件)是:

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)
Run Code Online (Sandbox Code Playgroud)

请注意默认情况下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]
Run Code Online (Sandbox Code Playgroud)

网络派系

Webfaction's 关于AccessingREMOTE_ADDR的文档说:

...IP 地址可用作HTTP_X_FORWARDED_FOR标题中逗号分隔列表中的第一个 IP 地址。

当客户端请求已经包含X-Forwarded-For标头时,他们不会说他们会做什么,但是按照常识,我会假设他们会替换它。因此对于 Webfactionnum_proxies应该设置为0.

nginx

Nginx 更明确地说明它是$proxy_add_x_forwarded_for

“X-Forwarded-For”客户端请求标头字段,$remote_addr附加了变量,用逗号分隔。如果客户端请求标头中不存在“X-Forwarded-For”字段,则该$proxy_add_x_forwarded_for变量等于该$remote_addr变量。

对于应用程序前面的 Nginxnum_proxies应保留默认值1

  • 如果您运行的是 werkzeug 1.0.0,则需要导入“from werkzeug.middleware.proxy_fix import ProxyFix”。 (5认同)