CC攻击本质上拼的是资源消耗速度,攻击方用大量请求打满服务器连接数、CPU和带宽,而静态资源恰恰是消耗源站性能的大头。图片、CSS、JavaScript、字体文件这些内容一旦被反复请求,源站不仅要处理TCP握手、TLS握手,还要从磁盘读取文件再传输出去。真正有效的CC防御思路不是单纯去“识别攻击”,而是让攻击请求根本到不了需要消耗计算资源的位置。静态资源全缓存策略就是把静态文件提前推送到边缘节点,由边缘节点直接响应,源站只处理动态逻辑和API请求。这样即使攻击流量再大,打到的也是边缘缓存层,源站服务可以保持稳定。
很多人以为全缓存就是把文件放到CDN上这么简单,实际操作中会遇到大量细节问题。静态资源的更新机制、缓存命中率、回源策略、不同文件类型的缓存时间、URL参数处理、Cookie剥离、缓存键规范化,这些环节任何一处没做好,要么导致用户看到旧内容,要么导致缓存穿透直接回源。更关键的是,全缓存策略需要和CC防护规则配合使用,否则攻击者完全可以通过构造随机查询参数的方式绕过缓存,让每个请求都变成回源请求。
静态资源全缓存的核心前提:缓存键设计缓存键决定了边缘节点如何判断两个请求是否命中同一个缓存对象。默认情况下,很多CDN会把整个URL包括查询字符串作为缓存键,这意味着同一个CSS文件后面带上不同的参数就会被当成不同资源,攻击者只需要给URL加上随机参数,就能让缓存命中率降到接近零。正确的做法是对静态资源开启忽略查询字符串的缓存规则,或者只保留特定参数参与缓存键计算。比如版本号参数v=1.2.3需要保留,因为它用于区分文件版本,而时间戳、随机数这类参数必须忽略。
实际操作中建议对静态资源目录做统一配置:/static/、/assets/、/images/、/css/、/js/这些路径下的文件,缓存键只保留协议、域名和路径部分,完全忽略查询字符串。同时开启缓存键规范化,统一大小写、移除默认端口、排序查询参数。这样攻击者无论怎么构造随机参数,请求都会命中同一个缓存对象,攻击流量被边缘节点直接吸收。
缓存过期策略与文件更新机制全缓存策略最大的顾虑是文件更新后用户拿不到新版本。解决这个问题有两种主流方案:文件名指纹和短周期缓存加主动刷新。文件名指纹是在构建阶段给文件名加上内容哈希,比如app.a3f2c1.js,文件内容变了哈希就变,文件名自然不同,新请求会命中新文件,旧文件缓存过期后自动淘汰。这种方式可以放心设置超长缓存时间,一年甚至永久缓存都不会有问题。
如果项目无法改造文件名指纹机制,就需要采用短周期缓存配合主动刷新。HTML文件设置不缓存或极短缓存,确保用户每次都能拿到最新的资源引用地址,而静态资源文件设置中等长度的缓存时间,比如一小时或几小时。发布新版本时通过CDN提供的缓存刷新接口主动清除旧缓存。这种方案的缺点是发布后短时间内可能有用户命中旧缓存,但配合版本号参数可以做到平滑过渡。需要特别注意的是,刷新操作要精确到具体文件或目录,避免全站刷新导致源站瞬间承受大量回源请求。
缓存命中率监控与穿透防护全缓存策略上线后必须持续监控缓存命中率。正常情况下静态资源的缓存命中率应该保持在95%以上,如果命中率突然下降,大概率是遇到了缓存穿透攻击或者配置变更导致缓存键异常。攻击者常用的穿透手法包括:随机查询参数、随机路径大小写、URL编码变形、添加随机请求头。前面提到的忽略查询字符串可以解决第一类问题,对于路径大小写和编码变形,需要开启缓存键规范化功能,让边缘节点在计算缓存键之前先对URL做标准化处理。
还有一种更隐蔽的穿透方式是攻击者直接请求源站IP地址,绕过CDN边缘节点。这种情况需要在源站防火墙层面做访问控制,只允许CDN节点的IP段访问80和443端口,其他来源一律拒绝。同时源站可以配置强制跳转规则,任何直接访问源站域名的请求都重定向到CDN域名。这样即使攻击者拿到源站真实IP,也无法直接对源站造成压力。
全缓存策略下的CC防御规则设计静态资源全缓存本身就能吸收大部分CC攻击流量,但边缘节点仍然需要处理请求,如果攻击流量足够大,边缘节点的带宽和连接数也会被打满。所以全缓存策略必须配合边缘层的访问控制规则。第一层是IP频率限制,针对单个IP设置合理的请求速率阈值,超过阈值后返回429状态码或者直接断开连接。第二层是UA过滤,大量CC攻击工具使用固定或异常的User-Agent,可以通过正则规则直接拦截。第三层是行为分析,对请求序列做模式识别,比如同一个IP在极短时间内请求大量不同路径的静态资源,这不符合正常浏览器行为,可以直接标记为攻击源。
规则设计的关键是避免误伤正常用户。IP频率限制的阈值要结合业务实际情况设定,静态资源页面通常一次加载会请求几十个文件,阈值设置过低会导致正常用户被拦截。建议采用滑动窗口算法而不是固定窗口算法,这样能更准确地识别突发流量。对于移动网络用户,由于运营商NAT导致大量用户共享出口IP,频率限制规则要更加宽松,或者结合Cookie和浏览器指纹做辅助判断。
源站保护的最后一道防线:连接数限制与超时控制即使边缘层做了全缓存和访问控制,源站仍然需要做好自身的防护配置。CC攻击的最终目标是耗尽源站资源,所以源站Web服务器层面的连接数限制和超时控制至关重要。Nginx可以通过limit_conn模块限制单个IP的并发连接数,通过limit_req模块限制请求速率。对于静态资源,源站可以开启sendfile和tcp_nopush优化文件传输效率,减少CPU占用。同时设置合理的keepalive_timeout值,避免攻击者通过大量空闲连接占用连接池。
还有一个容易被忽略的细节是源站的错误页面处理。CC攻击期间源站可能返回大量404、403、500错误,这些错误页面的生成也会消耗资源。建议为错误页面设置静态文件响应,避免动态生成错误内容。同时关闭源站的目录浏览功能,防止攻击者通过遍历目录发现更多可攻击的资源路径。
实际部署中的配置示例以Nginx作为源站服务器为例,静态资源全缓存配合CC防护的典型配置如下:
# 静态资源缓存规则
location ~* \.(jpg|jpeg|png|gif|webp|svg|css|js|woff|woff2|ttf|eot|ico)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
add_header X-Content-Type-Options "nosniff";
access_log off;
limit_conn per_ip 10;
limit_req zone=static burst=20 nodelay;
try_files $uri =404;
}
# 连接数限制配置
limit_conn_zone $binary_remote_addr zone=per_ip:10m;
limit_req_zone $binary_remote_addr zone=static:10m rate=50r/s;
# 源站IP访问限制
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
这段配置的核心思路是:静态资源文件设置长缓存时间并标记immutable,告诉浏览器和中间缓存节点该文件在缓存期内不会变化,不需要重新验证。同时限制单IP并发连接数和请求速率,防止单个攻击源占用过多资源。源站层面只允许内网和CDN回源IP访问,其他来源直接拒绝。
全缓存策略的适用边界与注意事项静态资源全缓存策略并非适用于所有场景。如果网站有大量个性化内容,比如用户上传的图片需要实时处理或鉴权,这些资源就不能简单地全缓存。对于需要登录后才能访问的静态文件,需要在边缘层做鉴权判断,只有通过验证的请求才允许命中缓存。这种情况下可以使用边缘节点的Token验证功能,在URL中携带短期有效的签名参数,边缘节点验证签名通过后再响应缓存内容。
另外需要注意HTTPS证书的部署位置。全缓存策略要求边缘节点能够直接响应HTTPS请求,所以证书需要部署在边缘节点上。源站和边缘节点之间的回源连接可以使用HTTP以降低源站的计算开销,但前提是回源链路是安全的专线或内网。如果回源走公网,建议保持HTTPS回源,防止中间人攻击篡改内容。
全缓存策略实施后,源站的带宽消耗会大幅下降,正常情况下源站只需要处理动态请求和缓存未命中时的回源请求。根据实际项目经验,静态资源占比高的网站实施全缓存后,源站带宽消耗可以降低80%以上,CC攻击的防护效果提升显著。攻击者面对边缘节点的缓存层,即使发起大规模请求,大部分流量在边缘就被响应,真正到达源站的请求量只有正常水平的零头。
最终要强调的是,CC防御静态资源全缓存策略不是一次配置就结束的工作。攻击手法在持续演变,缓存规则和防护规则需要根据实际流量数据不断调整。定期分析缓存命中率报告、回源日志和攻击拦截记录,找出穿透点并针对性优化,才能让这套策略长期有效运转。
