敏感接口限流需在http块预定义limit_req_zone,location仅应用规则;支持ip、uri、api key等维度限流,并可叠加多层防护与白名单豁免。

敏感接口的频次限制不能靠 location 自身实现,而是用 location 来精准“选中”要保护的路径,再通过 limit_req 指令绑定预定义的限流规则。关键在两点:限流逻辑必须提前在 http 块中声明,location 只负责应用。
在 http 块中定义限流区域
限流依据和速率必须全局定义,不能写在 location 里:
- 按客户端 IP 限流(最常用):limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s; —— 使用 $binary_remote_addr 更省内存,且能正确识别真实 IP(配合 real_ip 模块时)
- 按请求路径限流(防暴力扫多个接口):limit_req_zone $uri zone=per_uri:10m rate=3r/s; —— 每个不同 URI 独立计数,适合 /admin/、/login 等路径
- 按 API key 限流(需后端透传):limit_req_zone $arg_apikey zone=apikey_limit:10m rate=10r/m; —— 提取 URL 参数中的 key,每分钟最多 10 次
在 location 中精准启用限流
location 的作用是“指哪打哪”,确保规则只作用于目标接口:
- 精确匹配登录接口:location = /api/v1/login { limit_req zone=api_limit burst=3 nodelay; }
- 前缀匹配管理路径:location ^~ /admin/ { limit_req zone=per_uri burst=5 nodelay; }
- 正则匹配敏感文件:location ~* ^/(wp-login\.php|\.env|\.git) { limit_req zone=api_limit burst=1 nodelay; }
- 关闭静态资源限流(避免误伤):location ~* \.(js|css|png|jpg)$ { limit_req off; }
增强防护的常见组合
单一层限流不够时,可叠加多维度控制:
- IP + 路径双限流:location /api/ { limit_req zone=ip_limit burst=10 nodelay; limit_req zone=per_uri burst=5 nodelay; } —— 任一触发即拒绝
- 配合连接数限制(防并发绕过):limit_conn ip_conn 3; 需先定义 limit_conn_zone $binary_remote_addr zone=ip_conn:5m;
- 返回标准状态码:limit_req_status 429; 替换默认 503,语义更清晰
- 白名单豁免内网或监控:geo $whitelist { default 0; 192.168.0.0/16 1; } map $whitelist $limit_key { 1 ""; 0 $binary_remote_addr; } limit_req_zone $limit_key zone=smart_limit:10m rate=5r/s;
验证与调试要点
上线后别只看配置,要确认是否真生效:
- 加日志字段:log_format main '$remote_addr - $request_time $status $limit'; —— $limit 显示命中哪个 zone
- 调高日志级别:limit_req_log_level warn;,error.log 中出现 “limiting requests” 即表示触发
- 用 curl 快速测试:for i in {1..12}; do curl -sI http://localhost/api/v1/login | head -1; sleep 0.2; done
- 注意 location 匹配优先级:= 最高,^~ 次之,正则最后;写成 location /api/ 可能误伤 /api-docs,应尽量精确











