HTTPS下透传真实客户端IP的关键在于代理链的头传递、可信校验与后端解析,而非协议本身;前端Nginx需设置X-Real-IP、X-Forwarded-For等头,后端Nginx须启用realip模块并配置可信源与取值头,应用层需主动读取经校验的X-Real-IP。

HTTPS 下传递真实客户端 IP 和 HTTP 场景逻辑一致,关键不在协议本身,而在代理链是否完整配置了头传递、可信校验与后端解析。只要 Nginx 是 HTTPS 入口(即 SSL 终结在 Nginx),后续到后端的通信可以是 HTTP 或 HTTPS,真实 IP 的透传机制不变。
前端 Nginx(SSL 终结点)必须设置标准转发头
即使启用了 HTTPS,Nginx 仍需在 location 块中显式设置以下头字段,确保信息不丢失:
-
X-Real-IP:设为
$remote_addr,表示直连 Nginx 的客户端或上一级可信代理 IP -
X-Forwarded-For:用
$proxy_add_x_forwarded_for,自动追加当前连接源 IP 到已有链路末尾,保留多跳路径 -
X-Forwarded-Proto:设为
$scheme(值为https),让后端知道原始请求是加密的,避免重定向循环或混合内容警告 - X-Forwarded-Host 和 X-Forwarded-Port:可选,便于后端生成正确 URL(如跳转链接、API 回调地址)
后端 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_recursive on;,Nginx 会从右往左剔除已知代理 IP,最终把最左边的非代理 IP 赋给$remote_addr
后端应用要主动读取经校验的真实 IP
Nginx 修改了 $remote_addr,但大多数框架默认仍读 REMOTE_ADDR(即 Nginx 自身 IP)。必须显式切换信任来源:
- Java Spring Boot:启用
server.forward-headers-strategy=framework,并在嵌入式 Tomcat 中设置setRemoteIpHeader("X-Real-IP") - Python Flask:使用
ProxyFix(app, x_for=1),其中x_for表示可信代理层数;更推荐用trusted_hosts显式指定前端 Nginx 域名/IP - Node.js Express:
app.set("trust proxy", true)后,req.ip会自动解析X-Forwarded-For;若已配 realip,优先读req.headers["x-real-ip"] - 通用原则:优先取
HTTP_X_REAL_IP(经 realip 模块校验过),其次解析HTTP_X_FORWARDED_FOR中第一个公网非私有 IP,最后才 fallback 到REMOTE_ADDR
HTTPS 多级代理(如 CDN + Nginx)需逐跳配置
若请求先经过 HTTPS CDN(如 Cloudflare、阿里云全站加速),再进你的 Nginx:
- CDN 必须开启“传递真实 IP”功能,并将客户端 IP 写入
X-Forwarded-For或Cf-Connecting-IP等头(不同厂商命名不同) - 你的前端 Nginx 要识别 CDN 的出口 IP 段,加入
set_real_ip_from;同时把 CDN 提供的头(如Cf-Connecting-IP)映射为X-Real-IP,再继续向后传递 - 例如:
map $http_cf_connecting_ip $realip { default $http_cf_connecting_ip; "" $remote_addr; } proxy_set_header X-Real-IP $realip; - 后端 Nginx 的
real_ip_header保持为X-Real-IP即可,无需感知 CDN 头名差异


















