【问题标题】:REMOTE_ADDR not getting sent to Django using nginx & tornadoREMOTE_ADDR 未使用 nginx 和龙卷风发送到 Django
【发布时间】:2010-12-10 07:38:23
【问题描述】:

所以我用 nginx 进行了简单的设置,用于静态媒体和负载平衡,tornado 作为 django 的网络服务器(运行 4 个服务器)。我的问题是 remote_addr 没有传递给 django 所以我得到一个 KeyError:

article.ip = request.META['REMOTE_ADDR']

由于 nginx.conf,远程地址作为 X-Real-IP (HTTP_X_REAL_IP) 发送:

    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect false;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass http://frontends;
    }

由于 HTTP 附加到 META 键,我不能只做 proxy_set_header remote_addr $remote_addr。如果没有找到远程地址密钥,我可以做的是读取 X-Real-IP,但我很好奇是否有更智能的解决方案。

谢谢!

【问题讨论】:

  • 这不是正确的解决方案,但我添加了一个将 HTTP_X_REAL_IP 转换为 REMOTE_ADDR 的 django 中间件。
  • 这些语句将帮助您:proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Scheme $scheme;

标签: django nginx tornado


【解决方案1】:

这是我解决问题的方法。通过使用这个中间件:

class SetRemoteAddrMiddleware(object):
    def process_request(self, request):
        if not request.META.has_key('REMOTE_ADDR'):
            try:
                request.META['REMOTE_ADDR'] = request.META['HTTP_X_REAL_IP']
            except:
                request.META['REMOTE_ADDR'] = '1.1.1.1' # This will place a valid IP in REMOTE_ADDR but this shouldn't happen

希望有帮助!

【讨论】:

  • 唯一的问题是,如果您默默地放弃错误,您会在很久以后才发现配置错误的 Web 服务器(可能会丢失信息或用户无法登录)。我的建议是失败或至少记录错误。
  • 几乎总是,你不想在 CPython 2.x 中没有异常类型的try/except:,因为它也会捕获 SystemExit、KeyboardInterrupt 和 GeneratorExit——这些都是你最好留下的各种错误单独或在极少数情况下单独捕获它们。特别是在这种情况下,应该捕获 KeyError。但是你可以进一步简化所有这些代码:request.META.setdefault('REMOTE_ADDR', request.META.get('HTTP_X_REAL_IP', '1.1.1.1'))
  • 不错的解决方案,但请记住 has_key() 在 Python 3.x 中已被删除。使用:如果不是 request.META.get('REMOTE_ADDR', None):
【解决方案2】:

试试这个:

location / {
    proxy_pass http://frontends;
    proxy_pass_header Server;
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header REMOTE_ADDR $remote_addr;
}

只需添加proxy_set_header REMOTE_ADDR,它应该可以正常工作。

尝试过:

  • Django 1.5.4
  • Nginx 1.4.3
  • 龙卷风 2.2.1

【讨论】:

【解决方案3】:

我有类似的设置。把nginx放在apache前面后,发现apache日志里的IP一直是127.0.0.1。安装“libapache2-mod-rpaf”似乎可以解决它。我不知道您的问题是否与此有关。

【讨论】:

  • 感谢您的回答。顺便说一句:这也有助于 PHP 软件,它依赖于 $_SERVER['REMOTE_ADDR'] 现在也包含真正的远程 IP。
【解决方案4】:

添加“fastcgi_param REMOTE_ADDR $remote_addr;”到 nginx.conf 文件:

    location / {
    # host and port to fastcgi server
    fastcgi_pass 127.0.0.1:8801;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
    fastcgi_pass_header Authorization;
    fastcgi_intercept_errors off;
    ...
    # Add this line!
    fastcgi_param REMOTE_ADDR $remote_addr;
    ...
}

来源:how to nginx virtual servers + fcgi for django?

【讨论】:

  • 这适用于fastcgi_pass(谢谢!),但不适用于proxy_pass,这是OP 的设置(请参阅@windyjonas 的回答)。
  • 怎么样-fastcgi_param REMOTE_ADDR $http_x_real_ip;?如果 X-Real-IP 对 nginx 可用,它可以用作 fastcgi_param 传递。这将消除对应用程序源代码进行更改的需要。
【解决方案5】:

不,是not possible 传递remote_addr。所以我知道的唯一解决方案是使用 X-Real-IP 或 X-Forwarded-For 并确保后端正确处理这些。

编辑:这适用于 fastcgi_pass,而不是常规的 nginx proxy_pass

【讨论】:

  • 对于 fastcgi 处理程序,是的。但问题是关于 nginx 代理的。
  • 哎呀,我应该仔细阅读一下--proxy_pass 不是fastcgi_pass。显然,除非您编辑答案,否则我无法撤销我的反对票。 :/ 如果你要编辑它,我很乐意投票。
【解决方案6】:

对我来说,使用以下方法有效:

server {
    listen 80;
    server_name foo.bar.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

这适用于 django 1.4(特别是 localshop)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-20
    • 2013-09-09
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多