关键在于可信链路识别+X-Forwarded-For全链路透传(首层用$remote_addr初始化,后续用$proxy_add_x_forwarded_for追加)+realip模块校验(set_real_ip_from指定可信代理、real_ip_header X-Forwarded-For、real_ip_recursive on)+后端适配透传头。

要在 Nginx 多级代理链中准确把真实客户端 IP 传到后端应用,关键不是“层层加头”,而是建立一条可信、可验证、不中断的传递路径。漏掉任一环节——比如某层没透传 X-Forwarded-For,或最后入口没启用 realip 校验——IP 就会失真。
每层代理必须透传 X-Forwarded-For
这是全链路 IP 追踪的基础。所有中间 Nginx(CDN、WAF、LB、网关)都需确保该头完整延续:
- 首层代理(直连公网或 CDN)用
proxy_set_header X-Forwarded-For $remote_addr;初始化,写入用户真实 IP - 后续每一层统一使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;——它会自动在已有值末尾追加本层看到的$remote_addr,形成类似1.1.1.1, 10.0.0.5, 10.0.0.6的格式 - 禁止清空、覆盖、手动拼接 X-Forwarded-For;任何一层缺失,链路即断裂
最后一层 Nginx 必须启用 realip 模块校验
仅靠读 X-Forwarded-For 是不安全的,攻击者可伪造。必须由最终接入的 Nginx 完成可信剥离:
- 确认编译时已启用
--with-http_realip_module - 在 http/server/location 块中配置可信代理段:
set_real_ip_from 10.0.0.0/8;set_real_ip_from 172.16.0.0/12;set_real_ip_from 192.168.0.0/16;set_real_ip_from 173.245.48.0/20;(Cloudflare 回源段)
(按实际代理出口 IP 精确填写,不建议用宽泛范围) - 指定解析来源:
real_ip_header X-Forwarded-For; - 开启递归解析:
real_ip_recursive on;—— Nginx 将从右往左跳过所有可信 IP,取第一个非可信地址作为真实客户端 IP,并自动更新$remote_addr
后端应读取经 realip 修正后的值
应用代码无需再解析 X-Forwarded-For 字符串,直接使用已校验的结果:
- 优先读
X-Real-IP(由 Nginx 注入,等价于修正后的$remote_addr) - 若框架支持,也可直接用
request.getRemoteAddr()(PHP 的$_SERVER['REMOTE_ADDR']、Java 的HttpServletRequest.getRemoteAddr()),前提是 realip 已生效 - 禁用“取 X-Forwarded-For 第一个 IP”的简单写法,否则可能拿到 CDN 或中间代理 IP
配套关键头不能少
除 IP 外,其他头也影响路由、日志和安全判断:
-
proxy_set_header Host $http_host;—— 保留原始 Host,避免后端因域名变化出错 -
proxy_set_header X-Real-IP $remote_addr;—— 此处的$remote_addr是上一级代理出口 IP,用于中间调试,但后端不应依赖它 -
proxy_http_version 1.1;和proxy_set_header Connection '';—— 避免 HTTP/1.0 连接复用问题


















