CC防护(Challenge Collapsar,即CC攻击防护)中,结合地理位置与历史行为进行综合评分降权,本质上是一套多维度的流量清洗策略。它的核心逻辑是:不再单纯依靠单一IP的访问频率来判定攻击,而是把用户的地理位置信息、历史访问行为轨迹、请求特征等多个维度叠加在一起,给每个访问者打一个动态分数,分数超过阈值就直接降权或拦截。这种方式比传统的频率限制更精准,误杀率更低,同时对分布式CC攻击的防御效果也更强。具体怎么做?下面从原理、实现方案、评分模型设计、落地细节四个层面把这件事讲透。
一、为什么要把地理位置和历史行为结合起来做评分
传统CC防护大多只看一个指标——单位时间内的请求次数。比如一秒内同一个IP发了200个请求,直接封掉。但这种方式有两个致命问题:第一,正常用户在网络高峰期、使用共享出口IP时,也可能触发频率阈值被误杀;第二,现在的CC攻击很多是分布式的,攻击者用几千个不同IP轮流发请求,每个IP单独看都不超标,但总量能把服务器打垮。把地理位置和历史行为加进来,就是为了解决这两个痛点。
地理位置能帮你识别异常。比如一个IP归属地显示在境外,但你的业务只做国内市场,那这个IP的风险分就应该拉高。再比如同一个用户短时间内从北京跳到广州再跳到上海,物理上不可能,这就是明显的代理或僵尸网络特征。历史行为则能帮你建立信任基线。一个IP过去30天每天都在正常访问,突然某天请求量暴增,和一个全新IP上来就疯狂请求,风险等级完全不同。
二、综合评分降权的核心模型设计
评分模型是整套方案的大脑。一般来说,你需要设计一个加权评分体系,把多个维度的指标量化后汇总。常见的维度和权重分配如下:
第一,地理位置维度(权重建议20%-30%)。具体指标包括:IP归属地与业务目标区域的匹配度、IP是否属于已知数据中心/云服务商段、IP是否属于高风险地区(比如某些境外高发攻击源区域)、GeoIP数据库的置信度。如果IP归属地和用户常用地区不一致,扣分;如果是数据中心IP而非家庭宽带,扣分;如果是已知恶意IP段,直接拉满。
第二,历史行为维度(权重建议30%-40%)。这是最关键的部分。具体指标包括:该IP过去7天/30天/90天的平均请求频率、过去是否有过被标记的记录、Cookie或Session的持续时间、是否有正常的页面浏览路径(而不是直接刷接口)、用户代理(User-Agent)的稳定性。一个有长期正常行为记录的IP,即使短时间内请求量上升,也应该给予更高的信任分。
第三,实时行为维度(权重建议20%-30%)。包括当前会话的请求速率、请求的URL分布(是否集中在少数几个接口)、请求头的完整性、是否携带正常的Referer、是否有JavaScript挑战的通过记录等。
第四,设备与环境维度(权重建议10%-15%)。包括是否有正常的浏览器指纹、TLS指纹是否一致、是否使用了已知的自动化工具特征等。
最终的综合评分公式可以简化为:总分 = 地理位置分×W1 + 历史行为分×W2 + 实时行为分×W3 + 设备环境分×W4。当总分低于设定阈值时,执行降权(比如限速、返回验证码、延迟响应);当总分极低时,直接拦截。
三、技术实现方案与关键代码逻辑
落地这套方案,你需要几个核心组件:IP地理位置数据库、用户行为日志存储、实时评分引擎、降权执行模块。IP库可以用离线的MaxMind GeoLite2或者商业版,也可以用在线API查询。行为日志建议用Redis做实时缓存、用ClickHouse或Elasticsearch做长期存储分析。评分引擎可以自己写,也可以用现成的WAF规则引擎扩展。
下面给一个简化的评分引擎伪代码,展示核心逻辑:
function calculateRiskScore(ip, request) {
// 1. 获取地理位置信息
geoInfo = queryGeoIP(ip);
geoScore = 100;
if (geoInfo.country not in allowedCountries) geoScore -= 40;
if (geoInfo.isDatacenter) geoScore -= 20;
if (geoInfo.isKnownMalicious) geoScore = 0;
// 2. 获取历史行为数据
history = queryHistoryBehavior(ip, days=30);
avgReqPerMin = history.totalRequests / (30 * 24 * 60);
hasBadRecord = history.hasBeenFlagged;
sessionAge = history.firstSeenDays;
historyScore = 100;
if (avgReqPerMin > 10) historyScore -= 30;
if (hasBadRecord) historyScore -= 40;
if (sessionAge < 1) historyScore -= 20; // 新IP信任度低
// 3. 实时行为评分
realtimeScore = 100;
if (request.rate > 50/min) realtimeScore -= 30;
if (request.urlConcentration > 0.8) realtimeScore -= 25;
if (!request.hasValidReferer) realtimeScore -= 15;
// 4. 加权计算总分
totalScore = geoScore * 0.25 + historyScore * 0.35 + realtimeScore * 0.30;
// 5. 判定并执行降权
if (totalScore < 30) return BLOCK;
if (totalScore < 50) return CHALLENGE; // 返回验证码/JS挑战
if (totalScore < 70) return THROTTLE; // 限速
return ALLOW;
}
这段代码只是示意,实际生产环境中你还要考虑并发性能、缓存策略、评分衰减机制(比如历史行为的权重随时间递减)、以及白名单机制。特别要注意的是,评分引擎必须是高性能的,因为每个请求都要过一遍,建议用C++、Rust或者Go来写核心模块,Redis做状态缓存,避免每次都查数据库。
四、降权策略的分级执行机制
评分出来之后,不是只有"放行"和"拦截"两种结果,而是应该设计多级降权梯度。这样做的好处是:对可疑但不确定的流量不直接杀掉,而是先观察,既保护了业务,又减少了误杀。
第一级:观察模式(评分70-85分)。不做任何干预,但记录详细日志,标记为关注对象。如果后续行为恶化,自动升级。
第二级:轻度限速(评分50-70分)。把该IP的请求速率限制到正常值的30%-50%,比如原本一秒能发10个请求,现在限制到3个。同时返回正常响应,用户几乎无感知,但攻击者的效率大幅下降。
第三级:挑战验证(评分30-50分)。返回JavaScript挑战页面或者图形验证码,要求客户端执行一段JS代码或者完成人机验证。能通过的放行,通不过的继续降权。这一步能过滤掉大部分自动化脚本。
第四级:重度限速或阻断(评分0-30分)。直接把请求速率压到极低,或者返回503/403状态码,彻底阻断。这类IP大概率是攻击源或者严重异常。
五、实际部署中的关键注意事项
第一,GeoIP数据库要定期更新。IP归属信息是动态变化的,特别是云服务商的IP段经常调整,用过期的库会导致大量误判。建议每周同步一次,商业库可以用每日更新。
第二,历史行为数据的存储和查询要分层。最近1小时的行为放Redis,最近7天的放ClickHouse,超过7天的归档。查询时优先查Redis,命中就直接用,没命中再查长期存储。这样既保证速度又保证数据完整。
第三,要有白名单和灰度机制。把自己的监控IP、CDN回源IP、合作伙伴IP加入白名单,避免自家系统触发降权。新规则上线时先在小流量上灰度,观察误杀率和拦截效果,确认没问题再全量推。
第四,评分阈值要动态调整。不同业务场景的正常流量模式不一样,电商大促期间和平时的请求量差距可能有10倍。建议用机器学习或者自适应算法,根据历史正常流量的分布自动调整阈值,而不是写死一个固定数字。
第五,要做好日志和审计。每一次降权决策都要记录:IP、评分详情、触发的维度、执行的动作、时间戳。这不仅是排查问题的依据,也是后续优化模型的数据基础。
六、这套方案的优势和局限
优势很明显:精准度高,能区分正常高并发和攻击流量;抗分布式能力强,因为攻击者很难同时伪造地理位置和长期历史行为;误杀率低,对正常用户影响小;可扩展性好,新增维度只需要调整权重和加入评分项。
局限也要说清楚:依赖IP地理位置的准确性,如果攻击者使用和目标区域一致的代理IP,地理位置维度就失效了;历史行为数据对全新攻击IP没有参考价值,第一波攻击可能防不住;系统复杂度高,维护成本不低,需要专门的团队持续调优。
总的来说,CC防护中结合地理位置与历史行为的综合评分降权,是目前业界比较成熟且有效的防御思路。它不是银弹,不能100%防住所有CC攻击,但作为多层防御体系中的核心一环,能大幅提升攻击成本、降低误杀率、保护业务可用性。关键在于把模型设计好、数据维护好、阈值调优好,持续迭代才能真正发挥价值。
