nginx反向代理需配置proxy_set_header传递真实ip:用x-real-ip传可信客户端ip,x-forwarded-for记录完整链路;前置cdn时须配合set_real_ip_from和real_ip_header还原真实ip;后端需主动读取对应header并校验,避免伪造。

当 Nginx 作为反向代理时,后端服务(如 PHP、Node.js 或 Python 应用)默认拿到的是 Nginx 的本地 IP(如 127.0.0.1),而非用户真实 IP。要让后端获取真实客户端 IP,关键是在 server 块中合理使用 proxy_set_header,并配合可信代理配置。
设置 X-Real-IP 和 X-Forwarded-For
这两个请求头是传递真实 IP 的常用方式:
-
X-Real-IP:通常只填一个 IP,建议设为 Nginx 解析出的最可信客户端地址 -
X-Forwarded-For:用于记录完整转发链路,格式为X-Forwarded-For: client, proxy1, proxy2
在 server 块或 location 块中添加:
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
注意:$proxy_add_x_forwarded_for 会自动追加 $remote_addr 到原有 X-Forwarded-For 头(如果存在),避免覆盖上游代理已传的信息。
仅对可信代理信任并追加 IP
如果 Nginx 前面还有 CDN 或负载均衡(如阿里云 SLB、Cloudflare),$remote_addr 可能是该中间代理的 IP,而非真实用户 IP。此时需结合 set_real_ip_from 和 real_ip_header 提前还原真实 IP,再用于 proxy_set_header:
set_real_ip_from 192.168.0.0/16; # 你的可信内网段 set_real_ip_from 203.205.128.0/17; # 例如某 CDN 的 IP 段 real_ip_header X-Forwarded-For; real_ip_recursive on;
启用后,$remote_addr 和 $realip_remote_addr 就会变成还原后的用户真实 IP,后续 proxy_set_header X-Real-IP $remote_addr 才真正有效。
后端应用需主动读取对应 header
Nginx 只负责转发,后端必须明确从哪个 header 取值:
- PHP 中可用
$_SERVER['HTTP_X_REAL_IP']或$_SERVER['HTTP_X_FORWARDED_FOR'](注意校验和截取第一个) - Node.js(Express)需用
req.headers['x-real-ip']或req.ip(配合trust proxy设置) - Python(Django/Flask)需启用
SECURE_PROXY_SSL_HEADER或手动解析X-Forwarded-For
切勿直接信任 X-Forwarded-For 的原始值——它可能被客户端伪造,务必结合 set_real_ip_from 限定可信来源后再使用。
避免重复添加或覆盖 header
多个 proxy_set_header 指令会覆盖同名 header,且继承关系需留意:
- 定义在
http块的 header 会被所有 server 继承 - 若
server块里重写了X-Forwarded-For,就会覆盖http块里的设置 - 推荐统一在
location块中显式设置,避免隐式继承导致行为不一致
常见错误写法:proxy_set_header X-Forwarded-For $remote_addr; —— 这会丢弃原有转发链,应优先用 $proxy_add_x_forwarded_for。











