根本原因是Nginx默认记录$remote_addr(负载均衡器内网IP),需启用realip模块、配置set_real_ip_from和real_ip_header指定可信代理与请求头,并在log_format中改用$realip_remote_addr变量,三者缺一不可。

轮询日志里看不到真实客户端 IP,根本不是轮询算法的问题,而是 Nginx 默认记录的是直接连接它的 IP——也就是负载均衡器或 CDN 的内网地址。要让日志体现用户真实 IP,得靠 realip 模块还原 + 正确透传头 + 日志变量调整,三者缺一不可。
确认 realip 模块已启用并配置可信来源
Nginx 不会自动信任 X-Forwarded-For 里的 IP,必须明确告诉它哪些代理是可信的:
- 在 http 或 server 块中添加 set_real_ip_from,填入你的负载均衡器内网段(如 10.0.0.0/8、192.168.0.0/16)或具体 IP
- 加上 real_ip_header X-Forwarded-For,指定从哪个请求头取原始 IP
- 若有多层代理(比如 CDN → WAF → Nginx),务必开启 real_ip_recursive on,否则可能取到中间层 IP 而非最外层用户 IP
检查负载均衡器是否真正透传了 X-Forwarded-For
如果上游没传这个头,Nginx 再怎么配也白搭:
- 用 curl -v http://your-domain 或浏览器开发者工具 Network 面板,看请求头里有没有 X-Forwarded-For,值是否包含你预期的公网 IP
- 如果是云厂商 SLB 或四层 TCP 负载均衡,默认不加 HTTP 头;需在控制台开启“透传客户端真实 IP”或改用 Proxy Protocol
- 自建 HAProxy 或上一级 Nginx,要确保有类似 option forwardfor 或 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的配置
日志格式必须引用 $realip_remote_addr 而非 $remote_addr
即使 realip 配置完全正确,$remote_addr 在日志中仍显示为负载均衡器 IP。要记录真实 IP,必须改用解析后的变量:
- 定义日志格式时,把 $remote_addr 替换为 $realip_remote_addr
- 推荐写法:log_format main '$realip_remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
- 不要用 $http_x_forwarded_for 直接写入日志用于安全判断——它可被伪造,仅适合调试查看
快速验证是否生效
别只盯着配置文件,动手验证链路是否打通:
- 临时在 log_format 中加入 $http_x_forwarded_for 和 $realip_remote_addr 两列,对比输出
- 发起一次请求后,查 access.log:如果前者有值(如 203.0.113.42, 10.1.2.3),后者等于第一个公网 IP,说明 realip 已生效
- 再检查该行 $realip_remote_addr 是否就是你本地出口 IP,即可确认整条链路完整


















