白名单ip通过geo设为0,map将其映射为空key,使limit_req_zone跳过限流;非白名单则用$binary_remote_addr限流。geo与map须置于http块顶层,注意真实ip获取和ipv6/cidr支持。

用 map 指令配合 limit_req 实现白名单不限流,核心思路是:让白名单 IP 对应的限流 key 为空字符串,而 limit_req_zone 遇到空 key 会直接跳过限制逻辑。
白名单变量用 geo 定义
geo 指令适合做 IP 判断,它能根据客户端真实 IP($remote_addr)生成一个标记变量。推荐写法:
- 默认值设为 1,表示“需要限流”
- 把白名单 IP 或网段显式赋值为 0,表示“豁免限流”
例如:
geo $white_list {default 1;
192.168.5.100 0;
10.20.0.0/16 0;
2001:db8::/32 0;
}
用 map 把白名单映射为空 key
map 负责把 $white_list 的值转成限流用的 key:
- 当
$white_list == 0(白名单),映射为 空字符串 - 当
$white_list == 1(非白名单),映射为$binary_remote_addr(用于区分普通用户)
配置示例:
map $white_list $limit_key {0 "";
1 $binary_remote_addr;
}
定义并应用限流区域
在 http 块中定义限流 zone,key 使用上面生成的 $limit_key:
在需要保护的 location 中启用:
location /api/ {limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
注意:limit_req_zone 对空 key 不做任何计数或拒绝,所以白名单请求完全绕过限流。
关键细节提醒
-
$binary_remote_addr比$remote_addr更省内存,IPv4 固定占 4 字节 - 如果用了代理(如 CDN、LB),需确保
$remote_addr是真实客户端 IP;否则要配合real_ip_header和set_real_ip_from修正 -
geo和map必须放在http块顶层,不能嵌套在server或location内 - 白名单支持 CIDR 表示法(如
192.168.1.0/24),也支持 IPv6











