Python Flask request.remote_addr 在网络上是错误的,没有显示真实的用户 IP

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12770950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:51:00  来源:igfitidea点击:

Flask request.remote_addr is wrong on webfaction and not showing real user IP

pythonflaskwebfaction

提问by Ignas But?nas

I just deployed a Flask app on Webfaction and I've noticed that request.remote_addris always 127.0.0.1. which is of course isn't of much use.

我刚刚在 Webfaction 上部署了一个 Flask 应用程序,我注意到它request.remote_addr总是127.0.0.1. 这当然没有多大用处。

How can I get the real IP address of the user in Flask on Webfaction?

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

Thanks!

谢谢!

采纳答案by Ignas But?nas

If there is a proxy in front of Flask, then something like this will get the real IP in Flask:

如果在 Flask 前面有一个代理,那么这样的事情会在 Flask 中得到真实的 IP:

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

Update:Very good point mentioned by Eli in his comment. There could be some security issues if you just simply use this. Read Eli's postto get more details.

更新:Eli 在他的评论中提到了很好的一点。如果你只是简单地使用它,可能会有一些安全问题。阅读Eli 的帖子以获取更多详细信息。

回答by Rob Wouters

The problem is there's probably some kind of proxy in front of Flask. In this case the "real" IP address can often be found in request.headers['X-Forwarded-For'].

问题是在 Flask 前面可能有某种代理。在这种情况下,“真实”IP 地址通常可以在request.headers['X-Forwarded-For'].

回答by Shankar Cabus

Rewriting the Ignas's answer:

重写伊格纳斯的回答:

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

Remember to read Eli's postabout spoofing considerations.

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

回答by rezakamalifard

You can use request.access_routeto access list of ip :

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

if len(request.access_route) > 1:
    return request.access_route[-1]
else:
    return request.access_route[0]

Update:

更新:

You can just write this:

你可以这样写:

    return request.access_route[-1]

回答by saaj

Werkzeug middleware

Werkzeug 中间件

Flask's documentation is pretty specific about recommended reverse proxy server setup:

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

If you deploy your application using one of these [WSGI] servers behind an HTTP [reverse] proxy you will need to rewrite a few headers in order for the application to work [properly]. The two problematic values in the WSGI environment usually are REMOTE_ADDRand HTTP_HOST... Werkzeug ships a fixer that will solve some common setups, but you might want to write your own WSGI middleware for specific setups.

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

And also about security consideration:

还有关于安全考虑:

Please keep in mind that it is a security issue to use such a middleware in a non-proxy setup because it will blindly trust the incoming headers which might be forged by malicious clients.

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

The suggested code (that installs the middleware) that will make request.remote_addrreturn client IP address is:

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

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)

Note num_proxieswhich is 1by default. It's the number of proxy servers in front of the app.

请注意默认情况下num_proxies是哪个1。它是应用程序前面的代理服务器的数量

The actual code is as follows (lastest werkzeug==0.14.1at the time of writing):

实际代码如下(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

网络派系

Webfaction's documentation about Accessing REMOTE_ADDRsays:

网络派系关于访问REMOTE_ADDR的文档说:

...the IP address is available as the first IP address in the comma separated list in the HTTP_X_FORWARDED_FORheader.

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

They don't say what they do when a client request already contains X-Forwarded-Forheader, but following common sense I would assume they replace it. Thus for Webfaction num_proxiesshould be set to 0.

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

Nginx

nginx

Nginx is more explicit about it's $proxy_add_x_forwarded_for:

Nginx 更明确地说明它是$proxy_add_x_forwarded_for

the “X-Forwarded-For” client request header field with the $remote_addrvariable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_forvariable is equal to the $remote_addrvariable.

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

For Nginx in front of the app num_proxiesshould be left at default 1.

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