网站平时好好的,突然打不开,SSH 上去一看 CPU 100%、带宽跑满,Nginx 日志里全是同一个页面被反复请求,这大概率是 CC 攻击。CC 攻击不靠大流量硬打,而是模拟正常用户不断请求动态页面,让 PHP 和数据库一直忙。防御的核心不是“扛”,而是“识别、限流、缓存、清洗”。
一、先判断是不是 CC
- 访问日志里同一 IP 或同一小段 IP 高频请求同一 URL。
- User-Agent 高度一致,或者明显是脚本特征。
- 请求集中在搜索、登录、评论、动态接口等消耗资源的位置。
- 带宽没跑满,但 CPU 和数据库连接数很高。
先找出请求量最大的 IP:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20再看被请求最多的 URL:
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20两条命令结合起来,基本能判断攻击类型:是刷首页,还是刷搜索页,还是打登录接口。不同入口的防护策略不一样。
二、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 或 location 里引用:
location / {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 10;
}rate=10r/s 表示每个 IP 每秒 10 个请求,burst 允许突发 20 个,nodelay 表示突发部分立即处理,否则会排队增加延迟。阈值要结合真实业务调整,设得太严会误伤正常用户。登录、搜索这类接口可以单独设更低的 rate。
改完执行 nginx -t 检查语法,再 nginx -s reload。被限流拒绝的请求会返回 503,可以在日志里看到 limiting requests 字样。
三、封 IP 与拦截特征
确认恶意 IP 后,可以在 Nginx 层拒绝:
deny 1.2.3.4; deny 1.2.3.0/24;
IP 较多时用 ipset 批量封禁,避免防火墙规则膨胀。但要注意:如果站点已经接入 CDN,日志里的 IP 是 CDN 回源 IP,直接封会误伤大量正常用户。这时要用 real_ip 模块还原真实 IP:
set_real_ip_from 173.245.48.0/20; real_ip_header CF-Connecting-IP;
更稳妥的做法是直接在 CDN 或 WAF 后台封禁,源站只允许 CDN 回源 IP 访问。
四、Cloudflare 免费版能做什么
- 把域名接入 Cloudflare,开启小云朵代理,源站 IP 就被隐藏了。
- 攻击期间打开 Under Attack Mode,会对访问者做一次 JS 挑战。
- WAF 自定义规则可以按 IP、国家、UA、路径拦截。
- 免费版提供基础的速率限制规则,对小型 CC 够用。
- 缓存静态资源,减少回源,动态页面设置绕过缓存但保留防护。
接入 CDN 后一定要改源站防火墙,只允许 Cloudflare 回源 IP 访问 80 和 443。否则源站 IP 一旦泄露,前面所有防护都形同虚设。
五、缓存和静态化:从根上降压
CC 打的是动态页,最有效的办法是让请求不落到 PHP。Nginx fastcgi_cache 或页面缓存插件能把动态页变成静态响应,同样的攻击流量下,CPU 占用能降一个数量级。配置时注意排除登录用户和评论提交,缓存时间不宜过长,并在被攻击时临时提高缓存命中率。
六、应用层加固
- 登录页加验证码,并对失败次数限速。
- 关闭 WordPress 的 xmlrpc.php,这是被刷的重灾区。
- 限制评论频率,开启评论审核。
- 搜索接口加最小请求间隔,避免被当成压力测试入口。
- 数据库连接数设上限,防止一个慢查询拖垮整站。
七、被攻击时的应急顺序
- 先看监控,确认是带宽、CPU 还是数据库连接被打满。
- 开启 CDN 的防护模式,或临时把域名解析切到高防。
- Nginx 加限流和封禁,优先保动态接口。
- 开启页面缓存,静态资源全部走 CDN。
- 保留日志证据,攻击结束后再逐步放开策略,不要一次性全撤。
八、常见问题
- 限流后正常用户也被拦:rate 设得太低,或共享出口 IP 的用户多,按业务调整 burst。
- 封 IP 没效果:请求来自 CDN 回源,日志 IP 不是真实 IP,先配 real_ip。
- 开了 Cloudflare 还是被打:源站 IP 可能已泄露,换 IP 并限制回源。
- 攻击停了网站还是很慢:检查数据库连接、缓存是否被打穿、日志是否写满磁盘。
总结
CC 防御是分层的事:CDN 隐藏源站并清洗流量,Nginx 做限流和封禁,缓存把动态请求挡在 PHP 之前,应用层再加验证码和频率限制。平时把日志、监控和缓存配好,真被打的时候才有反应时间。指望单一手段挡住所有攻击不现实,但把这几层叠起来,绝大多数中小型 CC 都能扛过去。