网站运维

独立站被 CC 攻击:没有高防的小站能做的 6 件事

网站突然打不开,服务器 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,所有流量先经过它的全球网络,恶意请求在到达你的服务器之前就被拦下了。

要开的几个设置

  1. Under Attack Mode(I’m Under Attack):被攻击时打开,会给访客一个 5 秒的 JS 检查页,能挡掉绝大多数脚本。缺点是正常用户也要等一下,攻击结束后记得关掉
  2. Rate Limiting 规则:免费版有 1 条额度,设成「同一 IP 10 秒内超过 100 次请求就阻断」,把额度用在最需要保护的 URL 上(比如登录页、搜索页)
  3. Bot Fight Mode:免费,能识别并挑战可疑机器人
  4. 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 限流 + 页面缓存这套组合足够应付绝大多数情况。真被打的概率本来就低,不用为小概率事件花大钱。