跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何通过 proxy_set_header X-Real-IP 确保多层代理后依然能获取真实源 IP

关键在于首层代理设X-Real-IP为$remote_addr,中间层透传不覆盖,后端优先信X-Real-IP但需校验;更稳妥是Nginx用realip模块归一化REMOTE_ADDR。 关键不在“设不设”X-Real-IP,而在于“谁来设、怎么设、设给谁看”。单纯在某一层Nginx里写一句
proxy_set_header X-Real-IP $remote_addr
,反而会覆盖掉上游传来的真正客户端IP,导致后端拿到的是中间代理的IP。 首层代理必须用 $remote_addr 设置 X-Real-IP 只有最靠近客户端的那一层代理(比如CDN或WAF)能直接看到真实IP。它应将自身连接的客户端地址写入X-Real-IP:
proxy_set_header X-Real-IP $remote_addr;
同时务必设置
proxy_set_header X-Forwarded-For $remote_addr;
或
$proxy_add_x_forwarded_for
这一步不可被后续代理覆盖或重写 中间层代理必须透传而非重写 X-Real-IP 第二层及之后的Nginx(如业务入口层)不能用自己的 $remote_addr 覆盖X-Real-IP,否则就丢了源头信息: 正确做法是:只传递上游已有的值:
proxy_set_header X-Real-IP $http_x_real_ip;
同时继续追加自身IP到X-Forwarded-For:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
若上游没传X-Real-IP,该字段为空,后端需降级使用X-Forwarded-For首段 后端服务应优先信任 X-Real-IP,但需校验来源可信性 应用代码中直接读
X-Real-IP
最简洁,但前提是整个链路可控: PHP:
$_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']
Python:
request.headers.get('X-Real-IP') or request.remote_addr
注意:如果请求可能绕过首层代理(如内网直连),X-Real-IP 可能被伪造,建议结合白名单或 realip 模块做服务端校验 更稳妥的做法:Nginx 层统一提取并覆盖 $remote_addr 与其依赖后端解析,不如让Nginx自己完成“归一化”: 启用
http_realip_module
配置可信代理段:
set_real_ip_from 10.0.0.0/8;
、
set_real_ip_from 192.168.0.0/16;
指定头字段:
real_ip_header X-Real-IP;
或
real_ip_header X-Forwarded-For;
开启递归:
real_ip_recursive on;
之后所有日志和FastCGI变量(如
fastcgi_param REMOTE_ADDR $remote_addr
)自动使用真实IP

相关文章