要在Nginx的server块中准确记录客户端真实IP,关键是启用ngx_http_realip_module模块,配置set_real_ip_from声明可信代理网段、real_ip_header指定X-Forwarded-For头、real_ip_recursive on开启递归解析,使$remote_addr自动更新为真实IP,并在log_format中直接使用$remote_addr。

要在 Nginx 的 server 块中准确记录客户端真实 IP,关键不是“把 X-Forwarded-For 写进日志”,而是让 $remote_addr 这个变量本身变成真实 IP——这必须靠 ngx_http_realip_module 模块完成可信代理识别与递归解析。
启用 realip 模块并声明可信代理来源
Nginx 官方编译版默认已包含该模块(可运行 nginx -V 2>&1 | grep http_realip 确认)。在 server 块或外层 http 块中添加:
-
set_real_ip_from 100.64.0.0/10;—— 覆盖阿里云、腾讯云等主流云厂商 SLB/ALB 的私有地址段 -
set_real_ip_from 192.168.0.0/16;、set_real_ip_from 172.16.0.0/12;、set_real_ip_from 10.0.0.0/8;—— 覆盖常见内网负载均衡和代理网段 -
real_ip_header X-Forwarded-For;—— 明确从该请求头提取原始 IP 链路 -
real_ip_recursive on;—— 启用递归解析,确保多级代理(如 CDN → LB → Nginx)下能剔除所有可信中间 IP,最终取最左端未被白名单覆盖的地址
在 log_format 中直接使用 $remote_addr
配置生效后,$remote_addr 就是经过校验的真实客户端 IP。因此日志格式中无需改用 $http_x_forwarded_for 或 $realip_remote_addr(后者仅旧版本或特殊回退场景使用):
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
并在 server 块中启用:
access_log /var/log/nginx/access.log main;
确保上游正确透传 X-Forwarded-For
若日志仍显示代理 IP,大概率是前端未传递或传递异常:
- CDN 控制台需开启“透传客户端 IP”功能(如 Cloudflare 的 “True Client IP”,阿里云 CDN 的 “回源携带 X-Forwarded-For”)
- 若你控制前置代理(如另一层 Nginx),需确保其配置了:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 避免重复添加 XFF 头导致格式混乱(如
1.1.1.1, 1.1.1.1, 2.2.2.2),realip 模块依赖干净、单次追加的 IP 链路
验证是否生效
临时加一条调试日志对比值:
log_format debug '$http_x_forwarded_for — $remote_addr';
access_log /var/log/nginx/debug.log debug;
观察日志中三者是否一致:XFF 头内容、解析后的 $remote_addr。确认无误后 reload:
nginx -s reload


















