服务器被CC攻击怎么办:从确认到缓解的实操步骤
网站突然打不开、CPU和连接数飙升,但带宽没跑满,多半是CC攻击。
CC攻击用大量看起来正常的HTTP请求耗尽服务器资源,和流量型DDoS不同,它不靠大流量,而是靠请求数和连接数压垮Web服务。
处理顺序是:先确认是不是CC,再限速挡掉高频请求,然后封掉攻击源,最后检查源站是否暴露并验证恢复。
先确认是不是CC攻击
别急着改配置,先看三个地方:连接数、访问日志、资源占用。
用ss看当前连接数:
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c
如果ESTAB数量远高于平时,且大量连接来自少数几个IP,基本可以怀疑CC。
再看访问日志里同一IP的请求频率:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
正常情况下单个IP每分钟几十次请求算正常,如果某个IP一分钟几百上千次,且请求路径集中在首页或搜索接口,就是典型CC特征。
同时用top看Nginx或PHP-FPM进程是否吃满CPU,用free -h看内存是否被连接占满。
确认攻击特征后,记录攻击源IP和请求路径,后面限速和封禁都要用到。
用Nginx限速挡住高频请求
Nginx的limit_req模块能按IP限制请求速率,是缓解CC最直接的手段。
在http块里定义限速区域:
http {
limit_req_zone $binary_remote_addr zone=cc:10m rate=10r/s;
...
}
rate=10r/s表示每个IP每秒最多10个请求,zone=cc:10m是共享内存区,10MB大约能存16万个IP状态。
然后在server或location里启用:
location / {
limit_req zone=cc burst=20 nodelay;
...
}
burst=20允许短暂突发20个请求,nodelay表示突发请求立即处理不排队。
改完执行nginx -t检查语法,再nginx -s reload生效。
如果攻击集中在某个接口,比如搜索或登录,可以只在该location加限速,避免影响正常页面。
限速值要根据业务调整,设得太低会误伤正常用户,建议先观察日志里的正常请求频率再定。
封掉攻击源IP
限速只能削峰,攻击源IP明确时直接封更彻底。
用iptables封单个IP:
iptables -I INPUT -s 203.0.113.10 -j DROP
封整个网段:
iptables -I INPUT -s 203.0.113.0/24 -j DROP
用firewalld的系统:
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=203.0.113.10 reject'
firewall-cmd --reload
封之前确认IP不是自己的监控或CDN回源地址,误封会导致正常访问中断。
封完后用ss -ant | grep 203.0.113.10确认连接是否消失。
如果攻击IP很多且不断变化,手动封不过来,就需要上CDN或高防清洗。
把域名解析切到CDN,源站只放行CDN回源IP,攻击流量在CDN节点被过滤,源站压力会明显下降。
切换前确认源站没有直接暴露IP,否则攻击者绕过CDN继续打源站。
检查源站是否暴露并做收尾
处理完攻击后,检查源站IP是否还能被直接访问。
用curl从外部测试源站IP的80和443端口,如果能直接连上,说明CDN没有真正隐藏源站。
可以在防火墙里只放行CDN回源IP段,其余全部拒绝。
另外检查Nginx日志里是否还有异常请求路径,比如大量请求同一个动态接口,可以在Nginx里对该路径单独限速或返回403。
PHP站点还要看php-fpm进程数是否被打满,必要时调低pm.max_children防止内存耗尽。
最后验证恢复:用浏览器打开网站确认正常访问,用ss -s看连接数回落到正常范围,用top确认CPU不再持续跑满。
如果攻击仍在持续,保持限速和封禁策略,观察日志调整阈值。
处理CC攻击没有一劳永逸的配置,关键是先确认攻击特征,再用限速和封禁争取时间,最后通过CDN或高防把清洗能力前置。
平时把访问日志和连接监控打开,攻击发生时才能快速定位。