CC防护(Challenge Collapsar,即HTTP请求洪水防护)的核心难题从来不是"能不能拦住攻击",而是"怎么在不误杀正常用户的前提下精准拦截"。单条低阈值规则容易触发大量误报,比如某个IP在5秒内访问了3次页面就被封,这在高并发的电商场景下几乎不可用。真正有效的做法是把多个低阈值规则合并成一个综合评分体系——每个规则贡献一定分数,累计达到阈值才触发拦截,而不是任何单一规则命中就直接封堵。这就是"多规则融合评分决策"的本质逻辑。

为什么要用低阈值规则而不是直接设高阈值?因为攻击者的行为是分散的、渐进的。一个CC攻击脚本可能每次只发少量请求,单个维度看都不超标,但多个维度叠加就暴露了异常。低阈值规则的优势在于能捕捉到这些"看起来正常但合起来不正常"的行为模式。关键在于如何把这些碎片化的信号整合成一个可信的判断。

一、为什么单条规则防护CC攻击总是不够用

传统的CC防护策略通常是这样的:设定一个单一指标,比如"单个IP每分钟请求超过200次就拦截"。这种方式在面对低频慢速攻击时完全失效。攻击者可以把请求频率控制在每分钟150次,单看这一条规则根本触发不了。但如果同时观察请求频率、请求路径集中度、User-Agent异常度、会话时长等多个维度,就会发现这个IP的行为明显不对劲。

另一个问题是误杀。假设你把阈值设到每分钟500次才拦截,正常用户在抢购场景下也可能达到这个数值。低阈值规则单条使用时误报率更高,但多条规则合并评分后,正常用户通常只会触发一两条低分规则,总分达不到拦截线;而攻击者往往多条规则同时命中,总分迅速飙升。这就是评分机制的核心价值——用"多维度交叉验证"替代"单维度硬性切割"。

二、综合评分决策的基本架构设计

一个完整的CC防护评分系统通常包含四个层次:数据采集层、规则引擎层、评分计算层、决策执行层。

数据采集层负责实时收集每个请求的关键特征,包括但不限于:源IP、请求频率(滑动窗口内的计数)、请求URI的重复度、请求头特征(User-Agent、Referer、Accept等)、会话Cookie的有效性、请求间隔的统计分布(均值、方差)、TCP连接特征等。这些数据需要在极短时间内完成聚合,通常使用滑动时间窗口(比如10秒、30秒、60秒三档)来统计。

规则引擎层定义若干条低阈值检测规则,每条规则独立判断并输出一个分数。比如:

规则1:10秒内同一IP请求超过15次 → 得分 +20
规则2:30秒内同一IP访问同一URI超过10次 → 得分 +15
规则3:User-Agent为空或明显伪造 → 得分 +25
规则4:请求间隔标准差小于0.5秒(过于规律) → 得分 +18
规则5:无有效Cookie或Cookie异常 → 得分 +10
规则6:Referer为空且非首页访问 → 得分 +12
规则7:60秒内请求来自超过3个不同子域名 → 得分 +8
规则8:响应状态码连续出现4xx或5xx → 得分 +22

评分计算层将所有命中规则的分数累加,得到该IP在当前时间窗口内的综合风险分。决策执行层根据总分区间执行不同动作:低于30分放行,30-60分触发验证码挑战,60-80分限速(降低响应频率),80分以上直接阻断并加入临时黑名单。

三、低阈值规则的具体设计原则

设计低阈值规则时有几个关键原则必须遵守。第一,每条规则的阈值要足够低,确保能捕捉到早期异常信号,但又不能低到正常用户也频繁触发。一般建议以正常用户行为分布的70%-80%分位值作为单条规则的触发点。第二,规则之间要有一定的独立性,避免多条规则实际上在检测同一个行为特征导致分数虚高。第三,每条规则的权重(得分值)要根据其在实战中的区分度来设定,区分度高的规则给更高分。

具体来说,请求频率规则是最基础的,但单独使用区分度一般,建议给中等权重。User-Agent异常和请求间隔过于规律这两条在实战中区分度极高——正常用户的请求间隔一定是有波动的,而脚本攻击往往极其均匀,这类规则应该给高权重。Cookie异常和Referer为空在移动端场景下误报较多,权重可以适当调低。

还有一个容易被忽视的规则维度:行为序列分析。不是看单次请求,而是看一段时间内的请求序列是否符合正常浏览模式。正常用户会先访问首页、再进入列表页、再点击详情页,有一个合理的跳转链路。而CC攻击往往直接反复请求某个接口(比如登录接口或查询接口),跳转链路极短甚至没有。这类规则可以这样设计:

规则9:连续5次请求均命中同一API路径且无页面跳转 → 得分 +30
规则10:请求路径熵值低于1.5(路径过于集中) → 得分 +20

这两条规则在实际部署中效果非常显著,尤其是针对针对特定接口的CC攻击。

四、评分融合的算法选择与优化

最简单的融合方式是线性加权求和,就是把所有命中规则的分数直接加起来。这种方式实现简单、可解释性强,适合大多数场景。但它有一个缺陷:如果某个IP同时命中了10条规则,总分可能远超实际风险,因为规则之间存在相关性。

更精细的做法是引入衰减机制或者非线性融合。比如使用对数压缩:总分 = log(1 + Σ得分),这样即使命中很多规则,分数增长也会放缓,避免极端情况下的过度惩罚。另一种方式是设置单类规则的上限,比如"频率类规则最多贡献40分",防止某一类行为特征主导整个评分。

在实际工程中,还需要考虑时间衰减。一个IP在过去5分钟内累计了70分,但最近1分钟内没有新的异常行为,那它的风险应该在逐步降低。可以引入指数衰减公式:

当前有效分 = Σ(每条规则得分 × e^(-λ × t))
其中 t 是该规则触发距今的时间,λ 是衰减系数(通常取0.1-0.3)

这样设计的好处是:攻击者如果暂停攻击一段时间,分数会自然下降,不会被永久封禁;而持续攻击的IP分数会不断累积,最终触发拦截。这在应对"脉冲式CC攻击"(攻击一阵停一阵)时特别有效。

五、误报控制与动态阈值调整

综合评分系统上线后最大的挑战是误报。解决误报不能靠拍脑袋调参数,要靠数据驱动。建议建立一个反馈闭环:每次触发拦截或挑战时,记录该IP的后续行为。如果被挑战后通过了验证码并正常浏览,说明是误报,需要降低相关规则的权重或提高阈值;如果被拦截后该IP继续尝试攻击,说明判断正确,可以维持甚至加强。

动态阈值调整可以基于滑动窗口内的全站统计数据。比如在大促期间,全站平均请求频率会自然升高,这时候如果还用固定阈值就会大量误杀。系统应该自动感知全站流量基线,将规则阈值按比例上浮。具体做法是:每5分钟计算一次全站各维度的P95值,将规则阈值设为当前P95值的1.2-1.5倍,这样既能适应流量波动,又不会放得太松。

另外,白名单机制也是误报控制的重要手段。对于已知的搜索引擎爬虫、CDN节点IP、内部监控系统IP,直接跳过评分流程。对于登录态用户,可以适当提高容忍度,因为正常登录用户的行为模式和匿名访问者不同,不能用同一套标准去衡量。

六、实战部署中的性能考量

综合评分系统对性能的要求很高,因为每个请求都要实时计算分数。如果规则太多、计算太复杂,会直接拖慢业务响应速度。实际部署中通常采用以下优化策略:

第一,规则分优先级执行。先执行计算成本低、区分度高的规则(比如User-Agent检测、Cookie检测),如果前几条规则已经让分数超过拦截线,后面的规则就不用算了,直接执行拦截。第二,使用内存数据库(如Redis)存储滑动窗口计数,避免每次请求都查磁盘数据库。第三,对评分计算做异步化处理——先快速给出初步分数决定是否放行,后台再做精细评分更新黑名单。

在架构层面,建议把评分计算放在流量入口的网关层(如Nginx + Lua模块、或专门的WAF引擎),而不是放在应用服务器上。这样可以在请求到达业务逻辑之前就完成过滤,既保护了后端,又不影响业务代码。

七、与其他防护策略的协同配合

综合评分决策不应该是孤立的,它需要和其他防护手段形成纵深防御。在评分系统判断为"中风险"(比如40-60分)时,可以联动JS挑战或CAPTCHA验证,让客户端证明自己是真人浏览器。在评分系统判断为"高风险"时,可以联动IP信誉库,如果该IP在多个业务线都有攻击记录,直接全局封禁。

此外,还可以结合行为指纹技术。每个客户端在首次访问时生成一个浏览器指纹(基于Canvas、WebGL、字体列表等特征),后续请求携带该指纹。如果同一个IP频繁更换指纹,这本身就是高风险信号,可以作为额外的评分规则加入体系。这种多层验证的思路,让攻击者的成本呈指数级上升。

总结来看,CC防护中合并多个低阈值规则形成综合评分决策,本质上是从"非黑即白"的二元判断升级为"灰度评估"的连续决策。它不追求单条规则的完美,而是通过多维度、多规则的交叉验证来逼近真实风险。这套方法的核心竞争力在于:既能捕捉到传统单阈值方案漏掉的低频攻击,又能通过评分机制和动态调整把误报控制在可接受范围内。对于任何面临CC攻击威胁的业务系统来说,这都是当前最务实、最可落地的防护思路。