排查ip_hash哈希漂移的核心是确认$remote_addr是否为用户真实IP;若被多层代理覆盖为内网地址(如10.10.1.1),则哈希必然失真,需通过set_real_ip_from、real_ip_header和real_ip_recursive精准还原,并验证日志中$remote_addr与$http_x_forwarded_for是否匹配。

排查因代理层数过多引发的 ip_hash 哈希漂移,核心是确认 Nginx 收到的究竟是哪一级 IP —— 它是否还是用户真实地址,还是早已被多层代理覆盖成中间网关地址。漂移不是哈希算法出错,而是哈希对象错了。
确认 $remote_addr 是否已被污染
ip_hash 默认基于 $remote_addr 计算,而该变量在有代理时通常只反映**最近一跳客户端(即上一级代理)的地址**。若前面还有 CDN、WAF、LVS 或多层 Nginx,$remote_addr 很可能已是统一出口 IP(如 10.10.1.1),导致所有请求哈希结果一致,看似“全打到一台”,实为哈希源失效。
- 在 access_log 中添加 $remote_addr 和 $http_x_forwarded_for 字段,对比观察:正常应看到不同值;若两者相同或 $remote_addr 长期固定,说明真实 IP 未透传
- 用 curl 模拟请求,手动加头测试:
curl -H "X-Forwarded-For: 203.201.100.50" http://your-domain/,再查日志,验证 Nginx 是否能识别并使用该 IP
检查 real_ip_module 配置是否完整且可信
仅配置 set_real_ip_from 不够,必须确保代理链中每一级都可信、且头字段未被篡改。
- set_real_ip_from 必须精确列出所有可信代理 IP 或网段(如 CDN 回源段、内网 LB 地址),不能漏也不能宽泛(如写 0.0.0.0/0 是危险的)
- 确认 real_ip_header 与上游实际填充的头一致(常见为
X-Forwarded-For或X-Real-IP),且启用real_ip_recursive on;以支持多层嵌套解析(取最左/最右需结合业务判断) - 检查 error_log 是否有
ignoring invalid X-Forwarded-For类警告,这表示头格式非法或不可信代理伪造了字段
验证哈希源是否真正生效
即使启用了 real_ip_module,ip_hash 仍只认 $remote_addr —— 所以必须让还原后的 IP 成为新的 $remote_addr。
- 配置生效后,用
curl -I或后端应用打印 $http_x_real_ip(如果 proxy_set_header 透传了)或直接查 Nginx access_log 中 $upstream_addr + $http_x_forwarded_for 组合,确认不同用户是否映射到不同后端 - 停掉一台后端,持续用多个真实公网 IP(非同一 NAT 下)发起请求,观察是否出现 502、是否触发重试、是否落到 backup 节点——若全部卡死在宕机节点,说明哈希源没变,real_ip 未起作用
- 临时注释掉 upstream 中的 ip_hash,改用轮询,再比对日志中 $upstream_addr 分布:若轮询已均匀但 ip_hash 仍集中,基本可断定哈希输入源异常
定位代理链中哪一层丢失了原始 IP
从客户端向后逐级排查,重点看每层是否主动剥离或未设置 X-Forwarded-For。
- 浏览器开发者工具 → Network → 请求 Headers,找 X-Forwarded-For 值:若为空或只有本层代理 IP,说明前一级没传
- 检查 CDN/WAF 控制台,确认是否开启“透传客户端真实 IP”选项(如阿里云 SLB 的“获取真实访问 IP”、Cloudflare 的 “True Client IP”)
- 若自建多层 Nginx,确认每一层都有
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,而非简单写$remote_addr


















