limit_req 是 Nginx 内置模块,适合在网关层对特定 URI 或 IP 做请求频率限制,是防御 CC 攻击的基础手段之一,但配置不当容易误伤正常用户。
先说结论:limit_req 能有效限制高频请求,但必须区分业务场景设置速率,且务必配置管理白名单。
- 先判断:确认攻击特征是针对特定接口还是全站,以及正常用户的请求频率。
- 优先做:在 http 块定义限速区域,配合 geo 模块设置 IP 白名单。
- 再验证:使用批量请求脚本测试,确认是否触发 503 且未误伤白名单。
- 留后路:修改配置前备份,确保能快速回滚。
安全配置示例(含白名单)
以下配置片段可直接参考,需放入 nginx.conf 对应位置。注意 rate 参数需根据业务调整,此处示例为 10r/s,避免直接复制 1r/s 导致静态资源加载失败。
http {
# 定义白名单变量,白名单 IP 的 key 为空,共享全局桶或不限制
geo $limit_key {
default $binary_remote_addr;
192.168.1.0/24 ""; # 替换为你的管理网段
10.0.0.5 ""; # 替换为你的管理 IP
}
# 使用变量作为 key,白名单 IP 因 key 为空不受单个 IP 限制
limit_req_zone $limit_key zone=one:10m rate=10r/s;
}
server {
location / {
# burst 允许突发,nodelay 超出部分直接拒绝
limit_req zone=one burst=20 nodelay;
limit_req_status 503;
}
# 特定 API 接口可单独设置更严格的限制
location /api/login {
limit_req zone=one rate=1r/s burst=5 nodelay;
}
}
不同业务场景参数推荐
- 普通网页(HTML/CSS/JS):rate=10r/s ~ 50r/s,burst=20~50。页面加载并发请求多,过严会导致样式丢失。
- 通用 API 接口:rate=5r/s ~ 10r/s,burst=5~10。防止脚本高频调用。
- 敏感接口(登录/短信):rate=1r/s ~ 2r/s,burst=3。需严格限制,防止爆破。
- 静态资源(图片/视频):建议不限速或通过 CDN 防护,Nginx 限速可能影响加载速度。
怎么验证是否生效
单次 curl 请求无法触发限速,需使用脚本模拟高频请求。以下命令发送 20 个请求,观察是否出现 503 状态码:
for i in {1..20}; do curl -I -o /dev/null -s -w "%{http_code}\n" http://your_domain.com; done
同时查看 Nginx 错误日志,通常位于 /var/log/nginx/error.log,搜索 limiting requests 关键字确认是否触发限速:
grep "limiting requests" /var/log/nginx/error.log
紧急故障回滚方案
配置生效后若发现正常用户无法访问,需立即执行以下操作:
- 恢复备份:cp nginx.conf.bak nginx.conf
- 或临时注释:在 limit_req 指令前添加 # 注释符号。
- 检查语法:nginx -t
- 重载配置:nginx -s reload
注意:生产环境修改配置前,务必执行 cp nginx.conf nginx.conf.bak 备份。
常见坑与风险
- NAT 环境误伤:如果多个用户共用同一个出口 IP(如公司网络、移动网络),限速过严会导致正常用户无法访问。建议结合 Cookie 或 JS 挑战进行二次验证。
- burst 设置过小:正常页面加载可能包含多个并发请求,burst 太小会导致页面资源加载失败。
- 忘记定义 zone:limit_req 引用了未定义的 zone 会导致 Nginx 启动失败。
- 把自己锁在门外:未配置白名单可能导致管理员 IP 被限制,无法登录服务器修复。务必在 geo 模块中添加管理 IP。
参考来源
- Nginx 官方文档:limit_req_module - https://nginx.org/en/docs/http/ngx_http_limit_req_module.html