网站突然打不开,服务器 CPU 跑满,一看访问日志——同一个 IP 或者一大批 IP 在疯狂请求你的页面,每秒几十上百次。
这就是 CC 攻击(Challenge Collapsar):攻击者用大量请求耗尽你的服务器资源,让你的网站对正常访客不可用。
它和 DDoS 的区别:DDoS 拼带宽(把你网络堵死),CC 拼资源(让你的 PHP 和数据库算不过来)。小站遇到的绝大多数是 CC——因为它成本低,一台机器就能发起。
小站买不起动辄几万一年的高防。但能做的事其实不少,下面按成本和生效速度排序。
先确认:你真的是被攻击了吗
别自己吓自己。有时候流量暴涨是因为你的内容被转发了,或者爬虫来了。
看访问日志
# 统计访问最多的 20 个 IP
awk '{print $1}' /www/wwwlogs/你的站点.log | sort | uniq -c | sort -rn | head -20
判断标准:
- 单个 IP 几百上千次请求,且集中在短时间内 → 基本确认
- 请求的 URL 是动态页面(搜索页、带参数的 URL)而不是首页 → 恶意特征明显,因为动态页面最耗资源
- User-Agent 高度一致或者是空的 → 脚本行为
- IP 集中在某个段或者境外 → 可疑
看请求特征
# 看最常被请求的 URL
awk '{print $7}' /www/wwwlogs/你的站点.log | sort | uniq -c | sort -rn | head -20
# 看 User-Agent 分布
awk -F'"' '{print $6}' /www/wwwlogs/你的站点.log | sort | uniq -c | sort -rn | head -10
CC 攻击特别喜欢打这些地方:搜索页(?s=xxx)、需要数据库查询的列表页、登录页、接口。因为静态页面有缓存,打了也没用。
第 1 件事:封 IP(最粗暴,也最快)
找到攻击 IP 后直接封。
iptables 封单个 IP
iptables -I INPUT -s 攻击IP -j DROP
封整个 IP 段
iptables -I INPUT -s 1.2.3.0/24 -j DROP
nginx 层面封(推荐,更省资源)
在站点配置的 server 块里加:
deny 1.2.3.4; deny 5.6.7.0/24;
局限:如果攻击者用的是分散的 IP 或者肉鸡集群,封 IP 就是打地鼠,封不完。这招只对「少量 IP 高强度」的攻击有效。
第 2 件事:nginx 限流(核心手段,免费)
这是小站最有效的一招。限制单个 IP 的请求频率,超了就拒绝。
配置
在 nginx 的 http 块(宝塔:软件商店 → Nginx → 配置修改)加:
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s; limit_conn_zone $binary_remote_addr zone=perip_conn:10m;
然后在站点的 server 块里:
location / {
limit_req zone=perip burst=20 nodelay;
limit_conn perip_conn 20;
...原来的配置...
}
参数含义:
rate=10r/s:每个 IP 每秒最多 10 个请求burst=20:允许瞬时突发 20 个(因为正常用户打开一个页面会同时请求几十个资源)limit_conn 20:单个 IP 最多 20 个并发连接
参数别设太小。一个正常页面加载会请求几十个静态资源,你设 2r/s 会把正常用户也挡在外面。建议从宽松开始(10r/s),观察效果再收紧。
对动态请求单独限流(更精准)
location ~ \.php$ {
limit_req zone=perip burst=10 nodelay;
...
}
这样静态资源不限,只限制 PHP 动态请求——正好打在攻击者的痛处(他们就是冲着耗你 PHP 资源来的)。
第 3 件事:上 Cloudflare 免费版(强烈推荐)
这是性价比最高的一步,免费,而且效果比你在自己服务器上折腾强得多。
原理:把域名解析到 Cloudflare,所有流量先经过它的全球网络,恶意请求在到达你的服务器之前就被拦下了。
要开的几个设置
- Under Attack Mode(I’m Under Attack):被攻击时打开,会给访客一个 5 秒的 JS 检查页,能挡掉绝大多数脚本。缺点是正常用户也要等一下,攻击结束后记得关掉
- Rate Limiting 规则:免费版有 1 条额度,设成「同一 IP 10 秒内超过 100 次请求就阻断」,把额度用在最需要保护的 URL 上(比如登录页、搜索页)
- Bot Fight Mode:免费,能识别并挑战可疑机器人
- WAF 防火墙规则:免费版 5 条,可以拦特定国家、特定 User-Agent
注意:别把源站 IP 暴露了
上了 Cloudflare 之后,如果你的服务器真实 IP 泄露,攻击者可以绕过 Cloudflare 直接打你的源站,防护全废。
防泄露的做法:
- 服务器防火墙只放行 Cloudflare 的 IP 段(官网有公布列表),其他一律拒绝 80/443
- 检查有没有子域名没走 Cloudflare(比如直接解析到源站的
mail.xxx.com),攻击者能通过它反查到你的 IP - 网站发出的邮件头里可能带源站 IP,用 SMTP 服务发信可以避免
第 4 件事:禁用不必要的动态入口
关闭 WordPress 的搜索功能(如果被针对)
搜索页是很典型的攻击目标——每次搜索都要全表扫描,特别耗资源。
临时关闭可以在主题的 functions.php 加:
add_action( 'parse_query', function( $q ) {
if ( $q->is_search && ! is_admin() ) {
$q->set( 's', '' );
$q->is_search = false;
}
});
关闭 xmlrpc.php
这个文件是 CC 和爆破的重灾区(一次请求可以试上百个密码)。没有用就关掉。
location = /xmlrpc.php {
deny all;
}
限制 wp-login.php 访问频率
location = /wp-login.php {
limit_req zone=perip burst=3 nodelay;
...
}
第 5 件事:加缓存,让攻击打不动
CC 攻击之所以有效,是因为每个请求都要 PHP 算一遍、数据库查一遍。如果页面是静态缓存的,服务器直接从磁盘读文件返回,消耗降两个数量级。
- 页面缓存:宝塔的 Nginx 缓存、WP Rocket、或者 Nginx fastcgi_cache
- 对象缓存:Redis
这是最本质的防护:把「每个请求都很贵」变成「每个请求都很便宜」。攻击者要打垮你需要大 100 倍的流量,成本上他就放弃了。
缓存 + Cloudflare 组合,小站基本够用了。
第 6 件事:做好降级预案
真的扛不住的时候,有个体面的退路比硬撑着强。
准备一个静态应急页
一个纯 HTML 页面,写着「网站维护中,联系方式如下」,放联系方式和 WhatsApp/邮箱。攻击者打不垮一个静态文件。
真扛不住时把 nginx 指向这个页面,至少品牌和询盘通道还在。
保留主机商的应急联系方式
提前问清楚:你的主机商有没有应急防护、能不能临时加带宽、联系渠道是什么。出事之后再找客服,你会发现工单响应要几小时。
防护的成本排序
| 手段 | 成本 | 生效速度 | 挡得住什么 |
|---|---|---|---|
| 封 IP | 0 | 立即 | 少量固定 IP |
| nginx 限流 | 0 | 10 分钟 | 中等强度高频攻击 |
| Cloudflare 免费版 | 0 | 改解析后几小时 | 大部分 CC 和小规模 DDoS |
| 页面缓存 | 0 | 半小时 | 根源性降低资源消耗 |
| Cloudflare Pro(20 美元/月) | 低 | 即时 | 更强的 WAF 和速率限制 |
| 高防 IP / 高防 CDN | 几千到几万/年 | 需部署 | 大规模 DDoS |
最后:什么情况下你该考虑付费方案
如果你的站有这些特征,免费方案可能不够,建议考虑 Cloudflare Pro 或国内高防:
- 做竞争激烈的行业(仿牌、游戏、灰产边缘)——被同行打是常态
- 站点有实时收入(正在跑广告、正在做促销)——停一小时损失大于防护成本
- 已经反复被攻击——说明有人在针对你
反过来,普通的 B2B 外贸站、企业展示站,Cloudflare 免费版 + nginx 限流 + 页面缓存这套组合足够应付绝大多数情况。真被打的概率本来就低,不用为小概率事件花大钱。