资讯类网站遭遇CC攻击时最典型的特征不是带宽跑满,而是服务器CPU和数据库连接数瞬间飙升,页面打开速度从几百毫秒退化到十几秒甚至直接502。攻击者通常瞄准搜索页、列表页、用户评论接口这类动态请求,因为这些页面每次访问都要查数据库,单次请求的资源消耗是静态页面的几十倍。真正要解决的是把恶意流量和正常用户区分开,而不是简单地堆硬件带宽。
第一道防线应该放在Web服务器层。Nginx有两个模块必须配置到位:limit_req和limit_conn。limit_req控制请求速率,limit_conn控制并发连接数。很多运维只配了limit_req,但CC攻击常用的是低速率慢连接,每个IP的请求频率不高,却同时保持几百个连接慢慢发请求,这时候limit_conn才是关键。具体配置思路是按路径区分策略,搜索接口和评论接口单独设置更严格的阈值。
http {
# 定义共享内存区域,用于存储请求状态
limit_req_zone $binary_remote_addr zone=search_zone:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
server {
location /search {
# 搜索接口每秒最多5个请求,突发不超过10个
limit_req zone=search_zone burst=10 nodelay;
# 单IP并发连接数限制为3
limit_conn conn_zone 3;
proxy_pass http://backend;
}
location /comment {
limit_req zone=search_zone burst=5 nodelay;
limit_conn conn_zone 2;
proxy_pass http://backend;
}
}
}
这里有一个容易被忽略的细节:limit_req_zone的key用$binary_remote_addr而不是$remote_addr,前者是二进制格式,内存占用减少一半以上。如果网站前面挂了CDN或负载均衡,直接取remote_addr拿到的是节点IP,所有用户会被当成同一个来源,这时候必须改用X-Forwarded-For或X-Real-IP,但要确保这些头信息只来自可信的代理节点,否则攻击者可以伪造头信息绕过限制。
第二道防线是应用层的请求合法性校验。资讯类网站最常见的CC攻击目标是搜索功能,攻击者会随机生成大量关键词反复请求搜索接口,每个请求都触发一次全文检索。解决方案是给搜索接口加上前置校验:检查User-Agent是否合法、是否携带正常的Referer、是否支持Cookie回传。更有效的方法是在搜索请求前设置一个JavaScript挑战,正常浏览器会自动执行JS并携带计算结果,而大多数CC攻击脚本不具备JS执行能力。这个逻辑可以用Nginx的lua模块实现,也可以在应用层做。
第三层防护是动态IP信誉库。单纯依赖速率限制会误伤正常用户,尤其是企业出口或学校出口这种NAT场景,几百人共用一个公网IP,正常访问频率本身就很高。建议在Nginx层集成一个IP信誉检查,优先放行搜索引擎爬虫的已知IP段,对数据中心IP段和云服务商IP段提高警惕。攻击流量通常来自租用的VPS或肉鸡,这些IP段有规律可循。维护一个本地黑名单数据库,通过定时任务从公开威胁情报源同步,再配合Nginx的geo模块做拦截,命中黑名单的直接返回444。
geo $blocked_ip {
default 0;
include /etc/nginx/blocked_ips.conf;
}
server {
if ($blocked_ip) {
return 444;
}
}
第四层是缓存策略的调整。资讯类网站的内容更新频率其实不高,文章详情页完全可以做短时缓存。很多站点担心缓存导致用户看不到最新评论,其实可以把页面拆分成静态部分和动态部分,正文内容缓存30秒到5分钟,评论区域用异步加载。当CC攻击打过来时,如果请求命中了缓存层,后端压力直接降为零。Nginx的proxy_cache配合Cache-Control头可以做到这一点,关键是把搜索接口、用户中心这类个性化页面排除在缓存之外。
location /article {
proxy_cache news_cache;
proxy_cache_valid 200 60s;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_bypass $cookie_user_id;
proxy_pass http://backend;
}
第五层是数据库层面的保护。CC攻击的最终目的是耗尽数据库连接,即使前面几层拦截了大部分请求,仍可能有漏网之鱼。数据库连接池必须设置合理的最大连接数和超时时间,避免慢查询占满连接。资讯类网站最常见的慢查询是未走索引的全表扫描,攻击者会故意构造特殊参数触发这类查询。建议开启数据库的慢查询日志,定期分析并优化索引。同时给数据库账号设置只读和读写分离,搜索和列表查询走只读副本,主库只负责写入,这样即使查询被攻击,也不会影响文章发布和评论写入。
第六层是日志监控与自动化响应。CC攻击的流量模式有规律,比如某个时间段内特定路径的请求量突然增长、某个IP段的请求占比异常、User-Agent集中在少数几种。通过分析Nginx访问日志,可以快速定位攻击特征。建议部署一个轻量级的日志分析脚本,每分钟统计请求量Top的IP和路径,当某个IP的请求量超过阈值时自动调用Nginx的API将其加入临时黑名单。这个临时封禁可以设置过期时间,比如10分钟后自动解封,避免长期误封。
# 示例:统计过去1分钟请求量最高的前20个IP
tail -n 100000 /var/log/nginx/access.log | \
awk '{print $1}' | sort | uniq -c | sort -rn | head -20
第七层是架构层面的弹性设计。资讯类网站平时流量平稳,遇到热点事件时流量会暴涨,CC攻击往往也选择热点事件期间发动,因为此时流量基数大,攻击更容易混在正常流量中。建议将搜索服务、评论服务、推荐服务拆分成独立的微服务,各自有独立的限流和降级策略。当某个服务被攻击时,可以单独对该服务进行熔断降级,比如搜索接口暂时返回空结果或提示稍后再试,而不是整个网站崩溃。这种牺牲局部可用性保全整体的策略,在应对高强度CC攻击时非常有效。
还有一个容易被忽视的点是HTTPS握手层面的CC攻击。攻击者发起大量TLS握手请求但不完成握手过程,消耗服务器的CPU资源。Nginx可以通过ssl_reject_handshake指令直接拒绝SNI不匹配的连接,同时调整ssl_session_cache的大小和超时时间,减少重复握手的开销。对于不需要HTTPS的静态资源,可以单独设置一个HTTP端口来分流,但这只适用于对安全性要求不高的图片和CSS文件。
最后要强调的是,CC攻击防护是一个动态博弈的过程。攻击者会不断调整策略绕过防护,比如更换IP池、模拟更真实的浏览器行为、降低请求频率拉长攻击周期。所以防护策略不能是一次性配置完就高枕无忧,需要持续观察流量变化,定期复盘攻击事件,更新规则。建议每周检查一次Nginx错误日志和访问日志的异常模式,每月做一次压力测试验证防护策略的有效性。资讯类网站的核心资产是内容和服务可用性,把防护做到位,才能在攻击来临时保证用户正常访问。
