网站突然卡死,CPU 飙到 100%,但带宽没跑满——这多半不是 DDoS,是 CC 攻击。攻击者用大量代理 IP 反复请求你的动态页面(搜索页、登录接口、购物车),每个请求都逼着 PHP 和数据库干活,机器就这么被拖死了。我处理过几次这种情况,把判断和防御的路子写下来。
先确认是不是 CC 攻击
SSH 还能登上去的话,先看连接数:
netstat -ant | awk '/ESTABLISHED/ {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
正常业务下,单个 IP 的并发连接一般不超过 20。如果看到几十个陌生 IP 各挂着 50+ 连接,基本可以定性了。再翻一下 Nginx 日志,看请求都打在哪:
tail -5000 /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10
CC 攻击的典型特征:同一个动态 URL(比如 /?s= 搜索页)被不同 IP 高频请求,User-Agent 要么雷同要么明显是伪造的。
紧急止血:先把连接数压下来
在 Nginx 的 http 段加限流,这是见效最快的一步:
limit_req_zone $binary_remote_addr zone=cc:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn:10m;
server {
location / {
limit_req zone=cc burst=20 nodelay;
limit_conn conn 20;
}
}
改完 nginx -t 检查语法再 nginx -s reload。rate=10r/s 对普通企业站够宽松,正常访客感觉不到,脚本一压就被 503 挡回去。
攻击 IP 数量不多的话,直接封:
ufw deny from 198.51.100.23
但 CC 攻击往往有几百上千个代理 IP,手工封不过来,这时候要靠自动化。
用 Fail2ban 自动封禁
新建 /etc/fail2ban/filter.d/nginx-cc.conf:
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP.*"
然后在 jail.local 里加一段,60 秒内超过 300 个请求就封 1 小时:
[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
logpath = /var/log/nginx/access.log
maxretry = 300
findtime = 60
bantime = 3600
maxretry 别设太小。一个正常页面加载会带十几个静态资源请求,设成 60 会误伤真实用户,300 比较稳。
上 CDN 才是长久之计
源站硬扛终究吃亏。把域名接入 Cloudflare(免费版就行),开启 Under Attack 模式,攻击流量会先过一遍 5 秒盾的 JS 验证,绝大多数脚本直接过不去。国内站可以用腾讯云 CDN 或百度云加速。接入后记得在防火墙上限制 80/443 只接受 CDN 回源 IP 段的流量,不然攻击者查到源站真实 IP 照样绕过去打。
常见问题
CC 攻击和 DDoS 有什么区别?
DDoS 靠流量洪水把带宽塞满,CC 靠海量合法样式的 HTTP 请求耗尽 CPU 和数据库。前者要靠机房或高防清洗,后者服务器层面就能挡住大部分。
限流会不会误伤搜索引擎爬虫?
Googlebot 和百度蜘蛛的抓取频率通常低于 10r/s,正常限流不会触发。担心的话可以在 Nginx 里用 geo 模块给已验证的爬虫 IP 段设白名单。
攻击停了之后要做什么?
把攻击时段的日志备份下来分析规律,检查有没有趁乱注入的后门文件,限流规则留着别删——下次攻击来的时候你会庆幸没删。
你的服务器被 CC 攻击过吗?用了什么方案扛住的?欢迎在 fenij.com 评论区聊聊你的实战经验。