导读:本期聚焦于叶子创作的《Nginx如何通过X-Forwarded-For日志准确记录回源后的真实客户端IP?》,敬请观看详情。当流量经过CDN或反向代理回源到Nginx时,access日志里记录的往往是代理节点IP而不是用户的真实地址,排查问题和统计分析都会受到干扰。本文围绕X-Forwarded-For这个请求头展开,分析多级代理下IP链的形成机制,讲解realip模块的配置方法,包括set_real_ip_from、real_ip_header和real_ip_recursive三个关键指令的作用与取值建议,并给出日志格式定义、伪造IP的风险防范以及常见配置踩坑点的完整示例,帮助你在各种代理架构下都能拿到可信的真实客户端IP。

网站流量经过CDN、负载均衡或多层反向代理回源之后,Nginx的access日志中$remote_addr记录的通常是最后一跳代理服务器的IP,而不是访客的真实地址。这对于安全审计、频率限制和访问统计都是致命的。要让Nginx拿到真实客户端IP,核心就在于正确解析回源请求中携带的X-Forwarded-For请求头,并通过realip模块把它还原成$remote_addr。本文从请求头的形成机制讲起,完整演示配置方法与防伪造措施。

Nginx如何通过X-Forwarded-For日志准确记录回源后的真实客户端IP?

一、X-Forwarded-For请求头是如何形成的

X-Forwarded-For(简称XFF)是一个事实上的HTTP扩展头,由代理服务器在转发请求时添加。它的格式是一个IP列表,每经过一层代理,该代理就会把自己的直接对端IP追加到列表末尾。例如用户IP是203.0.113.50,请求先经过CDN节点,CDN回源到SLB,SLB再转发给源站Nginx,那么到达源站时XFF的值可能是:

X-Forwarded-For: 203.0.113.50, 198.51.100.10

这个列表的语义是:最左边的IP是原始客户端IP,中间是各级代理的IP。而$remote_addr此时记录的是SLB的地址,也就是最后一跳的直连对端。理解了链式结构,就能明白为什么不能简单地取第一个IP就当作真实IP——因为这个头是可以被客户端伪造的。

关键的风险点在于:如果用户直接访问源站(或者代理没有清洗XFF),他可以在请求里主动带上一个伪造的XFF头,例如:

X-Forwarded-For: 1.2.3.4

此时CDN会在后面追加真实IP,变成1.2.3.4, 203.0.113.50。如果Nginx不加校验地取最左边的IP,攻击者就可以随意伪造来源地址,绕过基于IP的风控策略。所以在配置时必须明确哪些地址段是可信代理,只有可信代理追加的IP才参与还原计算。

二、使用realip模块还原真实客户端IP

Nginx自带的ngx_http_realip_module(默认编译包含)专门用于解决这一问题。它的工作原理是:当请求的直连对端IP命中set_real_ip_from定义的可信列表时,Nginx会用指定请求头中的值替换$remote_addr,被替换掉的原值会保存到$realip_remote_addr变量中,方便日志留痕。完整配置示例如下:

http {
    # 声明可信代理:只有来自这些地址的请求才信任其XFF头
    set_real_ip_from 10.0.0.0/8;      # 内网SLB网段
    set_real_ip_from 172.16.0.0/12;   # 内网容器网段
    set_real_ip_from 192.0.2.0/24;    # CDN回源网段

    # 指定从哪个请求头取值,常见取值还有X-Real-IP、CF-Connecting-IP
    real_ip_header X-Forwarded-For;

    # 关闭递归:取XFF的最后一个IP,即第一个可信代理的对端
    real_ip_recursive off;
}

这里需要重点区分real_ip_recursive的两种取值。关闭递归时,Nginx从XFF列表的最右边取一个IP,只要该IP是可信代理追加的,就用它替换$remote_addr。开启递归时,Nginx从右向左依次检查,跳过所有可信IP,取第一个不可信的IP作为真实客户端IP。两者的适用场景不同:

  • real_ip_recursive off:适合只有一层代理的架构,取到的IP是直接连接代理的那个地址,最保守也最安全。
  • real_ip_recursive on:适合CDN加SLB的多层代理架构,可以穿过所有可信代理,最终落在用户原始IP上。前提是可信列表必须覆盖全部代理网段,否则中间任何一层漏配都会导致取值错误。

另外注意,如果使用的是云厂商CDN,部分厂商提供专有请求头,例如Cloudflare的CF-Connecting-IP只包含单一客户端IP,不需要解析列表,配合real_ip_header CF-Connecting-IP使用会更简单可靠。

三、日志格式定义与效果验证

还原了真实IP之后,还需要在日志格式中体现出来。建议同时记录$remote_addr(还原后的真实IP)和$realip_remote_addr(TCP直连IP),两个值对照可以快速判断请求是否经过了代理:

log_format main '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent '
                '"$http_referer" "$http_user_agent" '
                'xff="$http_x_forwarded_for" tcp_peer="$realip_remote_addr"';

server {
    listen 80;
    access_log /var/log/nginx/access.log main;
}

配置完成后用nginx -t检查语法,nginx -s reload平滑重载。验证时可以通过curl模拟带伪造头的请求:

curl -H "X-Forwarded-For: 8.8.8.8" http://your-site.ipipp.com/test

观察日志会发现:如果请求直接到达Nginx(直连IP不在可信列表内),XFF中的8.8.8.8不会被采用,$remote_addr仍是你的真实出口IP,伪造失败;如果请求经过可信的CDN回源,$remote_addr则是CDN追加的真实用户IP。这正是realip模块的安全价值所在。

还有一种常见做法是让最外层代理统一改写XFF为单一真实IP,或者传递proxy_set_header X-Real-IP $remote_addr;,源站直接读取X-Real-IP。这种方式实现简单,但要求最外层代理自身做好清洗,否则同样存在伪造风险,适合架构完全自主可控的场景。

四、常见踩坑点与排查思路

第一个坑是可信网段遗漏。随着基础架构扩展,新增了SLB网段或容器网段却忘记更新set_real_ip_from,导致这部分流量日志里显示的是代理IP。建议把可信列表集中维护,并定期与运维的网段清单核对。第二个坑是递归开关与架构不匹配:多层代理却关闭递归,取到的是CDN节点IP;单层代理却开启递归且把公网段误加进可信列表,会让攻击者的伪造IP直接生效。

第三个坑是忽略了对内网健康检查流量的处理,负载均衡的健康探测请求没有XFF头,日志中会出现大量内网IP,可以通过日志条件过滤或在location级别单独处理。第四个坑是后续应用层未同步:Nginx还原了IP之后,如果通过proxy_pass转发给后端,默认传递的仍然是Nginx自己追加的XFF,需确认后端框架(如Spring的ForwardedHeaderFilter、Express的trust proxy)也正确配置,避免各层记录不一致。

排查时可按三步走:先用curl -v确认到达源站的请求头内容;再看日志中xff字段与tcp_peer字段的对应关系是否符合预期;最后逐步核对set_real_ip_from列表是否覆盖所有真实链路。掌握这套方法后,无论流量经过几层代理,都能在Nginx日志中稳定拿到可信的真实客户端IP。

Nginx日志X-Forwarded-Forreal_ip修改时间:2026-08-31 18:08:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。