ip_hash是Nginx七层会话保持策略,基于客户端IP哈希确保路由一致;但CDN介入后$remote_addr变为代理IP导致失效,须通过real_ip_module还原真实IP(如配置set_real_ip_from和real_ip_header),并注意四层场景需改用Proxy Protocol与stream模块hash。

ip_hash 是 Nginx 七层负载均衡的一种会话保持策略,它基于客户端 IP 的哈希值决定后端节点,确保同一 IP 的请求始终落到同一台服务器。但当 CDN 或云负载均衡器介入后,$remote_addr 变成 CDN 节点 IP,ip_hash 就会失效——所有用户被“哈希”到少数几个 CDN 出口 IP 上,导致后端节点严重倾斜。
必须用 X-Forwarded-For + realip 模块还原真实 IP 后再做 ip_hash
ip_hash 默认只读 $remote_addr,而 CDN 不会改写这个变量。要让它真正按用户真实 IP 哈希,需先让 Nginx 把可信 CDN 传来的 X-Forwarded-For 解析为 $remote_addr:
- 在 http 块中启用 realip 模块,明确声明 CDN 的出口网段(如 Cloudflare 的 173.245.48.0/20、103.21.244.0/22 等)
- 设置 real_ip_header X-Forwarded-For,并开启 real_ip_recursive on
- 配置生效后,$remote_addr 就自动变为用户真实 IP,ip_hash 才能正确工作
CDN 必须传递且不伪造 X-Forwarded-For
不是所有 CDN 都默认透传或可信地设置 X-Forwarded-For:
- Cloudflare 用 CF-Connecting-IP 更可靠,应配 real_ip_header CF-Connecting-IP
- 阿里云 CDN、腾讯云 CDN 默认添加 X-Forwarded-For,但需确认未开启“隐藏真实 IP”类开关
- 自建 CDN 或边缘节点,务必在转发请求时加上 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
避免多级代理干扰 ip_hash 效果
如果架构是「用户 → CDN → Nginx LB → 后端」,中间环节越多,X-Forwarded-For 越容易被污染:
- 确保只有 CDN 是可信入口,Nginx LB 自身不重复追加 X-Forwarded-For(即不要在 upstream 段再写 proxy_set_header X-Forwarded-For)
- 若 CDN 已设好 CF-Connecting-IP 或 X-Real-IP,优先用这些单值头,比 X-Forwarded-For 更干净
- 日志中可加 $http_cf_connecting_ip 或 $realip_remote_addr 辅助验证是否还原成功
四层场景不适用 ip_hash,改用 Proxy Protocol
如果 CDN 或 SLB 工作在 TCP 四层(如阿里云 TCP 型 CLB),它无法修改 HTTP 头,X-Forwarded-For 完全不可用:
- 必须在 CDN/SLB 侧开启 Proxy Protocol v1/v2
- Nginx listen 指令加 proxy_protocol,并配 real_ip_header proxy_protocol
- 此时 $remote_addr 在 stream 或 http 块中均可被正确覆盖,但注意:ip_hash 仅支持 http 块,stream 块需用 hash $proxy_protocol_addr;


















