应使用真实客户端ip做hash分发:先用map从x-forwarded-for提取$嗜clientrealip,再在upstream中用hash $clientrealip consistent;替代ip_hash;同时配置realip模块限定可信代理范围并递归解析真实ip。

直接在 upstream 块中启用 ip_hash,同时确保后端能拿到真实客户端 IP,关键不是只加一句 ip_hash,而是要让 hash 计算基于用户真实 IP,而不是代理 IP(比如 CDN 或 WAF 的出口 IP)。
为什么默认 ip_hash 不可靠
Nginx 的 ip_hash 默认使用 $remote_addr 计算哈希值。但在反向代理、CDN、WAF 等多层架构下,$remote_addr 往往是上一跳代理的 IP,不是用户真实 IP。如果直接用它做 hash,同一用户经不同 CDN 节点访问,会被路由到不同后端,session 依然会断。
正确做法:用真实 IP 做 hash
核心思路是:先从 X-Forwarded-For 提取出用户真实 IP,再用这个 IP 做 hash 分发。分两步实现:
- 在
http块中用map提取真实 IP,例如:
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P
}
- 在
upstream块中改用hash $clientRealIp;替代ip_hash;:
upstream backend {
hash $clientRealIp consistent;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
-
consistent可选,提升节点增减时的哈希稳定性;不加也行,但扩容缩容可能引发部分会话漂移
必须同步透传真实 IP 给后端
光让 Nginx 自己用真实 IP 做 hash 还不够,后端应用也要能读到这个 IP(比如记录日志、限流、风控)。需在 location 块中设置:
proxy_set_header X-Real-IP $clientRealIp;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;- 确保上游代理(如 CDN)确实设置了
X-Forwarded-For,且格式为客户端IP, 代理1, 代理2
安全补充:限制可信代理范围
仅靠 map 提取不可防伪造。攻击者若手动加 X-Forwarded-For: 1.1.1.1,就会被当作真实 IP hash 和透传。所以应配合 realip 模块增强可信度:
- 确认 Nginx 编译时含
--with-http_realip_module - 在
http或server块中配置:
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 203.208.60.0/22;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
-
set_real_ip_from列出你信任的代理网段(如公司内网、CDN 回源 IP 段),只有来自这些地址的请求,Nginx 才会信任其X-Forwarded-For并更新$remote_addr -
real_ip_recursive on表示递归查找——从右往左剔除可信代理 IP,最终剩下最左边那个非可信 IP,即用户真实 IP











