要让Nginx访问日志准确记录CDN回源时的真实客户端IP,关键是启用http_realip_module并配置set_real_ip_from声明可信CDN网段、real_ip_header指定X-Forwarded-For头、real_ip_recursive on开启递归解析,使$remote_addr变量本身变为真实IP,并在log_format中直接使用$remote_addr。

要让 Nginx 访问日志准确记录 CDN 回源时的真实客户端信息,关键不是“多记一个头”,而是让 $remote_addr 本身变成用户真实 IP —— 这必须依赖 http_realip_module 的正确配置,而非简单改日志格式。
启用 realip 模块并声明可信 CDN 网段
Nginx 默认把直连它的 IP(即 CDN 节点 IP)当作 $remote_addr。要替换它,需明确告诉 Nginx 哪些上游是可信代理:
- 确认模块已启用:运行
nginx -V 2>&1 | grep -o http_realip,有输出表示支持 - 在
http或server块中添加 CDN 官方公布的可信回源网段,例如:- 阿里云 CDN:
set_real_ip_from 100.64.0.0/10; - Cloudflare:
set_real_ip_from 173.245.48.0/20;、set_real_ip_from 103.21.244.0/22;等(建议直接引用其最新 ASN 列表) - 腾讯云、百度云等同理,务必查官方文档获取准确 CIDR
- 阿里云 CDN:
指定来源头并开启递归解析
仅声明网段不够,还需告诉 Nginx 从哪个请求头读取原始 IP 链路,并正确剥离代理层:
-
real_ip_header X-Forwarded-For;—— 指定使用该头提取 IP 列表 -
real_ip_recursive on;—— 关键!启用后,Nginx 会从X-Forwarded-For值(如203.0.113.5, 198.51.100.1, 192.0.2.1)中,从右往左逐个比对是否属于可信网段;剔除所有匹配项后,最左边剩余的 IP 即为真实客户端 IP
日志格式中直接使用 $remote_addr
配置生效后,$remote_addr 已被 realip 模块动态覆盖为真实 IP,无需额外变量:
- 定义日志格式时,保持使用
$remote_addr:log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
- 站点配置中引用该格式:
access_log /var/log/nginx/access.log main;
- 切勿改用
$http_x_forwarded_for:它可能被伪造、含多个 IP、格式不统一,仅适合调试参考,不可用于统计或限流
验证 CDN 是否透传 X-Forwarded-For
若日志仍显示 CDN 节点 IP,问题大概率出在前端未正确传递头:
- 登录 CDN 控制台,确认已开启「透传客户端 IP」功能(如 Cloudflare 的 “True Client IP”,阿里云 CDN 的 “回源携带 X-Forwarded-For”)
- 若自建 LB 或前置 Nginx,需确保它设置了:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- 避免重复添加 XFF 头导致链路污染(如出现
1.1.1.1, 1.1.1.1, 203.208.60.1),realip 模块依赖干净、单向递增的 IP 序列


















