CC攻击打在评论区,本质不是要打垮整台服务器,而是用高频、看似合法的请求把“发表评论”“加载评论列表”“提交点赞”这几个轻量级接口拖到超时。攻击者很清楚,企业站的搜索入口、支付流程往往有风控和限流,但评论区因为要兼顾用户体验和SEO收录,反而成了防护最薄弱的地方。恶意刷屏不只是灌垃圾广告,更常见的是用代理池轮换IP,以每秒几十到几百次的频率请求评论提交接口,造成数据库连接池耗尽,正常用户点“发布”一直转圈,或者页面直接502。
先要分清你遇到的是哪一种“刷”。一种是内容型刷屏,攻击者用脚本批量提交“代开发票”“博彩链接”这类垃圾评论,目的是污染页面内容和外链。另一种是访问型CC,它根本不提交内容,只反复请求评论分页URL、评论接口或者搜索评论的AJAX地址,让后端频繁查库。后一种更隐蔽,因为请求头、URL都正常,单看日志就像普通用户在翻页。判断方法也简单:如果某个评论接口的QPS突然比平时高出5到10倍,但UV没有同步增长,且大量请求集中在同一个URL模式上,基本可以确定是CC攻击。
第一层防护:在边缘节点做请求特征过滤
企业站如果有CDN,一定要把评论相关的写操作接口单独配置。读接口比如评论列表可以做缓存,CDN直接返回静态化内容,源站压力能降七成以上。写接口不能缓存,但可以在边缘层做三件事:一是限制单IP对评论提交接口的请求频率,比如每60秒最多3次;二是校验User-Agent和Referer,脚本请求往往UA缺失或者Referer为空;三是开启浏览器质询,对短时间内高频访问同一评论URL的IP弹出JS跳转验证。这些规则在CDN控制台就能配,不用改业务代码。
没有CDN的情况,可以在Nginx层直接写限制。针对评论接口的location块,用limit_req_zone按IP限速,再用limit_conn限制并发连接。下面这段配置可以放在http块里,针对评论提交和评论列表接口做基础限流:
# 在http块中定义限流区域
limit_req_zone $binary_remote_addr zone=comment_write:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=comment_read:20m rate=30r/m;
limit_conn_zone $binary_remote_addr zone=comment_conn:10m;
# 在server或location块中应用
location /api/comment/submit {
limit_req zone=comment_write burst=3 nodelay;
limit_conn comment_conn 5;
proxy_pass http://backend;
}
location /api/comment/list {
limit_req zone=comment_read burst=10 nodelay;
proxy_pass http://backend;
}
这段配置的意思是,评论提交接口每个IP每分钟最多5次,突发最多3次;评论列表每分钟30次,突发10次。真实用户写评论不会一分钟超过5条,正常翻页也不会超过30次。但要注意,企业内网出口如果共用IP,比如所有员工从一个公网IP出去,这个阈值要适当调高,否则会误伤。
第二层防护:在应用层做行为识别和业务限流
边缘限流只能挡住简单脚本,攻击者用代理池轮换IP就能绕过。这时候必须在应用层识别行为模式。评论提交接口在收到请求后,不要立刻写库,先做几个检查:
第一,检查表单提交时间和页面加载时间的差值。正常用户从打开文章到写完评论,至少需要30秒到几分钟。如果页面加载后2秒内就提交了评论,大概率是脚本。可以在页面渲染时生成一个隐藏的token,里面包含时间戳,提交时后端验证这个时间差。攻击者如果直接请求接口拿不到token,或者token过期,直接拒绝。
第二,对评论内容做相似度检测。恶意刷屏的内容往往是同一段话复制粘贴,或者只改几个数字。可以在Redis里维护一个评论内容的MD5集合,如果相同内容在短时间内出现超过3次,直接标记为垃圾评论并延迟发布。更进一步的,用SimHash计算文本相似度,相似度超过90%的评论自动进入审核队列。
第三,设备指纹和账号维度限流。IP可以换,但浏览器指纹、设备ID、登录账号不容易换。如果站点有用户体系,评论接口必须登录后才能提交,然后按用户ID限流,比如每个账号每小时最多10条评论。未登录用户如果要评论,可以要求输入图形验证码或滑动验证。设备指纹可以通过前端JS采集Canvas指纹、屏幕分辨率、时区、插件列表等组合生成,即使攻击者清Cookie、换IP,指纹一致就能识别为同一设备。
第三层防护:数据库和缓存层的压力隔离
CC攻击打到评论接口,最终压力会传导到数据库。如果评论表有几百万行数据,每次查询都走全表扫描,不需要多大流量就能把库打挂。所以评论表的设计和索引非常关键。评论列表查询一定要走索引,比如按文章ID加评论状态加创建时间的联合索引。评论总数可以单独维护一个计数字段或者Redis计数器,不要每次都用COUNT(*)实时统计。
更彻底的方案是读写分离加缓存。评论列表这种读多写少的场景,完全可以缓存到Redis里,设置5到10分钟的过期时间。攻击者刷评论列表时,请求在Redis层就被挡住,根本不碰数据库。评论提交成功后,通过消息队列异步更新缓存和数据库,前端可以先返回“评论成功,正在审核”,这样即使后端写库有延迟,用户体验也不受影响。消息队列本身还能削峰填谷,攻击者瞬间灌入的大量写请求会被队列缓冲,后端按固定速率消费,数据库不会被打爆。
针对恶意刷屏内容的专项处理
如果攻击者已经成功写入了大量垃圾评论,除了限流,还要快速清理和拦截。建议在评论发布流程中加入多层过滤:第一层是关键词黑名单,包含“博彩”“代开发票”“加微信”等常见垃圾词,命中即拒绝或进入审核;第二层是正则表达式,识别手机号、微信号、URL链接,正常用户评论里很少带这些;第三层是行为评分,结合账号注册时间、历史评论数、被举报次数给用户一个信用分,信用分低的用户评论默认进入人工审核。
对于已经产生的垃圾评论,不要手动一条条删。可以在数据库里按特征批量标记,比如评论内容包含特定关键词、同一IP提交、创建时间集中在某个时间段,这些条件组合起来批量更新状态为“已删除”。同时把攻击者的IP段、账号ID、设备指纹加入黑名单,后续请求直接拦截。黑名单可以放在Redis里,应用层每次请求先查黑名单,命中就返回403。
监控和应急响应
防护做完不等于高枕无忧。评论区被攻击时,最早能发现问题的是监控。建议对评论相关接口设置三个维度的告警:QPS突增、错误率上升、响应时间变长。比如评论提交接口平时QPS是5,突然涨到50,持续1分钟就告警;评论列表接口P99响应时间超过500毫秒就告警。告警通道可以接企业微信、钉钉或者邮件,保证运维能在5分钟内收到通知。
应急响应时,第一步是确认攻击类型和规模,看日志里攻击源的IP分布、请求特征。如果攻击源集中在少数几个IP段,直接在防火墙或CDN上封禁这些段。如果攻击源是分散的代理池,就启用更严格的限流策略,比如把评论接口的限速从每分钟5次降到每分钟1次,同时开启全站验证码。最极端的情况下,可以暂时关闭评论功能,只保留评论展示,等攻击过去再恢复。关闭评论对SEO的短期影响有限,但如果评论接口被打挂导致整站不可用,损失会大得多。
还有一个常被忽略的点:评论区的分页URL如果设计不合理,会被攻击者利用来放大攻击效果。比如评论列表支持page参数,page=999999时后端仍然去查库,这种请求多了就会拖垮数据库。应该在应用层对page参数做边界校验,超过最大页数直接返回空结果,并且对分页接口做缓存,相同的page请求直接走缓存。
最后强调一点,评论区防护的核心不是堆设备,而是把“正常用户能顺畅评论”和“恶意请求被快速识别”这两件事同时做到。过度限流会伤害真实用户的互动意愿,评论量下降反过来影响页面活跃度和SEO表现。所以策略要分层、有梯度:边缘层挡掉明显异常流量,应用层识别复杂攻击,数据库层保证核心数据不被打穿。三层配合起来,评论区既能保持开放,又不会被CC攻击当成突破口。
