必须前后端协同:nginx 配置 proxy_set_header x-real-ip $remote_addr 和 x-forwarded-for $proxy_add_x_forwarded_for,并在 spring boot 的 application.yml 中启用 server.tomcat.remote-ip-header=x-real-ip 及正确配置 internal-proxies 正则以信任可信代理。

要让 Spring Boot 正确拿到真实客户端 IP,Nginx 必须把 X-Real-IP 头可靠地传过去,而 Spring Boot 也得知道该信任并读取它——单靠加一行 header 不够,前后两端都要配合。
前端 Nginx 配置 X-Real-IP 透传
在 location 块中、proxy_pass 之前添加:
-
proxy_set_header X-Real-IP $remote_addr;:把当前连接的直接上游 IP(首层代理即用户真实 IP)写入该头 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:保留完整代理链路,便于多级场景排查 -
proxy_set_header X-Forwarded-Proto $scheme;:透传协议,避免 Spring Boot 误判 HTTPS
注意:$remote_addr 是 Nginx 收到请求时的源地址。如果 Nginx 前面还有 CDN 或负载均衡器,这个值就是那个代理的 IP,不是用户真实 IP——此时需结合 set_real_ip_from 和 real_ip_header 在 Nginx 内部先修正 $remote_addr,再透传。
后端 Spring Boot 主动解析 X-Real-IP
Spring Boot 默认只认 TCP 连接远端地址(即 Nginx 的 IP),必须显式启用对代理头的支持:
- 在
application.yml中配置:
tomcat:
remote-ip-header: X-Real-IP
protocol-header: X-Forwarded-Proto
internal-proxies: 127.0.0.1|192.168.d+.d+|10.d+.d+.d+|172.(1[6-9]|2[0-9]|3[0-1]).d+.d+
- 其中
internal-proxies是正则表达式,列出所有可信代理(如 Nginx 所在服务器的内网 IP 段),只有来自这些地址的请求,Spring Boot 才会信任X-Real-IP - 若用
application.properties,对应写法为:server.tomcat.remote-ip-header=X-Real-IPserver.tomcat.protocol-header=X-Forwarded-Protoserver.tomcat.internal-proxies=127\.0\.0\.1|192\.168\.\d+\.\d+|...
验证是否生效
最直接的方式是临时加个响应头看效果:
- 在 Nginx 的
location块里加:add_header X-Debug-Remote-Addr $remote_addr; - 重启 Nginx,访问接口,检查响应头中
X-Debug-Remote-Addr是否为公网 IP(而非 127.0.0.1 或内网地址) - 同时打印 Spring Boot 中
request.getHeader("X-Real-IP")的值,确认与预期一致 - 用
curl -H "X-Real-IP: 1.1.1.1" http://your-domain/测试:若返回 1.1.1.1,说明未限制可信源,存在伪造风险,需补全internal-proxies配置
多级代理时的关键点
如果请求路径是「用户 → CDN → WAF → Nginx → Spring Boot」,每级都必须:
- 设置
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(如 Cloudflare 回源段、WAF 内网出口等) - Spring Boot 的
internal-proxies只需匹配最后一跳 Nginx 的地址,不需包含 CDN/WAF











