nginx 日志显示负载均衡器内网ip而非用户真实ip,因未启用realip模块解析x-forwarded-for;需配置set_real_ip_from、real_ip_header及log_format使用$realip_remote_addr,并确保负载均衡器透传该请求头。

因为 Nginx 没有正确识别并替换来自负载均衡器的请求头,仍把 $remote_addr(即连接发起方的 IP)当作客户端真实 IP 记录。而这个“连接发起方”其实是负载均衡器的内网 IP,不是用户原始 IP。
关键原因:Nginx 未启用 realip 模块解析 X-Forwarded-For
负载均衡器(如云 SLB、HAProxy 或上一级 Nginx)通常会在 HTTP 请求头中添加 X-Forwarded-For,把用户真实 IP 放在最前面。但默认情况下,Nginx 不会主动用它替换 $remote_addr,也不会自动将它写入日志——必须显式启用 realip 模块并配置可信代理段。
-
set_real_ip_from必须明确列出负载均衡器的 IP 或网段(例如10.0.0.0/8或具体内网 IP),否则 Nginx 会忽略所有X-Forwarded-For头 -
real_ip_header X-Forwarded-For告诉 Nginx 从哪个头取真实 IP - 若有多层代理(如 CDN → SLB → Nginx),需开启
real_ip_recursive on,否则可能取到中间代理的 IP 而非最前端用户 IP
日志格式里没引用真实 IP 变量
即使 realip 配置正确,$remote_addr 在日志中依然显示为负载均衡器 IP——因为日志格式默认用的是这个变量。要让日志体现真实 IP,必须改用解析后的变量:
- 启用 realip 后,
$realip_remote_addr就是解析出的真实客户端 IP - 或直接在
log_format中使用$http_x_forwarded_for(但注意该字段可能被伪造,不推荐用于安全策略) - 推荐写法:
log_format main '$realip_remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
负载均衡器本身没传 X-Forwarded-For
有些云厂商 SLB 或四层 TCP 负载均衡默认不加 HTTP 头(因为它们工作在传输层)。这时 X-Forwarded-For 根本不存在,Nginx 再怎么配置也无济于事。
- 确认你的负载均衡类型:如果是七层(HTTP/HTTPS),务必开启“透传客户端真实 IP”或“添加 X-Forwarded-For 头”开关
- 如果是四层(TCP/UDP),X-Forwarded-For 不可用,得改用 Proxy Protocol,并在 Nginx 的
listen指令中加上proxy_protocol,同时后端服务也要支持解析 - 检查请求头:用
curl -v http://your-site或浏览器开发者工具看响应头是否含X-Forwarded-For,或在 Nginx access log 中临时加$http_x_forwarded_for看是否为空
可信代理配置错误或缺失
set_real_ip_from 是一道安全闸门。如果填错、漏填、或用了公网 IP 却实际走的是内网通信,Nginx 就不会信任该请求头,坚持用 $remote_addr。
- 常见错误:写成
set_real_ip_from 127.0.0.1;,但负载均衡器和 Nginx 并不在同一台机器 - 正确做法:查清负载均衡器发来请求的实际源 IP(比如
172.16.0.10或192.168.100.0/24),只允许这些地址触发 realip 解析 - 可配合
error_log级别调高(如debug)观察 realip 模块是否生效:“realip: xx.xx.xx.xx is not trusted” 表示匹配失败











