拒绝 CC 攻击:Nginx 频率限制与连接数压制实战
主机选(zhujixuan.com)的 Linux 教程里,经常有人问:网站没被 DDoS,但 CPU 突然飙到 100%,访问日志里全是同一个 IP 的重复请求。不用怀疑,这是 CC 攻击的低级变种。别慌,Nginx 自带的频率限制和连接数压制模块,就能直接把它挡回去。下面直接说怎么配,配完马上生效。

为什么 Nginx 能挡住大部分 CC 攻击?
CC 攻击的本质是模拟正常请求,但频率远超人类。Nginx 的 `ngx_http_limit_req_module` 和 `ngx_http_limit_conn_module` 就是干这个的:一个限制每秒请求次数,一个限制同一 IP 的并发连接数。两者配合,能把 90% 的 CC 攻击拦在业务层之外。
限制单个 IP 的请求频率:`limit_req_zone`
打开 Nginx 主配置文件(通常是 `/etc/nginx/nginx.conf`),在 `http` 块里加上:
nginx
定义共享内存区域,存储客户端 IP 的请求状态
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
• `$binary_remote_addr`:用客户端 IP 作为 key,二进制格式更省内存。
• `zone=one:10m`:分配 10MB 共享内存,大约能存 16 万个 IP 状态。
• `rate=10r/s`:每个 IP 每秒最多 10 个请求。具体值根据你的业务调,API 接口可以放宽到 30r/s。
然后在需要保护的 `server` 或 `location` 块里引用:
nginx
location / {
limit_req zone=one burst=20 nodelay;
}
• `burst=20`:允许瞬间超出 rate 的请求数,超出后排队处理。
• `nodelay`:排队的请求不延迟,直接拒绝超出的部分。不加 `nodelay` 的话,超出的请求会被延迟处理,容易积压。
老鸟叮嘱:别把 `rate` 设得太低,比如 1r/s,否则你自己的正常用户刷新一下页面就被拒绝了。先观察业务日志,算一下平均 QPS 再定。
限制单个 IP 的并发连接数:`limit_conn_zone`
同样是 `http` 块里加:
nginx
定义共享内存区域,存储客户端 IP 的连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;
然后在 `location` 块里限制:
nginx
location / {
limit_conn addr 20;
}
• `addr` 对应上面定义的 zone 名称。
• `20` 表示每个 IP 最多同时建立 20 个连接。静态资源可以放宽到 50,动态接口建议 10 以内。
组合使用:频率限制 + 连接数压制
把上面两个规则写在一起,效果最好:
nginx
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
listen 80;
server_name example.com;
location / {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 20;
proxy_pass http://backend;
}
}
}
注意:`limit_conn` 在 HTTP 层面生效,`limit_req` 在请求处理阶段生效。先过连接数限制,再过频率限制,顺序不用你操心,Nginx 自己会处理。
常见报错与排障
配置重载后报错:`unknown directive "limit_req_zone"`
说明你编译 Nginx 时没带这个模块。检查一下:
nginx -V 2>&1 | grep -o limit_req
如果没输出,需要重新编译 Nginx,加上 `–with-http_limit_req_module` 和 `–with-http_limit_conn_module`。大多数发行版默认都带了,只有自己编译的才可能漏掉。
配置后所有请求都被拒绝:`503 Service Temporarily Unavailable`
大概率是 `rate` 设得太低,或者 `burst` 太小。先临时调大 `rate` 到 100r/s,看看业务正常时平均 QPS 是多少,再慢慢降到合理值。
限制生效后,白名单 IP 也被限制了
给白名单 IP 单独开一个 zone 就行了:
nginx
geo $white_ip {
default 1;
192.168.1.0/24 0;
}
map $white_ip $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=white_one:10m rate=10r/s;
这样白名单 IP 的 `$limit_key` 为空,不会被限制。
老鸟叮嘱:千万别忽略日志
配置完频率限制后,一定要打开 Nginx 的错误日志,看看有没有误杀:
tail -f /var/log/nginx/error.log | grep "limiting requests"
如果发现正常用户 IP 频繁被限,说明参数太严了。调整 `rate` 或 `burst`,别一刀切。另外,`limit_req` 和 `limit_conn` 只防应用层攻击,遇到大流量 DDoS 还得靠 CDN 或硬件防火墙。
FAQ
Q1:Nginx 频率限制后,为什么有些 IP 还是能发大量请求?
检查一下 `limit_req_zone` 是不是放在了 `server` 块里。必须放在 `http` 块,否则多个 server 会各自独立计数,攻击者换个域名就能绕过。
Q2:VPS 防火墙端口放行后还是访问不了是什么原因?
先确认 Nginx 是否监听正确端口,用 `ss -tlnp | grep 80` 看。如果监听没问题,再检查 `limit_req` 和 `limit_conn` 是否把本地 IP 也限制了。加 `geo` 模块排除内网段。
Q3:Linux 小白可以直接用 root 账号操作吗?
可以,但建议用 sudo。尤其是修改 Nginx 配置时,万一写错语法,root 身份重载失败可能导致服务全挂。先用 `nginx -t` 测试配置,没问题再 `systemctl reload nginx`。
Q4:BBR 开启后为什么速度没有明显提升?
BBR 优化的是 TCP 拥塞控制,对 CC 攻击无效。CC 攻击靠的是应用层请求频率,不是带宽。先确认攻击类型,别把 BBR 当防火墙用。
Q5:频率限制对爬虫有效吗?
对遵守 robots.txt 的爬虫(如 Googlebot)无效,因为它们请求频率低。对恶意爬虫有效,但最好配合 User-Agent 黑名单或验证码。
Q6:连接数限制对 WebSocket 有影响吗?
有。WebSocket 会保持长连接,`limit_conn` 会把它算作一个连接。如果业务用了 WebSocket,把限制值调大,或者单独写一个 location 不限制。
转载请注明出处:https://www.zhujixuan.com/jishujiaocheng/9521.html 商家投稿邮箱:zhujixuanblog@qq.com
