多级代理下需用 real_ip 模块提取可信 X-Forwarded-For 中的真实 IP,并以 $realip_remote_addr(或 fallback 到 $binary_remote_addr)作为 limit_req_zone 的 key,配合 set_real_ip_from 和 geo/map 实现精准限流,避免所有用户被误判为同一内网 IP。

在多级代理(如 CDN、SLB、WAF、Nginx 反向代理链)环境下,客户端真实 IP 通常被覆盖为上一跳代理的内网地址(如 10.x.x.x 或 172.x.x.x),直接用 $binary_remote_addr 限流会失效——所有用户被识别为同一个 IP,导致误限或漏限。解决核心是:**准确提取并信任可信代理链传递的原始客户端 IP,并以此作为限流 key**。
一、确认并配置可信代理头(X-Forwarded-For)
Nginx 默认不解析 X-Forwarded-For(XFF),需手动提取最左/最可信的原始 IP:
- 若你控制全部上游代理(如自建 SLB + CDN 配置了固定 header),可约定由最后一层可信代理写入
X-Real-IP,并在 Nginx 中直接使用:set $client_real_ip $http_x_real_ip; - 更常见的是依赖
X-Forwarded-For。但该 header 可被客户端伪造,必须结合set_real_ip_from指令声明可信代理网段,再启用real_ip_header X-Forwarded-For;,让 Nginx 自动剥离可信代理 IP,取最左未被污染的地址: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>real_ip_header X-Forwarded-For;<br>real_ip_recursive on;
- 验证是否生效:加日志
log_format main '$remote_addr — $realip_remote_addr — $http_x_forwarded_for';,观察$realip_remote_addr是否为真实公网 IP。
二、用真实 IP 做限流 key,避免共享内存误判
一旦 $realip_remote_addr 可靠,就用它替代 $binary_remote_addr 构建限流区域:
- 定义 zone 时改用
$realip_remote_addr(注意:该变量在 real_ip 模块启用后才可用):limit_req_zone $realip_remote_addr zone=perip:10m rate=5r/s; - 若部分请求无 XFF(如直连或恶意绕过代理),
$realip_remote_addr可能为空,建议 fallback 到$binary_remote_addr:map $realip_remote_addr $limit_key {<br> "" $binary_remote_addr;<br> default $realip_remote_addr;<br>}
再用limit_req_zone $limit_key zone=perip:10m rate=5r/s;
三、应对代理自身 IP 泛洪的补充策略
即使拿到真实 IP,CDN 节点或 SLB 若自身 IP 被高频调用(如健康检查、缓存回源),仍可能触发限流。可做分层防护:
- 对已知代理网段(如阿里云 SLB 的
100.64.0.0/10、Cloudflare 的 ASN 列表)单独放行或宽松限流:geo $is_trusted_proxy {<br> default 0;<br> 100.64.0.0/10 1;<br> 173.245.48.0/20 1;<br>}map $is_trusted_proxy $rate_limit {<br> 1 "100r/s";<br> 0 "5r/s";<br>}
再配合limit_req_zone $limit_key zone=perip:10m rate=$rate_limit; - 对特定路径(如
/health、/ping)跳过限流:location = /health {<br> limit_req off;<br> return 200 "OK";<br>}
四、验证与调试要点
上线前务必实测,重点检查:
- curl -H "X-Forwarded-For: 203.0.113.42" http://your-site/api —— 是否按
203.0.113.42限流,而非代理内网 IP - 连续发 6 次请求(超 5r/s),第 6 次是否返回
503 Service Temporarily Unavailable(默认行为) - 换一个真实 IP 再试,确认两者限流互不影响
- 查看
nginx -t和 error log,确认无invalid number of arguments in "limit_req_zone"或 real_ip 相关警告
不复杂但容易忽略:真实 IP 限流的前提是代理链可控且 header 可信。若 CDN 不支持透传或 WAF 强制清洗 XFF,就得考虑在应用层做二次限流,或要求上游提供带签名的用户标识(如 X-User-ID)作为限流维度。


















