https代理透传客户端真实ip的关键是三层协同:前端nginx显式设置x-real-ip等头,后端nginx用realip模块校验可信源并还原$remote_addr,后端应用主动读取x-real-ip而非remote_addr。

HTTPS代理下透传客户端真实IP,核心不是协议切换,而是确保代理链中每层都正确识别、校验并传递IP信息。SSL终结在Nginx时,后续通信用HTTP或HTTPS都不影响IP透传逻辑,关键在三步:前端Nginx设置头、后端Nginx校验可信源、后端应用读取经校验的头。
前端Nginx(SSL终结点)必须显式设置转发头
即使启用了HTTPS,Nginx默认不会自动添加X-Real-IP等头。需在location块中(proxy_pass之前)配置:
-
proxy_set_header X-Real-IP $remote_addr;—— 把当前连接IP设为真实IP;若前面有CDN或SLB,此值需先经set_real_ip_from修正 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 安全追加,不覆盖上游已有的IP链路 -
proxy_set_header X-Forwarded-Proto $scheme;—— 告知后端原始是https,避免跳转错乱或混合内容警告 - 可选:
proxy_set_header X-Forwarded-Host $host;和proxy_set_header X-Forwarded-Port $server_port;,便于后端生成正确URL
后端Nginx必须启用realip模块并限定可信源
仅靠header不可信,后端Nginx需用http_realip_module还原$remote_addr:
- 确认模块已启用:
nginx -V 2>&1 | grep -o http_realip_module - 在
http或server块中指定可信代理网段:set_real_ip_from 192.168.10.0/24;(填前端Nginx出口IP) - 指定取值头:
real_ip_header X-Real-IP;(推荐,比X-Forwarded-For更直接)或real_ip_header X-Forwarded-For; - 开启递归解析:
real_ip_recursive on;,Nginx会从右往左剔除可信代理IP,最终把最左边非代理IP赋给$remote_addr
后端应用必须主动读取X-Real-IP,不能依赖REMOTE_ADDR
Nginx修改了$remote_addr,但框架默认仍读自身连接IP(即Nginx内网地址)。必须显式切换信任来源:
-
Java Spring Boot:配置
server.forward-headers-strategy=framework,并在Tomcat中设setRemoteIpHeader("X-Real-IP") -
Python Flask:用
ProxyFix(app, x_for=1, trusted_hosts=["192.168.10.10"]),显式指定前端Nginx IP -
Node.js Express:
app.set("trust proxy", true)后,优先读req.headers["x-real-ip"]而非req.ip -
独立Tomcat:在
server.xml中添加<valve classname="org.apache.catalina.valves.RemoteIpValve"></valve>,默认从X-Forwarded-For取第一个IP
常见陷阱与验证要点
透传失败往往卡在细节:
- 没检查
set_real_ip_from是否覆盖了前端Nginx的实际出口IP(如云厂商SLB网段要查文档填准) - 把
proxy_set_header X-Forwarded-For $remote_addr;写成覆盖式,丢掉了上游CDN传来的原始IP - 后端日志或代码里还在用
request.getRemoteAddr()或request.remote_addr,没切到header读取 - 未验证:可在后端返回头中输出
X-Real-IP和X-Forwarded-For值,对比请求发起方真实IP











