Nginx 限速需用 limit_req_module 配漏桶算法,http 块定义 zone、$binary_remote_addr 作 key、合理设 rate/burst/nodelay,并避错配与绕过。

在 Nginx 中限制单个 IP 的访问速率,核心是使用 ngx_http_limit_req_module 模块,配合漏桶算法实现按 IP 统计并控制请求频次。关键不在“能不能限”,而在于“限得准不准、绕不绕得过、配得稳不稳”。
必须在 http 块中定义限速区域
这是生效前提,漏掉会报错或完全不生效:
- 用 $binary_remote_addr 作为 key:比 $remote_addr 更省内存(IPv4 固定 4 字节),且能穿透简单代理(需配合
real_ip模块) -
zone=name:size:例如
zone=ip_rate:10m,表示建一个叫 ip_rate、大小 10MB 的共享内存区,所有 worker 进程共用 -
rate=xxr/s 或 xxr/m:如
rate=10r/m(每分钟 10 次)更适合防爆破;rate=1r/s适合强实时接口
在精确匹配的 location 中启用限速
避免宽泛匹配误伤正常路径,也防止被绕过:
- 用 = /path 严格匹配(如
location =/api/login),而不是location /api/ -
burst 设合理缓冲值:比如
burst=5允许短时手抖多点几次,但不纵容持续高频 - 加 nodelay:突发超限请求不排队,立即返回 429,防攻击者占满队列耗尽资源
- 配 limit_req_status 429:返回标准状态码,不暴露后端细节
避开常见失效写法
这些配置看似合理,实际等于没限:
- ❌ 把
limit_req写在if块里 —— Nginx 不支持,静默忽略 - ❌ 用
$remote_addr且未配置real_ip—— 反向代理下全站被限成同一个 IP - ❌
burst=100配rate=1r/s—— 等于允许每 100 秒集中打 100 次,正中暴力破解下怀 - ❌ 忘记白名单 —— 内网运维、健康检查探针应豁免,可用
geo + map动态控制
建议搭配使用的增强项
单靠限速不够全面,组合才更健壮:
- 加 limit_conn 控并发连接数:比如
limit_conn_zone $binary_remote_addr zone=ip_conn:5m;+limit_conn ip_conn 3;,防多线程绕过 - 自定义 429 响应体:用
error_page 429 @rate_limited;+location @rate_limited { ... }返回简洁 JSON,隐藏技术栈 - 日志中标记限速行为:在 log_format 中加入
$limit或$limit_rate变量,便于审计分析











