Nginx需配置set_real_ip_from和real_ip_header才能通过X-Forwarded-For等头获取真实客户端IP,再用$realip_remote_addr在自定义日志格式中记录,而非直接使用$remote_addr。

Nginx 默认记录的 $remote_addr 是直接连接它的客户端地址,比如负载均衡器或 CDN 的 IP,不是用户真实 IP。要准确记录真实请求信息,关键不是“加字段”,而是先还原真实客户端身份,再用合适变量写入日志。
确保能拿到真实客户端 IP
Nginx 本身不自动信任 X-Forwarded-For 这类头,必须显式配置可信代理段,否则 $http_x_forwarded_for 可被伪造。
在 http 块中添加:
# 声明哪些 IP 是可信的上游代理(如云厂商 LB、公司内网反向代理) set_real_ip_from 10.0.0.0/8; set_real_ip_from 192.168.0.0/16; set_real_ip_from 172.16.0.0/12; # 若使用 Cloudflare,加上其 IP 段(官方定期更新,需同步) # 指定从哪个 HTTP 头取真实 IP real_ip_header X-Forwarded-For; # 或用 CF 的标准头(如果前端是 Cloudflare) # real_ip_header CF-Connecting-IP; # 可选:只取第一个非代理 IP(防伪造链) real_ip_recursive on;
配置后,$realip_remote_addr 就代表可信的真实客户端 IP(注意:不是 $remote_addr)。
定义含真实 IP 和关键请求信息的日志格式
在 http 块中定义一个增强格式,例如:
log_format full_client '$realip_remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt:$request_time u:$upstream_response_time '
'host:$host server:$server_addr';说明:
-
$realip_remote_addr:经set_real_ip_from校验后的真正用户 IP -
$host:请求头中的 Host 值(用于识别访问域名) -
$server_addr:本机响应请求的实际 IP(多网卡或 VIP 场景下可区分节点) -
rt和u:分别记录 Nginx 总耗时与上游服务响应耗时,便于性能归因
在 server 或 location 中启用该日志
server {
listen 80;
server_name example.com;
# 启用自定义日志(路径确保有写权限)
access_log /var/log/nginx/example.access.log full_client buffer=64k;
# 可选:对健康检查等路径关闭日志减少干扰
location = /healthz {
access_log off;
return 200 "OK";
}
}补充:记录请求体或自定义头(按需开启)
若需排查 API 问题,可加入 $request_body,但要注意前提:
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
- 必须在
server或location块中设置:client_body_buffer_size 128k; client_max_body_size 10m; # 不要设 client_body_in_file_only on;
然后在 log_format 中添加:
'req_body:"$request_body" ' 'x_id:"$http_x_request_id" ' 'auth_type:"$http_authorization" '
⚠️ 注意:$request_body 仅对未被 proxy_pass 等指令重写/转发的原始请求有效;敏感内容(如密码、token)务必脱敏,不可明文落盘。
验证与生效
改完配置后执行:
nginx -t && nginx -s reload
用带 X-Forwarded-For 的请求测试:
curl -H "X-Forwarded-For: 203.0.113.45" http://your-domain.com/
查看日志是否出现 203.0.113.45 而非代理 IP。
不复杂但容易忽略

















