前言:当CPU曲线突然拉满,你只有几分钟
CC攻击的可怕之处在于它不像SYN Flood那样立刻让端口瘫痪,而是让服务器缓慢窒息——CPU稳步爬升到100%,网站响应变得像在泥潭里跑步。你登录SSH时可能已经卡得敲不下命令,而攻击者正用成百上千个代理IP刷着你站点最耗资源的接口(比如搜索、登录、报表生成)。
本文不会讲“什么是CC攻击”这种基础概念,而是直接给出你此刻最需要的东西:一套从发现异常→定位攻击→临时阻断→根源分析→加固防护的闭环操作五步法。每一步都附带可执行的命令和可验证的结果,不忽悠、不绕弯。
第一步:快速确认——到底是CC攻击还是程序BUG
CPU 100%不一定都是攻击,也有可能是代码死循环、数据库慢查询、爬虫暴增。你需要用最快速度做两个动作来定性。
1.1 查看实时进程,锁定CPU消耗大户
SSH登录后立刻执行(如果ssh卡顿,尝试重启sshd或使用串口控制台):
top -c -b -n 1 | head -50
重点关注%CPU列,如果排在前面的都是Apache/Nginx/PHP-FPM worker进程,并且每个worker都显示处理同一个URI(比如/?id=1&page=1之类的重复请求),那基本可以断定是CC攻击。如果消耗最高的是mysqld,且SQL查询时间很长,则更可能是慢查询或缓存失效。
1.2 查看网络连接状态,寻找大量ESTABLISHED
执行:
netstat -ant | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
正常情况下,来自同一个IP的连接数不会超过几十个。如果看到大量来自不同IP但连接数接近(比如每个IP只有3-5个连接,但总连接数上千),并且这些IP分布在不同C段,说明正在遭受分布式CC攻击。如果攻击IP来自少数几个C段,也可能是单点代理攻击。
第二步:紧急止血——在不扩容硬件的前提下快速阻断
确认是CC攻击后,你的首要目标不是抓黑客,而是让CPU降下来。以下是风险最低、见效最快的临时方案。
2.1 使用iptables临时封禁可疑IP段
如果攻击IP集中在某几个C段,直接封禁该段:
iptables -A INPUT -s 192.168.1.0/24 -j DROP
注意:在封禁前请确认这些IP不是你的CDN节点或合法爬虫。如果无法确认,建议先限速而非直接DROP:
iptables -A INPUT -s 192.168.1.0/24 -m limit --limit 5/s -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -j DROP
2.2 利用Nginx的limit_req限制请求频率
大多数CC攻击针对特定URI(如登录页面、API接口),可以在Nginx的server或location块中增加:
limit_req_zone $binary_remote_addr zone=cc:10m rate=30r/m;
server {
location /api/ {
limit_req zone=cc burst=5 nodelay;
proxy_pass http://backend;
}
}
这里rate=30r/m表示每分钟最多30次请求,burst=5允许瞬间突发5次。请根据正常业务流量调整参数。配置后重新加载nginx:nginx -s reload。CPU会立刻下降,因为大量超额请求在Nginx层就被拒绝了。
2.3 临时切换为静态页面或开启CDN缓存
如果上面两步没能让CPU降到80%以下,最粗暴的方法:将动态请求临时重定向到一个静态HTML(比如维护页面)。在Nginx配置中:
location / {
if (-f $uri) { break; }
rewrite ^ /maintenance.html break;
}
同时联系CDN服务商开启全站缓存。攻击过去后再恢复原配置。
第三步:深度排查——从日志中揪出攻击特征
CPU降下来之后,你需要搞清楚攻击者到底在刷什么,才能做针对性防护。
3.1 分析access.log,统计高频请求URI
切换到Nginx日志目录:
cd /var/log/nginx/
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20
如果排第一的URI请求次数是第二名的几十倍,且该URI是动态接口(如/api/user/login),攻击目标就是它。记录下该URI。
3.2 分析User-Agent和Referer
执行:
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -rn | head -10
如果User-Agent都是相同的随机字符串或很老的浏览器版本(如Mozilla/4.0),说明是工具发包。可以在Nginx中直接屏蔽该User-Agent:
if ($http_user_agent ~* "Mozilla/4.0") { return 403; }
但注意:不要轻易屏蔽真实用户的UA,建议先对可疑UA进行限速。
3.3 检查PHP-FPM慢日志
如果攻击触发了PHP执行,慢日志能告诉你哪个脚本执行时间异常:
tail -f /var/log/php-fpm/slow.log
通常会发现攻击者反复请求一个执行时间超过1秒的函数(如文件写入、复杂计算)。考虑对那个函数增加频率限制或引入队列异步处理。
第四步:建立长效防护——让相同的手法失效
应急搞定后,必须把临时措施升级为永久规则。
4.1 加入WAF规则(ModSecurity或云WAF)
推荐使用ModSecurity的OWASP CRS规则集,对CC攻击有现成的规则(如922100检测请求速率)。但是开箱即用容易误伤,需要先设置为DetectionOnly模式观察一段时间。云WAF(如Cloudflare、阿里云WAF)的CC防护更智能,建议直接购买专业版。
4.2 设置连接数限制(连接池)
在Nginx中,针对每个客户端IP设置最大连接数:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location / {
limit_conn addr 10;
}
}
}
注意:如果使用了CDN,$binary_remote_addr会来自CDN节点IP,需要改为$http_x_forwarded_for或CDN提供的真实IP变量。
4.3 引入验证码/滑块验证
对于登录、注册、搜索等高危接口,增加验证码(Google reCAPTCHA或hCaptcha)是最有效的硬性拦截。攻击脚本无法通过验证码,但用户体验会受影响。更折中的方案是:当同一IP在短时间内请求超过阈值时,才弹出验证码。
4.4 架构层面做动静分离
确保所有静态资源(图片、CSS、JS)都通过CDN分发,不要让动态服务器处理静态请求。同时将动态请求中可以被缓存的接口(如新闻列表)使用Redis或Varnish做全页缓存,减少PHP/数据库压力。
第五步:事后复盘——建立标准化响应SOP
攻击结束后,写下这次事件的详细记录:攻击时间、攻击IP列表、攻击URI、采取的阻断措施、CPU恢复时间、后续永久防护配置。这些数据可以用来优化监控告警。
5.1 告警阈值调优
设置CPU和连接数的监控告警(建议CPU>80%持续5分钟告警,ESTABLISHED连接数>5000告警),避免下次被动发现。可以使用Netdata或Prometheus+Alertmanager。
5.2 定期演练
在测试环境模拟CC攻击(可以使用wrk或ab工具),验证防护规则是否有效。确保团队每个人都知道SSH备用入口、iptables临时封禁命令、Nginx限频配置修改位置。
5.3 考虑上高防IP或流量清洗
如果CC攻击频率高(每月1次以上),建议接入高防IP服务(如阿里云高防、腾讯云大禹),它们有专门的CC防护引擎,能识别并清洗异常流量。
写在最后:没有银弹,但有经验
CC攻击防护没有一劳永逸的方案,因为攻击手法也在进化。本文的五步法帮你建立了一个快速响应-深度分析-永久加固-复盘改进的闭环。关键是每一步都要有可验证的结果:限速后CPU是否下降、封禁后连接数是否减少、日志中特征是否消失。下次再遇到CPU 100%,你可以从容应对。
延伸阅读
