构建透明多层反向代理链路的关键是保留原始客户端IP完整路径:每层需追加(而非覆盖)$remote_addr到X-Forwarded-For,配合set_real_ip_from限定可信代理段,并由后端优先解析X-Real-IP。

要构建透明的多层反向代理链路,关键不是简单地覆盖 X-Forwarded-For,而是**保留原始客户端 IP 的完整路径,并确保每一层都正确追加、不篡改、不伪造**。Nginx 默认的 proxy_set_header X-Forwarded-For $remote_addr; 会覆盖上游传来的值,破坏链路透明性,必须调整。
正确拼接 X-Forwarded-For 而非覆盖
每层代理应将上一层传来的 X-Forwarded-For 值原样保留,并在末尾追加当前层的直连客户端 IP(即 $remote_addr)。Nginx 不支持直接字符串拼接变量,需用 map 指令构造安全的追加逻辑:
map $http_x_forwarded_for $xff_with_remote {
"" $remote_addr;
default "$http_x_forwarded_for, $remote_addr";
}
<p>server {
location / {
proxy_set_header X-Forwarded-For $xff_with_remote;
proxy_pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a>;
}
}</p>这样:第一层收到客户端请求(无 XFF 头)→ 写入 X-Forwarded-For: A;第二层收到时已有 X-Forwarded-For: A → 追加为 A, B;第三层收到 A, B → 变成 A, B, C,形成可追溯的 IP 链。
严格限制可信代理段,防止头伪造
仅当请求来自已知可信代理(如内网 LB、前置 CDN)时,才信任并继承其 X-Forwarded-For。否则一律以 $remote_addr 为准,避免外部恶意注入:
- 用
set_real_ip_from明确声明可信代理网段(如10.0.0.0/8、172.16.0.0/12) - 启用
real_ip_header X-Forwarded-For;和real_ip_recursive on; - 之后
$remote_addr就会自动解析为真实客户端 IP,$http_x_forwarded_for也只取自可信来源
未匹配可信段的请求,Nginx 会忽略其 XFF 头,从源头切断伪造可能。
后端服务需按规范解析 XFF 链
透明链路的价值最终由后端兑现。后端不能只取 XFF 第一个 IP(易被伪造),也不能盲目取最后一个(是最后一跳代理 IP):
- 应结合
X-Real-IP(若 Nginx 已用 real_ip_module 设置)或remote_addr(经 real_ip_module 修正后)作为最可信源 - 若必须依赖 XFF,应根据本层“可信代理数量”截取倒数第 N 个:例如你有 2 层可信代理,则取 XFF 中倒数第 3 个 IP(即
A, B, C中的 A) - 推荐统一使用
X-Real-IP—— 它由 Nginx 在 real_ip_module 处理后生成,天然可靠
可选:添加 X-Forwarded-By 或自定义链路标识
为便于调试和审计,可在每层追加标识自身角色:
proxy_set_header X-Forwarded-By "nginx-lb-v2"; # 或追加到 X-Forwarded-For(需注意标准兼容性) proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $remote_addr (lb-v2)";
这类非标准扩展不参与 IP 解析,但能快速定位某次请求经过了哪些代理节点,对排查超时、路由异常非常实用。











