要让后端获取真实客户端IP,必须同时完成三件事:Nginx透传X-Real-IP/X-Forwarded-For/X-Forwarded-Proto/Host头、启用realip模块并配置可信代理源与real_ip_header、后端显式读取对应header而非REMOTE_ADDR。

要在 Nginx 反向代理中让后端服务拿到真实的客户端 IP,不能只靠加一两个 header——必须同时完成三件事:Nginx 主动透传、Nginx 自身识别并校验真实 IP、后端代码主动读取对应字段。漏掉任何一环,后端看到的就还是 127.0.0.1 或内网地址。
在 proxy_pass 前设置关键请求头
这些 header 必须写在 location 块里,且紧邻 proxy_pass 指令之前:
-
X-Real-IP:设为
$remote_addr,表示当前连接的直接上游 IP(单层代理时即用户真实 IP) -
X-Forwarded-For:用
$proxy_add_x_forwarded_for,它会自动把当前$remote_addr追加到已有值末尾,保留完整链路(如:1.2.3.4, 192.168.1.10) -
X-Forwarded-Proto:设为
$scheme,透传原始协议(http/https),避免后端误判 HTTPS 状态 -
Host:设为
$host,确保后端能正确解析域名和路由
启用 realip 模块并限定可信代理源
仅发 header 是不安全的——攻击者可伪造 X-Forwarded-For: 1.1.1.1。Nginx 必须知道哪些上游是可信的,才信任它们传来的头信息:
- 确认模块已编译启用:
nginx -V | grep http_realip_module(若无,需重新编译加--with-http_realip_module) - 在
http或server块中配置可信 IP 段,例如:set_real_ip_from 10.0.0.0/8;set_real_ip_from 192.168.0.0/16;set_real_ip_from 203.208.60.1; - 指定从哪个 header 提取真实 IP:
real_ip_header X-Real-IP;(推荐)或real_ip_header X-Forwarded-For; - 开启递归解析:
real_ip_recursive on;,Nginx 会从右往左剔除已知代理 IP,最终把第一个非代理 IP 赋给$remote_addr
后端应用必须显式读取 header,而非 REMOTE_ADDR
Nginx 设置只是“发出去”,后端框架默认仍读 REMOTE_ADDR(即 Nginx 的 IP)。必须改用 header 解析逻辑:
-
Java Spring Boot:在
application.properties中启用 RemoteIpValve:server.tomcat.remote-ip-header=x-real-ipserver.tomcat.protocol-header=x-forwarded-proto -
Python Flask:使用
ProxyFix中间件,明确指定可信代理数量或 IP 列表 -
Node.js Express:调用
app.set('trust proxy', true),并确保 Nginx 已透传X-Forwarded-For和X-Forwarded-Proto -
通用建议:优先读
HTTP_X_REAL_IP(经 realip 校验),其次解析HTTP_X_FORWARDED_FOR中最左的非私有 IP,最后 fallback 到REMOTE_ADDR
多级代理场景下的注意事项
如果请求经过 CDN、WAF 或多个 Nginx 节点,X-Forwarded-For 会变成类似 客户端IP, CDN出口, WAF出口, Nginx-A出口 的格式:
- 每一级代理都必须设置:
proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 最末端 Nginx 的
set_real_ip_from必须覆盖所有中间代理的出口 IP 段 - 不要直接取
X-Forwarded-For最右或最左的值——必须结合real_ip_recursive on和可信源白名单来解析


















