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

时间:2012-02-21 15:20:56

标签: python deployment nginx pyramid wsgi

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

应用程序由端口6543上的Python Paste提供,而端口80上侦听的nginx服务器将请求转发到Paste服务器。

nginx配置的灵感来自Pyramid食谱:

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;

    }

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

以下是我正在考虑的事项:

  • 添加一个NewRequest订户,在必要时替换request.environ ['REMOTE_ADDR']:

    if 'HTTP_X_REAL_IP' in event.request.environ: event.request.environ['REMOTE_ADDR'] = event.request.environ['HTTP_X_REAL_IP']

  • 在点击金字塔图层之前使用wsgi中间件修改request.environ。

  • 别的东西

您使用哪种策略部署Pyramid应用程序? 如果我有两个nginx代理会怎么样? (第一个服务于LAN,第二个服务器直接连接到互联网)。

4 个答案:

答案 0 :(得分:6)

如果您通过paste.deploy.config.PrefixMiddleware在WSGI管道中使用use = egg:PasteDeploy#prefix,它会自动将X-Forwarded-For转换为REMOTE_ADDR。它对于反向代理的其他属性也很有用,例如它会将X-Forwarded-Proto翻译为wsgi.url_scheme,以确保如果用户使用https访问,则生成的网址也是https。

http://pythonpaste.org/deploy/class-paste.deploy.config.PrefixMiddleware.html

答案 1 :(得分:2)

我在nginx后面使用gevent服务器,并使用request.client_addr来获取客户端的IP地址。

答案 2 :(得分:1)

如果您没有WSGI pipline,或者不想使用paste,那么添加一个事件处理程序:

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)

并确保您的代理设置标题

答案 3 :(得分:-2)

在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