nginx的ip_hash将ipv4地址前3段作为哈希键,故192.168.1.x等同子网内所有ip映射至同一后端;其设计本意即基于c类网络地址哈希,非缺陷;可通过real_ip模块、cookie哈希或least_conn+共享session优化。

Nginx 的 ip_hash 算法对内网私有 IP(如 192.168.x.x、10.x.x.x、172.16.x.x–172.31.x.x)的处理方式,和公网 IP 完全一致——它不区分公有或私有地址,只按 IPv4 的点分十进制格式取前 3 段参与哈希计算。
ip_hash 对 IPv4 地址的实际哈希逻辑
Nginx 源码中关键逻辑是:
- 将
$remote_addr解析为四字节数组(如192.168.1.4→[192, 168, 1, 4]) -
仅取前三个字节(即
192,168,1)代入哈希公式:hash = (hash * 113 + iphp->addr[i]) % 6271; // i = 0, 1, 2
- 最终用
hash % upstream_server_count决定转发目标
这意味着:
-
192.168.1.4和192.168.1.100→ 前三段相同 → 哈希值相同 → 固定落到同一台后端 -
192.168.2.5→ 前三段变为192.168.2→ 哈希结果不同 → 可能分到另一台
内网环境下的典型影响
在公司/学校等局域网中,大量终端处于同一 C 类子网(如 192.168.1.0/24),它们的前三段完全一致:
- 所有
192.168.1.x用户 → 全部被映射到同一个后端服务器 - 即使后端有 4 台机器,实际只有 1 台承载全部内网流量
这并非算法缺陷,而是设计使然:官方明确说明 “the key for the hash is the class-c network address”(哈希键是 C 类网络地址)。
如何让内网 IP 更均匀分布?
不能改 Nginx 源码,但可通过配置提升粒度:
- ✅ 启用
real_ip模块并正确设置set_real_ip_from+real_ip_header X-Forwarded-For,把穿透代理后的真实终端 IP 交给ip_hash(前提是上游可信且透传准确) - ✅ 改用
hash $http_cookie_session consistent;(需应用写入唯一 session cookie) - ✅ 切换为
least_conn+ Redis 共享 Session,彻底解耦负载均衡与会话绑定 - ❌ 不要尝试用
geo或正则伪造$remote_addr—— 易引发安全与一致性问题
内网 IP 被当作 C 类网络统一哈希,是 ip_hash 的固有行为,不是异常。关键在于你是否真的需要“按终端 IP 绑定”,还是只需“用户会话不丢失”——后者有更健壮的替代方案。











