ip_hash原生支持IPv6会话保持,主流版本默认用完整IPv6地址哈希(旧版或特定环境可能仅取前64位),比IPv4更精确;但需确保upstream配置规范、真实IP可还原且HTTP模块启用。

ip_hash 原生支持 IPv6 客户端会话保持,但必须明确知道它对 IPv6 的处理方式——不是“额外开启”,而是默认启用,且使用完整 IPv6 地址(或前 64 位)参与哈希计算。只要配置规范、真实 IP 可还原,IPv6 用户就能和 IPv4 一样被稳定路由到同一台后端。
IPv6 下 ip_hash 的工作逻辑
nginx 对 IPv6 客户端不做截断,直接取完整地址(如 2001:db8::1)进行哈希;部分旧版本或特定编译环境可能只取前 64 位,但主流 1.19+ 版本默认用全地址。这比 IPv4(仅取前三段)更精确,也更少出现“多个用户被哈希到同一节点”的情况。
- IPv4:哈希 192.168.1.x → 视为同一 IP 组,易在 NAT 环境下集中打到一台后端
- IPv6:哈希 2001:db8:abcd::1001 → 每个终端地址独立,天然分散性更好
- 只要后端列表不变,同一 IPv6 地址始终映射到同一 server;某 server 标记为 down 时,nginx 自动剔除并重算余下节点的哈希分布
基础配置必须满足的硬性条件
IPv6 能否真正生效,不取决于是否写了 ip_hash,而取决于 upstream 结构、真实 IP 获取、以及协议兼容性三个环节是否闭环。
- upstream 块首行必须是 ip_hash;,不能缩进,不能与 hash、least_conn 等指令混用
- 至少定义两台可用后端(不能只写一个 server,否则 nginx 启动报错或降级为轮询)
- server 行只写 IP:PORT,IPv6 地址需用方括号包裹,例如:server [2001:db8::10]:8080;
- 仅作用于 HTTP upstream,stream 模块不识别 ip_hash,需改用 hash $remote_addr consistent;
确保拿到真实的 IPv6 客户端地址
如果请求经过 CDN、云 WAF 或前置代理,$remote_addr 默认是代理的 IPv4/IPv6 地址,所有 IPv6 用户会被哈希成同一个值,全部压到一台后端——这是最常见的“配了没用”原因。
- 在 http 块中声明可信代理段,包括 IPv6 网段:
set_real_ip_from 2001:db8::/32;
set_real_ip_from 2001:db8:abcd::/64;
(根据你实际代理出口 IPv6 段调整) - 指定真实 IP 来源头字段:real_ip_header X-Forwarded-For;(注意:X-Forwarded-For 是逗号分隔列表,nginx 默认取最左,如需取最右可加 real_ip_recursive on;)
- 在 location 中透传头信息:proxy_set_header X-Real-IP $remote_addr; 和 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
验证 IPv6 会话保持是否生效
不要只看配置文件,要实测行为:
- 用 IPv6 客户端(如本地启用 IPv6 的 curl 或浏览器)连续请求,观察响应头中的 X-Upstream(可自定义添加)或后端日志里的 server IP 是否一致
- 临时在 upstream 中加一个 down 参数停掉某台 server,确认 IPv6 请求是否自动漂移到另一台,且后续仍固定——说明哈希环动态生效
- 检查 nginx 错误日志:nginx -t 必须通过;若出现 "ip_hash cannot be used with weight",说明某行 server 错误加了 weight=1 之类参数


















