【问题标题】:How to get the real IP of a client in a pyramid server behind a nginx proxy如何在 nginx 代理后面的金字塔服务器中获取客户端的真实 IP
【发布时间】:2012-03-11 21:54:17
【问题描述】:

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

应用程序由 Python Paste 在端口 6543 上提供服务,并且在端口 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。 我看到了一些解决这个问题的策略,但我不知道是否有推荐的方法来做到这一点。

这是我正在考虑的:

  • 如有必要,添加一个替换 request.environ['REMOTE_ADDR'] 的 NewRequest 订阅者:

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

  • 在到达 Pyramid 层之前使用 wsgi 中间件修改 request.environ。

  • 别的东西

您使用哪种策略来部署 Pyramid 应用程序? 如果我有两个 nginx 代理会发生什么? (第一个服务于局域网,第二个服务于直接连接到互联网的机器)。

【问题讨论】:

    标签: python deployment nginx pyramid wsgi


    【解决方案1】:

    如果你没有 WSGI 管道,或者不想使用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)
    

    并确保您的代理设置标题

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 我一定错过了一些东西,因为我首先按照食谱中的建议尝试了 PrefixMiddleware,但它没有用。我显然需要再试一次。
        • 好吧,原来我忘了插入 [pipeline:main] 部分。一切正常
        【解决方案4】:

        在 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-14
          • 1970-01-01
          • 1970-01-01
          • 2021-09-01
          • 2020-10-21
          • 2020-08-23
          • 2011-07-19
          相关资源
          最近更新 更多