短视频站点的CC攻击跟传统企业站完全不是一回事。传统站点怕的是流量打满带宽,短视频站点最怕的是接口被恶意刷到数据库连接池耗尽、转码队列阻塞、CDN回源被穿透。攻击者根本不需要打满你的总带宽,只要持续请求那些最消耗资源的动态接口——比如搜索、评论加载、用户主页作品列表、短信验证码下发——就能让核心服务雪崩。所以防护思路必须从“扛住流量”转向“识别并拦截恶意请求逻辑”。

先明确一个判断:短视频场景下,真正有威胁的CC攻击绝大多数不是海量IP的随机洪水,而是慢速、低频但精准打击高消耗接口的攻击。攻击者会模拟真实客户端行为,带上完整的UA、Referer甚至Cookie,请求频率控制在每IP每分钟几次到几十次,但目标全是那些会触发数据库复杂查询或缓存穿透的URL。这类攻击用传统的单IP频率限制很难拦住,因为阈值设高了拦不住,设低了误杀正常用户。

第一步:梳理高消耗接口清单并做差异化限流

你需要先把自己的接口按资源消耗程度分级。短视频站点里,视频流播放接口通常走CDN缓存,压力不大;但用户主页作品列表、评论分页、搜索联想词、推荐流刷新、关注列表这些接口,每次请求都可能涉及多表关联查询或实时计算。把这些接口单独拎出来,设置比普通页面严格得多的访问频率上限。例如普通页面允许单IP每分钟60次请求,搜索接口只允许10次,用户主页列表只允许20次。限流要基于IP加设备指纹加用户ID三个维度同时做,单独任何一个维度都可以被绕过。

实际部署时,建议在网关层用Redis做滑动窗口计数。不要用固定窗口,固定窗口在窗口边界处会被突发流量打穿。滑动窗口的代码逻辑大致如下:

# 滑动窗口限流伪代码
key = f"rate:{ip}:{fingerprint}:{api_path}"
now = time.time()
window = 60  # 窗口60秒
limit = 10   # 最多10次

pipe = redis.pipeline()
pipe.zremrangebyscore(key, 0, now - window)
pipe.zadd(key, {str(now): now})
pipe.zcard(key)
pipe.expire(key, window)
results = pipe.execute()
current_count = results[2]
if current_count > limit:
    return block_response()

这套逻辑的关键在于把时间戳作为有序集合的score,每次请求先清理窗口外的记录再计数,保证任意60秒内的请求量都被精确统计。对于短视频站点,建议对搜索、评论、用户主页三个接口的窗口和阈值单独配置,不要用一套参数覆盖所有接口。

第二步:识别攻击特征,不只是看IP

CC攻击者现在普遍使用代理池,IP维度只能作为辅助判断。你需要建立多维度的风险评分模型。以下几个特征在短视频站点场景下非常有效:

请求序列的时序分布。正常用户刷短视频,请求间隔是有节奏的,看完一个视频再刷下一个,间隔通常在几秒到几十秒之间。攻击脚本的请求间隔往往高度一致,比如精确到每3秒一次,或者呈现固定模式的循环。你可以计算单IP在短时间内请求间隔的标准差,标准差极小说明是脚本行为。

设备指纹与账号的绑定关系。攻击者可能换IP,但设备指纹和账号ID的组合是相对稳定的。如果一个设备指纹在短时间内关联了十几个甚至几十个不同的账号,或者一个账号在短时间内从十几个不同的设备指纹上登录访问,基本可以判定为恶意。短视频站点一定要在客户端SDK里植入稳定的设备指纹采集逻辑,包括硬件信息、系统版本、屏幕参数、字体列表等,生成唯一的指纹ID。

行为漏斗的转化率。正常用户进入用户主页后,大概率会点击某个视频观看,观看后可能点赞或评论。攻击脚本通常只请求列表接口,不触发后续的视频播放、点赞、关注等行为。你可以在服务端埋点,统计每个会话内“列表请求次数”与“实际播放次数”的比值。如果某个IP或设备指纹的列表请求量远大于播放量,比如请求了50次列表但只播放了2次视频,这个比例严重失衡,直接标记为高风险。

第三步:在边缘层做无状态挑战与JS运行时校验

很多CC攻击工具是基于Python、Go或者Node.js写的脚本,它们不会执行JavaScript,也不会维护完整的浏览器环境。你可以在CDN边缘节点对可疑请求返回一个带有JS挑战的页面,要求客户端执行一段简单的计算并回传结果。正常浏览器会自动完成这个过程,攻击脚本如果没有内置JS引擎就会卡住。

具体做法是:当某个IP或设备指纹的风险评分超过阈值时,边缘节点返回HTTP 200但内容是一段HTML和JS,JS里包含一个由服务端下发的随机数和一段混淆后的计算逻辑,客户端计算完成后带着结果重新请求原URL,边缘节点校验结果通过后放行并设置一个短期有效的Cookie。这个方案对用户体验影响很小,因为挑战过程通常在一秒内完成,而且只对可疑流量触发。

更进一步的方案是在客户端SDK里内置一个动态签名机制。每次请求时,SDK根据当前时间戳、请求路径、设备指纹和一个内置的密钥,生成一个签名参数附加在请求头里。服务端在网关层校验这个签名。攻击者即使抓包拿到了请求格式,也无法在没有逆向SDK的情况下生成正确的签名。签名算法要定期轮换,并且配合时间戳的有效期校验,防止重放攻击。

第四步:针对短视频场景的缓存策略优化

CC攻击之所以能对短视频站点造成巨大伤害,根本原因是高消耗接口的缓存命中率太低。攻击者往往会在请求参数里加入随机值或者不断翻页,让缓存全部失效,请求直接打到数据库。你需要从缓存设计上堵住这个漏洞。

对于用户主页作品列表这类接口,可以缓存前几页的热数据。比如前3页的作品列表缓存5分钟,第4页到第10页缓存1分钟,10页之后的请求直接返回空结果或者要求登录验证。正常用户很少会翻到10页之后,攻击脚本为了消耗资源往往会深度翻页,这个策略能有效拦截大部分恶意翻页行为。

搜索接口的缓存要区分热门词和长尾词。热门搜索词的结果缓存时间可以长一些,长尾词的结果缓存时间短一些,但对于那些明显是随机字符串或者无意义组合的搜索词,直接返回空结果并标记该IP的风险分数。你可以在搜索服务前面加一层布隆过滤器,快速判断一个搜索词是否在历史词库中出现过,没出现过的词直接降级处理。

评论接口的缓存要按评论ID做分片缓存,避免单个视频的热门评论被反复查询。同时对于评论的加载请求,如果请求的偏移量超过了该视频评论总数的某个比例,直接返回空列表,因为正常用户不会把评论从头翻到尾。

第五步:建立实时监控与自动化响应机制

防护CC攻击不是一次性配置完就结束了,攻击者会不断调整策略,你的防护规则也需要动态演进。建议在网关层输出结构化的访问日志,实时写入消息队列,然后用流处理框架做聚合分析。监控指标不要只看QPS和带宽,要重点关注以下比值:

高消耗接口的QPS与全站QPS的比值。正常情况下这个比值相对稳定,如果突然飙升,说明有人在集中刷某个接口。

非登录用户的请求占比。CC攻击通常不携带有效登录态,如果某个时间段内非登录用户对高消耗接口的请求占比异常升高,需要立即告警。

单IP的请求路径多样性。正常用户会访问多种不同的路径,攻击脚本往往只请求少数几个目标路径。你可以计算每个IP在5分钟内访问的不同URL路径数量,如果这个数量极低但请求总量很高,就是典型的定向刷接口行为。

自动化响应方面,建议做分级处置。风险评分中等的,触发JS挑战或者验证码;评分较高的,直接拉入黑名单并限制访问频率;评分极高的,在边缘节点直接丢弃请求并记录日志。黑名单要有自动过期机制,避免误伤后长时间无法恢复。同时要保留人工审核的通道,对于被误判的正常用户,可以通过客服渠道快速解封。

第六步:源站架构层面的兜底保护

即使前面所有防护层都被绕过,源站本身也要有自我保护能力。短视频站点的数据库连接池、转码服务、消息队列这些核心组件,都要设置独立的资源隔离和熔断机制。比如数据库连接池可以按业务模块拆分,评论服务用独立的连接池,用户服务用另一个连接池,某个模块被攻击时不会拖垮整个数据库。

对于转码和上传这类重资源操作,要做异步队列和优先级控制。CC攻击如果针对上传接口发起恶意请求,大量无效文件进入转码队列,会占用大量CPU和存储资源。你可以在上传接口增加文件类型校验、文件大小限制、单用户上传频率限制,并且在转码队列入口做流量整形,优先处理正常用户的转码任务。

还有一个容易被忽视的点是CDN回源保护。攻击者可能会绕过CDN直接攻击源站IP。你需要确保源站只允许CDN节点的IP段访问,其他来源的请求一律拒绝。同时源站要配置独立的防火墙规则,对非CDN来源的请求做严格限制。如果源站IP被泄露,要能快速切换。

短视频站点的CC攻击防护本质上是一场持续的对抗。攻击者会研究你的防护规则并寻找绕过方法,你需要基于行为分析、多维特征识别和动态挑战机制,构建一个能自适应演进的防护体系。把高消耗接口的差异化限流做好,把设备指纹和行为漏斗用起来,把缓存策略优化到位,再配合边缘层的JS挑战和源站的资源隔离,就能在绝大多数情况下把CC攻击的影响控制在可接受范围内。