HAProxy以Docker容器运行时,容器内获取真实客户端IP的问题
解决Docker集群中HAProxy转发客户端真实IP到Django的问题
1. 调整Docker Compose的HAProxy网络模式
默认端口映射是NAT模式,会把客户端IP替换为Docker网关IP,导致HAProxy无法获取真实客户端IP。需将HAProxy容器改为主机网络模式,让它直接使用主机网络栈:
services: haproxy: image: haproxy:latest network_mode: host # 关键配置:跳过Docker端口NAT volumes: - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
注意:使用
network_mode: host后,无需再写ports: ["9763:80"],直接在HAProxy配置里监听主机的9763端口即可。
2. 修正HAProxy的Backend转发配置
确保HAProxy的backend段正确转发真实IP,同时指定标准的转发头部:
backend api balance roundrobin option forwardfor header X-Real-IP # 强制用X-Real-IP传递真实IP http-request add-header X-Forwarded-For %[src] server django1 django-container-1:8000 check server django2 django-container-2:8000 check
同时配置
X-Real-IP和X-Forwarded-For,覆盖不同场景的IP解析需求。
3. 配置Django信任HAProxy代理
Django默认不会信任代理发来的转发头部,需在settings.py中添加信任配置:
# settings.py ALLOWED_HOSTS = ['你的域名或主机IP'] # 生产环境不要用* # 填写HAProxy所在主机的IP或Docker网关IP(根据实际网络调整) TRUSTED_PROXIES = ['127.0.0.1', '10.0.0.1'] # 开启转发头部解析 USE_X_FORWARDED_HOST = True USE_X_FORWARDED_PORT = True # 如果用了HTTPS,添加SSL头部信任 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 视图中获取真实IP的示例 def get_client_ip(request): return request.META.get('HTTP_X_REAL_IP', request.META.get('REMOTE_ADDR'))
4. 验证配置有效性
重启所有容器后,在Django视图中打印request.META的HTTP_X_REAL_IP、HTTP_X_FORWARDED_FOR字段,确认是否为真实客户端IP。若仍显示Docker内网IP,检查:
- HAProxy日志中
%[src]是否为真实客户端IP - Docker Compose的网络配置是否生效
- Django的
TRUSTED_PROXIES是否包含HAProxy的IP
内容的提问来源于stack exchange,提问作者MsA
相关产品推荐
相关产品推荐

