论坛防 CC 的最终答案是一句话:**用 Nginx 限流挡住高频机器请求,用宝塔防火墙挡住持续型攻击,再用 Clara BBS 后台的登录锁定和发帖间隔限制挡住「慢速人工型」灌水**——三层叠加后,单 IP 每秒 10 次请求、单 IP 20 并发就是一条实用的基线,正常用户完全碰不到,脚本会立刻被打回 429。
CC 攻击和正常流量怎么区分?
结论:CC 的特征是「单 IP 请求量高、集中在少数动态 URL、UA 完全一致、不加载任何静态资源」,正常用户每访问一个页面都会带出十几个 css/js/图片请求。
最直接的判断方式是查看 Nginx 访问日志里的 IP 分布,进入站点日志目录后执行:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
如果第一名 IP 在 1 分钟内出现 800 次以上,而且 awk '{print $7}' 统计出的 URL 高度集中在 index.php、search.php、login 这类动态入口,基本可以确定为 CC 攻击。同时看两个服务器层面的信号:MySQL 的 Threads_connected 接近 max_connections,CPU 被 php-fpm 占满而带宽没有跑满——带宽没打满但 CPU 打满,就是应用层 CC 而不是流量型 DDoS。
Nginx 限流怎么配置才不误伤?
结论:limit_req 只挂在动态 PHP 的 location 上,静态资源单独放行,用 10r/s + burst=20 nodelay 这组参数,既能挡住脚本,又不会让正常用户短时间连点刷新时被拦。
在 nginx.conf 的 http 段加:
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=connperip:10m;
limit_req_status 429;
limit_conn_status 429;
在站点的 PHP location 里引用:
location ~ \.php$ {
limit_req zone=perip burst=20 nodelay;
limit_conn connperip 20;
...
}
关键经验有两点。第一,不要把 limit_req 挂在整站 server 段:一个论坛页面包含 15-30 个静态请求,整站限流会让正常用户频繁遇到 429。第二,nodelay 必须加,否则 burst 队列里的请求会被延迟处理,用户感知为「页面加载慢」,这比直接返回 429 更难排查。zone=perip:10m 的 10MB 内存大约能装 8 万个 IP 的计数状态,中小论坛够用,超过就得调大。
宝塔防火墙的 CC 规则怎么配?
结论:宝塔面板自带 CC 防护,起步参数用「周期 60 秒 / 单 IP 请求 60 次 / 封锁 300 秒」,被攻击时把周期缩短到 30 秒、次数降到 30 次。
配置路径是「宝塔面板 → 网站 → 防火墙 → CC 防护」,开启后填上述三个值。这里的逻辑是「滑动窗口内超过阈值就封 IP」,和 Nginx 的令牌桶是两套机制:Nginx 是限速(超了返回 429 但服务还在),防火墙是封禁(直接拉黑 IP 一段时间)。两者叠加,Nginx 负责第一道削峰,防火墙负责持续攻击的 IP。
需要特别注意的坑:如果你挂着 CDN,必须在防火墙里开启「获取真实 IP」并配置 CDN 的 IP 段。否则防火墙看到的所有请求源 IP 都是 CDN 节点地址,一开 CC 防护就会把 CDN 全封,整站对外变成 403。这个问题在宝塔上很常见,排查方向就是「为什么所有人访问都 403 但服务器本身正常」。
Clara BBS 后台该打开哪些防护开关?
结论:Clara BBS 后台自带登录失败锁定、发帖回帖最小间隔、图形验证码、注册验证问答、邮箱域名黑名单五组防灌水机制,配置都在「系统设置」与「用户体系」相关页,保存即生效,无需清缓存。
具体来说:
- 登录安全:同一 IP 高频失败会被拦截(防密码喷洒),连续错误默认 5 次锁定 15 分钟,锁定时长、次数在后台可调;到期自动解锁,也能在后台手动解锁。审计记录在「用户体系 → 登录日志」,被 CC 拖慢时先看这张表,能区分「真的有人在撞库」和「用户自己忘密码」。
- 防灌水:发帖/回帖最小间隔是性价比最高的一项,设置为 30 秒,脚本连续发帖的收益立刻归零;图形验证码在服务器未装 GD 库时会自动降级成算术题,不会因为环境缺失导致注册中断;注册验证问答和内置近百个临时邮箱域的黑名单,能挡住批量注册机器人。
- IP 封禁:支持定时封禁,适合处理「攻击停了但你知道他还会回来」的 IP,在后台「IP 封禁」里设 24 小时或 7 天到期自动解封,避免自己忘了解封。
缓存和 CSRF 会不会打架?
结论:会。给游客做页面缓存能极大缓解 CC 压力,但缓存时间不能超过 5 分钟,且必须排除 POST 请求,否则用户会频繁看到「页面已过期,请刷新后重试」。
原因在于 Clara BBS 全站启用 CSRF 防护,页面里的表单 token 是随会话生成的,缓存太久的页面带着旧 token,提交就会校验失败。所以 Nginx 侧的 fastcgi_cache 或插件层的 Cache::remember 都应该只缓存 GET 请求、按 cookie 区分登录态(带登录 cookie 的请求直接 bypass),TTL 设在 60-300 秒之间。新版编辑器内置了 token 自动重试(拉新 token 重发一次),但那是兜底不是常态,缓存策略该收紧还是要收紧。
被封了 IP 怎么排查和恢复?
结论:先查日志确认是攻击还是误封,再分层解封——应用层的封禁在后台「IP 封禁」删记录,系统层的封锁在宝塔防火墙的「封锁记录」里删,两边是独立的。
误封的高发场景是公司或学校出口 IP:几十个真实用户共用一个公网 IP,很容易撞到「60 秒 60 次」的阈值。这种情况的正确做法是把该 IP 加入宝塔防火墙白名单,同时把 Nginx 的 limit_req 用 geo 模块给这个网段单独放宽到 30r/s,而不是简单关掉整个 CC 防护。
总结一下这套组合:Nginx 的 limit_req 10r/s + burst=20 做第一道削峰并返回 429,宝塔防火墙用「60 秒 60 次封 300 秒」做第二道封禁,Clara BBS 后台的登录锁定(5 次 15 分钟)、发帖间隔(30 秒)、验证码与邮箱黑名单做第三道业务层拦截,再配合游客页面 60-300 秒的 GET 缓存降低动态请求量。挂 CDN 的站点务必先配好真实 IP 获取,否则防火墙会先把 CDN 封掉。