Django+Gunicorn+Nginx环境下客户端IP获取错误求助
解决方案:正确获取Docker+Nginx反向代理下的Django客户端真实IP
1. 修正Nginx配置(移除多余的REMOTE_ADDR设置)
你的Nginx配置里,proxy_set_header REMOTE_ADDR $remote_addr;属于多余配置,反而会干扰真实IP传递。Nginx作为反向代理时,Django收到的默认REMOTE_ADDR就是Nginx容器的IP(即你看到的172.22.0.1),真实客户端IP需通过X-Forwarded-For头传递,保留核心转发配置即可:
server { server_tokens off; listen 80; server_name 127.0.0.1; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://microservice_backend:8000; } location ~/(media|static)/ { root /var/html; } }
2. 修复自定义IP提取函数
你的函数错误读取了HTTP_REMOTE_ADDR,但Nginx传递的真实IP在X-Forwarded-For头中,对应Django request.META里的HTTP_X_FORWARDED_FOR键。修正后的函数:
def get_client_ip(request) -> str: # 读取Nginx传递的X-Forwarded-For头 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: # X-Forwarded-For格式为「真实IP, 代理IP1, 代理IP2...」,取第一个值就是真实客户端IP ip = x_forwarded_for.split(',')[0].strip() else: # 无转发头时,直接取REMOTE_ADDR(仅适用于直接访问Django的场景) ip = request.META.get('REMOTE_ADDR', 'unknown') return ip
3. 正确配置django-xff中间件
若要用django-xff自动将REMOTE_ADDR替换为真实IP,必须在settings.py中配置信任的代理IP/子网(出于安全考虑,中间件默认会忽略未信任代理的转发头):
# settings.py MIDDLEWARE = [ # 确保django-xff中间件放在最前端(至少在依赖IP的中间件之前) 'xff.middleware.XForwardedForMiddleware', # ... 其他中间件 ] # 设置信任的代理:填写Nginx所在的Docker子网(如你的172.22.0.0/16) XFF_TRUSTED_PROXIES = ["172.22.0.0/16"] # 可选:开启严格模式,仅信任配置范围内的代理 XFF_STRICT = True
问题根源解释
- 172.22.0.1是Docker网关的IP,即Nginx容器访问Django容器时的源IP,因此Django默认的
REMOTE_ADDR会是这个值。 - 你之前的自定义函数错误读取了
HTTP_REMOTE_ADDR(对应Nginx手动设置的REMOTE_ADDR头,值仍是网关IP),根本没拿到真实客户端IP。 - django-xff返回192.168.0.1是因为未配置信任代理,中间件解析转发头时未正确过滤,导致取到了中间代理的IP。
内容的提问来源于stack exchange,提问作者Renzog
相关产品推荐
相关产品推荐

