nginx多级代理可靠传递真实ip的关键是每层明确“传什么、信谁”:统一用$proxy_add_x_forwarded_for透传x-forwarded-for,逐层配置set_real_ip_from声明可信上游,启用real_ip_recursive并读取$realip_remote_addr。

要让 Nginx 在多级代理链中可靠地传递和识别客户端真实信息,关键不是简单加几行 proxy_set_header,而是每层都明确“传什么”和“信谁”。配置错一层,X-Forwarded-For 就可能被伪造、真实 IP 就会丢失、后端日志链路就断掉。
必须逐层透传 X-Forwarded-For 并追加 IP
每一级 Nginx 都要延续代理链路,不能覆盖也不能跳过:
- 统一使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 它自动判断:上游已有 XFF 就追加当前$remote_addr,没有就只填$remote_addr - 禁用
proxy_set_header X-Forwarded-For $remote_addr这类覆盖写法,否则历史链路直接清空 - XFF 值格式应为
1.1.1.1, 2.2.2.2, 3.3.3.3,最左是原始客户端,最右是上一跳出口 IP
每层都要声明可信上游并修正真实 IP
仅靠 XFF 不安全,攻击者可伪造。Nginx 必须知道哪些上游是可信的,才能从 XFF 中剥离它们,还原出真实客户端 IP:
- 在每台 Nginx 的 location 或 server 块中,添加
set_real_ip_from 10.0.10.5;(填上一级代理的真实出口 IP 或网段) - 指定解析来源:
real_ip_header X-Forwarded-For; - 启用递归解析:
real_ip_recursive on;,确保多层嵌套时能正确剥掉所有可信代理 IP - 后端应读取
$realip_remote_addr(由 real_ip 模块修正后的变量),而不是直接解析 XFF 第一个值
补充关键头与唯一请求 ID
除了 IP 追踪,建议同步透传协议、主机名和全链路 ID:
-
proxy_set_header X-Real-IP $remote_addr;—— 供不支持 real_ip 模块的老服务快速取值 -
proxy_set_header X-Forwarded-Proto $scheme;和X-Forwarded-Host $host;—— 避免重定向跳转错误 - 启用
$request_id(Nginx 1.11.0+ 内置):proxy_set_header X-Request-ID $request_id;,并在 log_format 中记录,形成轻量级追踪起点
后端识别逻辑要匹配 Nginx 配置
前端链路配得再好,后端若读错字段,一切白搭:
- 不要直接取
request.headers['X-Forwarded-For']的第一个 IP —— 可能是伪造的私有地址(如 192.168.x.x) - 应跳过所有私有网段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.1),取第一个公网非私有 IP
- 更稳妥做法:Nginx 用
proxy_set_header X-Real-IP $realip_remote_addr;,后端直接读该头或框架封装好的request.client_ip











