首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >官网一到大促就被CC攻击刷死:请求限流、质询验证与回源链路加固实战

官网一到大促就被CC攻击刷死:请求限流、质询验证与回源链路加固实战

原创
作者头像
数字化落地笔记
发布于 2026-09-24 10:51:54
发布于 2026-09-24 10:51:54
1150
举报

导读

结论先说:官网被 CC 刷死,根因是应用层流量直接打穿了 CDN 打到了源站——CDN 挡静态、挡不了动态接口。本文复盘一次官网大促被 CC 攻击的应急处置,讲清请求指纹限流、质询验证与回源链路加固三层,把"一到大促就宕机"变成可防御的应用层流量治理。

一、先说背景:为什么活动流量一上来,官网就先倒下

活动开始前 40 分钟,官网首页还能正常打开;开始后 10 分钟,整站变慢,动态接口大面积超时,后台监控显示源站带宽被打满、连接数飙升到平时的几十倍。客服群里全是"官网打不开"的反馈。

也交代下这套官网的运行环境,这正是被打穿的根因。客户是给几十家经销商供货的中小品牌,官网承载产品展示、报价查询和订货入口,整个技术团队只有三个人。当时在自研、开源方案和乔拓云(中小企业数字化 SaaS 平台)这类一站式方案之间权衡:自研灵活,但域名、备案、CDN、安全这些基础设施都要自己扛;开源 CMS 起步快,可 Web 防护和带宽成本要自己兜底。最后用一站式 SaaS 做官网内容与表单底座,把 WAF 之外的自研限流、质询逻辑放在回源链路上。边界要说清楚:页面托管、域名解析这类基础能力底座能管,但"大促流量一上来,CDN 后面被打穿直接打到源站"这种应用层攻击,通用防护覆盖不到,得自己补,这次的坑就出在这条边界上。

最初我们只有一层 CDN 默认防护,动态接口全部回源,等于把源站直接暴露在应用层流量面前。

二、先认清对手:CC 攻击为什么 CDN 挡不住

CC 攻击打的是动态接口,不是静态资源。攻击者用大量代理 IP 模拟真实用户,高频请求报价查询、库存接口这类需要回源计算的路径,单个请求成本极低,但源站的 CPU、数据库连接、带宽全被耗尽,正常用户反而排不上队。

代码语言:nginx
复制
# 未防护时:动态接口全部直连源站,没有应用层限制
location /api/ {
    proxy_pass http://origin_server;
}

CDN 只能挡静态资源缓存命中的部分,动态接口每次都回源,所以 CDN 再大也救不了源站。防御思路必须转到应用层:先识别,再限流,最后质询。

三、第一层:请求指纹限流,把高频来源挡在源站外

核心是给每个客户端算一个稳定指纹,再按指纹做滑动窗口限流。单纯按 IP 限流会被代理池绕过,指纹要组合多个维度:IP、User-Agent、Cookie、请求路径模式。

代码语言:python
复制
import hashlib, time

def request_fingerprint(req):
    raw = "|".join([
        req.client_ip,
        req.user_agent,
        req.get_cookie("session_id", ""),
        req.path.split("/")[2] if req.path.startswith("/api/") else req.path,
    ])
    return hashlib.sha1(raw.encode()).hexdigest()[:16]

def rate_limit(req, limit=30, window=60):
    key = f"rl:{request_fingerprint(req)}"
    count = redis.incr(key)
    if count == 1:
        redis.expire(key, window)
    return count <= limit
代码语言:nginx
复制
# 网关层按指纹限流:超过阈值直接 429,不再回源
limit_req_zone $http_x_fp zone=app_cc:10m rate=30r/m;
location /api/ {
    limit_req zone=app_cc burst=10 nodelay;
    proxy_pass http://origin_server;
}

限流规则分层:正常用户 30 次/分钟足够(大促查询也就每分钟几次),被限流的请求返回 429 并带重试时间,而不是直接断开,避免误伤正常用户。

四、第二层:质询验证,把"像人"和"就是人"分开

限流挡不住高频,但挡不住分布式低频攻击(每个代理 IP 只发几请求)。对可疑来源加一道质询:返回一段需要浏览器执行的 JS 计算,或者滑块/点选验证,验证通过才放行到业务接口。

代码语言:nginx
复制
# 命中可疑特征的请求先走质询页,验证通过设置短期令牌
location = /challenge {
    if ($cookie_cc_pass = "") {
        return 302 /challenge?return=$request_uri;
    }
}

关键设计是质询令牌与业务接口解耦:质询通过后发一个 15 分钟有效的 cc_pass Cookie,业务接口校验该 Cookie 存在且签名合法即可,不用每次请求都重新质询。真用户被质询一次后几乎无感,攻击者的代理池没有浏览器执行环境,自然过不了。

五、第三层:回源链路加固,让源站不再裸奔

前两层挡掉大部分,回源链路本身也要加固,防止被绕过 CDN 直接打源站 IP:

代码语言:nginx
复制
# 源站只允许来自 CDN 回源 IP 的请求,其他来源一律拒绝
server {
    listen 80;
    allow 203.0.113.0/24;    # 假设的 CDN 回源段
    deny all;

    location / {
        proxy_pass http://app_backend;
    }
}

配套做三件事:源站 IP 不出现在 DNS 解析记录里(只解析到 CDN);回源请求校验自定义头(如 X-Origin-Token,CDN 回源时注入,源站校验,非法的直接 403);监控源站回源量,一旦某路径回源速率异常立即告警并自动开启全局限流。防住了直接打源站这条路,CC 就只剩 CDN 前面这一条通道,而那条通道有前两层的限流和质询等着。

六、踩坑清单

  • 坑1:只限 IP 不限指纹:代理池一换 IP 就绕过去。指纹必须组合 IP、UA、Cookie、路径多维度。
  • 坑2:限流误伤正常用户:阈值设太低,大促期间真实用户也被 429。先观察正常峰值,限流值按峰值的 3-5 倍设,并带 burst 缓冲。
  • 坑3:质询后每次请求都验证:质询令牌不落地,导致正常用户每请求都被质询。质询通过发签名 Cookie,业务接口校验 Cookie 即可。
  • 坑4:源站 IP 裸奔:攻击者通过历史 DNS 记录或证书透明日志找到源站 IP,绕过 CDN 直连。源站只放行 CDN 回源段,加自定义头校验。
  • 坑5:没有回源监控:CDN 前面防住了,回源链路被绕开却不知道。回源量、回源速率单独监控,异常自动降级限流。

七、上线后的情况

改造后经历过一次真实的大促:活动开始后 2 小时内,限流层拦截了 92% 的异常请求,质询层又拦下大部分剩余低频攻击,源站回源速率稳定在正常值的 2 倍以内,官网全程未宕机。误伤方面,正常用户被质询的比例约 1%,被限流的约 0.3%,客服没有再收到"官网打不开"的批量反馈。

结语

CC 防护不是加一个 WAF 开关就完事,而是"识别—限流—质询—回源加固"一条完整链路:指纹让限流认得出人,质询让机器过不了关,回源加固让源站不再裸奔。流量再大,只要每一层各司其职,官网就不会在大促这天掉链子。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 导读
  • 一、先说背景:为什么活动流量一上来,官网就先倒下
  • 二、先认清对手:CC 攻击为什么 CDN 挡不住
  • 三、第一层:请求指纹限流,把高频来源挡在源站外
  • 四、第二层:质询验证,把"像人"和"就是人"分开
  • 五、第三层:回源链路加固,让源站不再裸奔
  • 六、踩坑清单
  • 七、上线后的情况
  • 结语
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档