nginx白名单免限流的核心原理是:通过map指令将白名单ip映射为空字符串,使limit_req跳过对其限流;非白名单ip则按$remote_addr正常限速。

Nginx 使用 map 指令结合白名单实现“免限流”是一种轻量、高效的方式,核心思路是:**为白名单 IP 设置一个特殊的限流键(如空字符串或固定值),使其不参与 limit_req 的限制逻辑**。因为 Nginx 的 limit_req 只对非空且非“全相同”的键生效,若键为空或恒定不变(如 "0"),再配合恰当的 zone 配置,就能跳过限速。
白名单免限流的核心原理
map 指令用于根据客户端 IP 动态生成一个变量值;limit_req 则依据该变量值做哈希分桶限流。关键点在于:
- 若
map将白名单 IP 映射为 空字符串(""),Nginx 默认会跳过对该请求的限流检查(官方行为:key 为空时 limit_req 不生效) - 若映射为一个固定值(如 "whitelist"),则所有白名单请求都共享同一个 key,只要 zone 足够大(例如 rate=1000r/s),实际等效于不限流
- 推荐用空字符串方式,更简洁、无资源占用风险
配置示例:基于空字符串的白名单免限流
在 http 块中定义:
map $remote_addr $limit_key {
default $remote_addr; # 默认:按真实 IP 限流
192.168.1.100 ""; # 白名单 IP → 空字符串 → 免限流
2001:db8::1 ""; # 支持 IPv6
10.0.0.0/8 ""; # 支持 CIDR(需 Nginx ≥ 1.19.0)
}
然后在 server 或 location 中启用限流:
limit_req_zone $limit_key zone=api:10m rate=5r/s;
<p>server {
location /api/ {
limit_req zone=api burst=10 nodelay;
proxy_pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a>;
}
}</p>
✅ 效果:白名单 IP 的请求 key 为空,limit_req 直接跳过;其他 IP 正常按 5r/s 限流。
注意事项与常见问题
-
CIDR 匹配需版本支持:Nginx 1.19.0+ 才原生支持
map中写10.0.0.0/8这类网段;旧版本需用 geo 指令替代(见下条) -
geo 更适合复杂网段白名单:若需兼容老版本或大量网段,建议改用
geo+map组合(geo 输出 0/1,map 再转为空字符串) - 避免 key 冲突:不要把非白名单 IP 映射成相同非空字符串(如全设为 "common"),否则会导致不同用户共用 quota,引发误放行
-
测试是否生效:用 curl -H "Host: example.com" http://127.0.0.1/api/test,并检查响应头是否有
X-RateLimit-Remaining(需自定义日志或 Lua 辅助)或直接看 error_log 中的限流记录
补充:兼容老版本的 geo + map 写法
适用于 Nginx
geo $white_ip {
default 0;
192.168.1.100 1;
10.0.0.0/8 1;
}
<p>map $white_ip $limit_key {
1 "";
0 $remote_addr;
}</p>
后续 limit_req_zone 和 limit_req 配置保持不变即可。











