核心是在nginx层完成可信代理校验与真实ip提取,通过set_real_ip_from限定可信ip段、real_ip_header指定来源头、real_ip_recursive开启递归解析,再透传$remote_addr给后端,后端须信任该值而非原始请求头。

要让后端只接受来自信任代理的请求头(比如 X-Forwarded-For 或 X-Real-IP),核心不是“后端自己过滤”,而是**在 Nginx 层就完成可信校验与真实 IP 提取**,再把干净、可信的结果透传过去。否则后端直接读取原始 header,极易被伪造。
明确可信代理范围
用 set_real_ip_from 声明哪些 IP 或网段是可信的上游代理(如 CDN 回源 IP、负载均衡器、内网网关)。Nginx 只信任这些来源发来的转发头。
- 写法示例(推荐精确控制):
set_real_ip_from 10.0.0.0/8;<br>set_real_ip_from 172.16.0.0/12;<br>set_real_ip_from 192.168.0.0/16;<br>set_real_ip_from 203.208.60.1;
- 切勿使用
set_real_ip_from 0.0.0.0/0,这等于放弃校验,完全暴露于 IP 伪造风险 - 若部署在云环境,需查清 CDN 或 LB 的官方回源 IP 段(如阿里云全站加速、腾讯云 CDN 都有公开列表),填入此处
指定真实 IP 来源字段并启用递归解析
告诉 Nginx 从哪个 HTTP 头里提取真实客户端 IP,并支持多层代理链的清洗。
- 常用配置:
real_ip_header X-Forwarded-For;<br>real_ip_recursive on;
-
real_ip_recursive on表示:从X-Forwarded-For值中,从右往左逐个比对,剔除所有匹配set_real_ip_from的 IP,最终剩下最左边那个非代理 IP —— 即真实客户端 IP - 若上游统一用
X-Real-IP(如某些私有网关),则改用real_ip_header X-Real-IP
透传时只用可信后的变量
启用 real_ip_header 后,$remote_addr 就已变成真实客户端 IP。后续所有 proxy_set_header 都应基于它,而非原始不可信头。
- 正确写法:
proxy_set_header X-Real-IP $remote_addr;<br>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- 错误写法(绕过校验):
proxy_set_header X-Real-IP $http_x_real_ip;<br>proxy_set_header X-Forwarded-For $http_x_forwarded_for;
—— 这会把客户端可能伪造的值直接转发 - 同时建议加一句:
proxy_set_header X-Forwarded-Proto $scheme;,避免协议误判
后端配合:只读取 Nginx 提供的可信字段
Nginx 完成校验和赋值后,后端必须放弃 REMOTE_ADDR,转而信任 Nginx 设置的 header。
- Java(Spring Boot):
配置server.forward-headers-strategy=framework,并在反向代理配置中启用RemoteIpValve或使用HttpServletRequest.getRemoteAddr()前先检查X-Forwarded-For - Node.js(Express):
app.set('trust proxy', ['10.0.0.0/8', '192.168.0.0/16']);,之后req.ip自动返回清洗后的真实 IP - Python(Django):
设置USE_X_FORWARDED_HOST = True和SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),并确保ALLOWED_HOSTS包含代理 IP











