Python 如何在nginx代理背后的金字塔服务器中获取客户机的真实IP

Python 如何在nginx代理背后的金字塔服务器中获取客户机的真实IP,python,deployment,nginx,pyramid,wsgi,Python,Deployment,Nginx,Pyramid,Wsgi,我有一个金字塔应用程序,在某些地方使用request.environ['REMOTE\u ADDR'] 该应用程序由端口6543上的Python Paste提供服务,在端口80上侦听的nginx服务器正在向Paste服务器转发请求 nginx配置的灵感来自金字塔食谱: server { listen 80; ## listen for ipv4 listen [::]:80 default ipv6only=on; ## listen for ipv6 ser

我有一个金字塔应用程序,在某些地方使用
request.environ['REMOTE\u ADDR']

该应用程序由端口6543上的Python Paste提供服务,在端口80上侦听的nginx服务器正在向Paste服务器转发请求

nginx配置的灵感来自金字塔食谱:

server {

    listen   80; ## listen for ipv4
    listen   [::]:80 default ipv6only=on; ## listen for ipv6

    server_name  localhost;

    access_log  /var/log/nginx/localhost.access.log;

    location / {

        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:6543;

    }
在金字塔应用程序中,变量request.environ['REMOTE_ADDR']现在始终等于127.0.0.1。 我看到了一些解决这个问题的策略,但我不知道是否有推荐的方法

以下是我正在考虑的:

  • 如有必要,添加一个新的request订阅服务器,以替换request.environ['REMOTE\u ADDR']:

    如果event.request.environ中的“HTTP\u X\u REAL\u IP”:
    event.request.environ['REMOTE\u ADDR']=event.request.environ['HTTP\u X\u REAL\u IP']

  • 在到达金字塔层之前,使用wsgi中间件修改request.environ

  • 别的

您使用哪种策略部署金字塔应用程序? 如果我有两个nginx代理,会发生什么?(第一个服务于LAN,第二个服务于直接连接到internet的机器)

在nginx中:

location / {
    proxy_pass http://yourapp;
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $remote_addr;
        }
在php中,我会:

        if($_SERVER["HTTP_X_FORWARDED_FOR"]){
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }else{
        $ip = $_SERVER["REMOTE_ADDR"];
      } 

也许在python中类似,$ip是您真正的ip

如果您通过
use=egg:PasteDeploy#prefix
在WSGI管道中使用
paste.deploy.config.PrefixMiddleware
,它将自动将
X-Forwarded-For
转换为
REMOTE\u ADDR
。它还适用于反向代理的其他属性,例如,它将
X-Forwarded-Proto
转换为
wsgi.url\u scheme
,以确保如果用户使用https访问,则生成的url也是https


我使用nginx后面的gevent服务器,并使用
request.client\u addr
获取客户端的ip地址。

如果您没有WSGI管道,或者不希望使用
粘贴
,请添加事件处理程序:

config.add_subscriber(reverseProxyProtocolCorrection,'pyramid.events.NewRequest')
事件处理程序的读取方式如下:

def reverseProxyProtocolCorrection(event):
    event.request.scheme = 'https' if event.request.headers['X-Forwarded-Proto']=='https' else 'http'
    event.request.remote_addr=parseXForward(event.request.headers['X-Forwarded-For'],event.request.remote_addr)

并确保您的代理设置了标题

我一定错过了什么,因为我第一次尝试使用PrefixMiddleware,正如烹饪书中建议的那样,但它不起作用。我显然需要再试一次。好吧,结果我忘记插入[pipeline:main]部分了。一切正常