多级 nginx 代理链中 x-forwarded-for 需逐层追加 ip 而非覆盖,应使用 $proxy_add_x_forwarded_for 而非 $remote_addr,并配合 proxy_set_header 正确拼接;需确保上游透传该头,且最外层代理须校验可信来源以保障安全。

在多级 Nginx 代理链中,X-Forwarded-For 字段需逐层追加客户端真实 IP 和各中间代理的 IP,而不是简单覆盖。关键在于使用 $remote_addr 而非 $proxy_add_x_forwarded_for 的默认行为,并配合 proxy_set_header 正确拼接。
理解 X-Forwarded-For 的拼接逻辑
X-Forwarded-For 是一个逗号分隔的 IP 列表,最左边是原始客户端 IP,后续是各级代理的 IP(按请求经过顺序追加)。Nginx 默认的 $proxy_add_x_forwarded_for 变量会自动将 $remote_addr 追加到上游传来的 X-Forwarded-For 值末尾(若存在),这正是多级链所需的逻辑 —— 但前提是上游确实传递了该头,且本级未错误覆盖。
配置代理时正确设置请求头
在每级 Nginx 的 location 或 server 块中,使用以下指令:
-
必须启用:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -
禁用覆盖:不要写成
proxy_set_header X-Forwarded-For $remote_addr;,否则会丢弃上游已有的 IP 链 - 确保传递:上游代理必须已设置并透传该头;若上游是其他服务(如 HAProxy、Cloudflare),需确认其是否保留并转发该字段
验证多级链是否生效
可在后端应用(如 Python Flask、Node.js)中打印接收到的 X-Forwarded-For 头内容。例如,请求路径为「用户 → CDN → Nginx A → Nginx B → 应用」,理想值类似:203.0.113.45, 198.51.100.2, 192.0.2.10
其中 203.0.113.45 是真实客户端 IP,198.51.100.2 是 CDN 出口 IP,192.0.2.10 是 Nginx A 的出口 IP(即 Nginx B 的 $remote_addr)。
安全注意事项
不可直接信任任意 X-Forwarded-For 值,尤其来自公网的请求。应在最外层代理(如边界 Nginx)做如下处理:
- 只允许可信内部网段的代理追加该头,用
set_real_ip_from+real_ip_header X-Forwarded-For提取真实客户端 IP - 对非可信来源,可清空或重置该头:
proxy_set_header X-Forwarded-For "";或用map规则过滤 - 避免后端直接使用未校验的
X-Forwarded-For做访问控制或日志记录











