网站被人恶意刷请求、某个接口被脚本疯狂调用、下载文件被人抢带宽——这些场景都需要 Nginx 限流限速来保护服务器。Nginx 是几乎所有网站最前面的一层,它自带的限流功能既高效又零成本:limit_req 限请求速率、limit_conn 限并发连接、limit_rate 限下载速度。这篇文章把 Nginx 限流限速的核心配置讲透,照着配就能让你的网站扛住恶意流量。
一、为什么需要 Nginx 限流
服务器资源是有限的,而恶意或异常的流量是无限的:
- CC 攻击:模拟正常用户大量请求,把 PHP/数据库打挂
- 接口刷量:登录接口被人无限尝试密码、短信接口被人刷爆
- 盗链下载:图片、文件被人直接引用,白白消耗带宽
- 爬虫失控:个别爬虫疯狂抓取,拖慢正常用户访问
在 Nginx 这一层限流,是最靠前、最省资源的防线,能在请求到达后端之前就把流量挡掉。
二、limit_req:限制请求速率(防 CC)
limit_req 基于漏桶算法,限制同一个 IP 每秒/每分钟的请求数。
基本配置:
# 在 http 块定义限流区域
http {
# 每个 IP 每 1 秒最多 5 个请求,超出部分进 burst 缓冲
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=5r/s;
server {
# 在需要限流的 location 使用
location / {
limit_req zone=req_zone burst=10 nodelay;
}
}
}
参数说明:
rate=5r/s:每个 IP 限速 5 次/秒burst=10:允许瞬时突发 10 个请求(排队缓冲)nodelay:缓冲的请求立即处理,不排队等待limit_req_status 429:超限时返回 429 状态码
登录接口单独限制(更严格,防止爆破):
location /login {
limit_req_zone $binary_remote_addr zone=login_zone:10m rate=1r/s;
limit_req zone=login_zone burst=3 nodelay;
}
这样每个 IP 登录接口 1 秒最多 1 次,能有效防止密码暴力破解。
三、limit_conn:限制并发连接
有些攻击不是频率高,而是同时建立大量连接挂起。limit_conn 限制单个 IP 的最大并发连接数。
http {
# 定义并发连接限制区域
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
server {
location / {
limit_conn conn_zone 10; # 每个 IP 最多 10 个并发连接
}
}
}
典型场景:图片服务器、下载服务器限制每个 IP 并发连接,防止被工具多线程拉爆带宽。
四、limit_rate:限制下载速度
limit_rate 限制单个连接的传输速率,用于防止个别用户独占带宽。
server {
# 限制每个连接下载速度 500KB/s
limit_rate 500k;
# 也可以对整个 location 限速
location /download/ {
limit_rate 1m; # 下载目录限制 1MB/s
limit_rate_after 10m; # 前 10MB 不限速,之后限速
}
}
limit_rate_after 很实用:先让用户以正常速度下载前 10MB,之后限速,既照顾体验又防占用带宽。
五、综合实战:一个防止 CC 的推荐配置
http {
# 请求速率限制
limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
# 并发连接限制
limit_conn_zone $binary_remote_addr zone=conn:10m;
server {
listen 80;
server_name example.com;
location / {
# 全局限频 + 限制并发
limit_req zone=req burst=20 nodelay;
limit_conn conn 10;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 后台管理接口单独严格限流
location ~ ^/admin/ {
limit_req zone=req burst=5 nodelay;
limit_conn conn 3;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}
}
}
六、常见问题与注意事项
Q1:限流误伤了正常用户怎么办?
把 burst 调大一些,让正常的小流量波动不会触发。也可以对已知的正常爬虫(百度、谷歌)放行。
Q2:怎么放行特定 IP 或屏蔽某些 IP?
# 用 geo 或 map 区分
geo $limit {
default 1;
192.168.1.0/24 0; # 内网不限流
你的IP 0; # 你自己不限流
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req:10m rate=10r/s;
当 $limit_key 为空时不会限流,这样就实现了"白名单不限流"。
Q3:限流返回 429 后,怎么让用户看到友好页面?
location / {
limit_req zone=req burst=20 nodelay;
error_page 429 /too_many.html;
}
location = /too_many.html {
root /var/www/html;
internal;
}
Q4:可以按 URL 而不是按 IP 限流吗?
可以,把 zone 的 key 改成 $request_uri 即可,但要注意多个用户会互相影响,更常用的是按 IP。
Q5:限流会影响 SEO 收录吗?
正常设置一般不会。搜索引擎爬虫频率不高,只要 rate 别设太低(别低于 1r/s)基本无影响。真被误限可以放行白名单。
七、验证限流是否生效
配置好后重载 Nginx:
nginx -t # 检查配置语法
nginx -s reload # 重载配置
用 ab(ApacheBench)压测验证:
ab -n 1000 -c 50 http://example.com/
# 观察 Nginx 日志中的 429 状态码
tail -f /var/log/nginx/access.log | grep 429
大量 429 说明限流正常生效,成功挡住了超出的请求。
总结
Nginx 限流限速是保护网站的第一道防线:limit_req 挡 CC 高频攻击、limit_conn 限并发连接、limit_rate 控下载带宽,配合白名单和 429 友好页面,一套配好就能让网站从容应对恶意流量。记住核心套路:定义 zone → 在 location 里启用 → 重载生效 → 压测验证。需要更强防护的话,可以再配合本站的 iptables 防火墙教程和 WAF 方案层层加固。
