DDoS攻击的核心思路很简单:用海量的垃圾流量把目标的带宽或者连接资源耗尽。面对动辄几百G的攻击流量,单机防御几乎没有意义,因为流量在到达你的服务器之前就已经把机房上游链路打满了。这就是为什么大型互联网公司几乎都把业务挂在CDN后面——CDN天生就是分布式的,它有成百上千个边缘节点分布在全球各地,攻击流量会被分散到整个网络中消化,而不是集中砸向某一个点。这篇文章就来拆解CDN做DDoS清洗的完整原理,看看边缘节点到底是怎么吸收和过滤攻击流量的。

边缘节点为什么能吸收超大流量
CDN抗DDoS的第一层防御不是什么智能算法,而是纯粹的架构优势。传统的单点服务器防御,相当于一个人扛着一根水管接洪水;而CDN的架构是把洪水引进一片湖泊群,每个湖泊分担一点,水位自然就上不去了。
这里面有一个关键技术在起作用,叫Anycast(任播)。简单说,同一个IP地址会同时宣告给全球多个机房。当攻击者向这个IP发起流量时,BGP路由协议会自动把流量引导到网络拓扑上最近的节点。攻击源在全球分布越广,流量就被切得越碎——一个500G的攻击,如果攻击源分布在五十个国家,可能每个区域的CDN节点只需要承受几十G,这个量级对现代CDN节点来说完全在承受范围内。Cloudflare之所以敢宣传无限量抗D,底层依赖的正是这种架构。
除了Anycast分流,边缘节点的容量储备也很关键。大型CDN厂商的边缘节点通常接入多个运营商的骨干网,单节点带宽容量普遍在几十G到上百G级别,而且节点之间可以互相兜底。当某个区域的节点压力过大时,调度系统可以把该区域的流量引导到其他健康节点,实现二次分发。这种水平扩展能力是单机硬件防火墙永远做不到的。
攻击流量是如何被识别出来的
吸收流量只是第一步,光能扛住还不够,必须把恶意流量识别出来并丢弃,否则脏流量会顺着回源链路打到源站。识别的核心是流量特征分析,不同类型的攻击有不同的指纹。
先看SYN Flood这类连接型攻击。正常用户完成TCP握手需要三次握手,攻击者发送大量伪造源IP的SYN包却从不回应SYN+ACK,导致服务器上堆积大量半开连接。CDN边缘节点会维护连接状态表,统计每个源IP的并发半开连接数和新建连接速率,一旦超过阈值就触发清洗动作,比如启用SYN Cookie机制。开启SYN Cookie后,节点不保存半开连接状态,而是把状态信息编码进SYN+ACK的序列号里返回给客户端,只有真正完成握手的合法连接才会被分配资源,伪造源的连接根本走不到下一步。
再看UDP反射放大攻击,比如DNS反射、NTP的monlist反射、memcached反射。这类攻击的特征是攻击流量伪造了受害者的IP去向第三方服务发起请求,第三方把放大后的响应发给受害者。CDN侧识别这类攻击主要靠几个维度:一是包长分布异常,反射攻击的响应包大小往往高度一致;二是源端口集中,比如DNS反射的源端口几乎全是53;三是IP信誉库匹配,已知的开放反射器IP会被直接拦截。下面是一段简化的检测逻辑伪代码,展示多维特征打分的思路:
def score_packet(pkt):
risk = 0
# 源IP信誉检查:已知反射器或僵尸网络节点直接加分
if pkt.src_ip in ip_reputation_db:
risk += 50
# UDP源端口特征:DNS/NTP/memcached反射端口
if pkt.proto == "UDP" and pkt.src_port in (53, 123, 11211):
risk += 20
# 包长高度一致是反射攻击的典型指纹
if pkt.length in amplification_signature_lengths:
risk += 20
# 新建速率超过该源IP的历史基线
if pkt.src_ip.pps > baseline(pkt.src_ip) * 10:
risk += 10
return risk # 总分超过阈值则丢弃该包还有一类是应用层的HTTP Flood,比如CC攻击。这种攻击的每个请求在TCP层面看都是完全合法的,单靠网络层特征识别不出来。这时候就要看行为特征:请求频率是否远超正常用户、是否不加载静态资源、是否不携带正常的Cookie和Referer、是否用同一套UA批量请求动态接口。主流CDN会结合这些信号计算风险分,配合设备指纹和JS挑战来区分真人和机器人。
多层清洗机制的协同工作
识别出恶意流量后,怎么过滤也分层次。一个成熟的CDN清洗体系通常是漏斗式的,从网络层到应用层逐级收紧。
第一层是访问控制和速率限制。CDN控制台上配置的CC防护规则、IP黑白名单、地域封禁都属于这一层。它的特点是规则明确、执行成本低,比如限制单个IP每秒最多100个请求,超出的直接返回429或者静默丢弃。速率限制对突发性的低强度攻击最有效,配置起来也最简单:
# 边缘节点速率限制配置示例(Nginx语法参考)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
server {
location /api/ {
# 突发容忍200个请求,超出部分直接拒绝
limit_req zone=api_limit burst=200 nodelay;
limit_req_status 429;
proxy_pass http://origin_backend;
}
}第二层是协议合规性校验。边缘节点会主动验证客户端的协议行为是否符合标准,比如TCP握手是否完整、HTTP请求头是否合法、TLS握手能否正常完成。大量的攻击工具为了追求性能会走捷径,比如跳过完整的TLS握手或者发送畸形的HTTP头,这些在协议校验这一关就会被卡掉。
第三层是人机挑战,这是应用层清洗的杀手锏。当节点怀疑某个会话是机器人时,会返回一段JavaScript挑战代码,要求浏览器执行计算并携带结果重新请求。真实浏览器会正常执行并重试,而绝大多数攻击脚本因为不具备完整JS执行环境,会卡在这一步。对于更高强度的对抗,还有二次验证码、设备指纹绑定等手段。挑战的好处是不需要提前知道攻击特征,属于无差别的被动验证,误伤率低。
源站保护与回源链路的实战要点
CDN清洗做得再好,如果攻击者能绕过CDN直接打源站,一切防御都是白费。这一点经常被忽视,也是很多企业被打了才发现源站IP早就泄露的原因。
第一要务是隐藏源站真实IP。源站IP可能通过历史DNS解析记录、邮件头、SSL证书查询、子域名扫描等途径泄露,上了CDN之后建议更换源站IP,并且在源站的防火墙上只放行CDN的回源网段。以云服务器安全组为例,入站规则只保留CDN厂商公布的回源IP段,其他全部拒绝,这样即使IP泄露,攻击流量也进不来。
第二是启用回源验证。常见的做法是CDN在回源请求中携带一个自定义头,比如携带一串密钥:
GET /api/data HTTP/1.1 Host: origin.example-ipipp.com X-CDN-Auth: 8f3a2b1c9d4e5f60718293a4b5c6d7e8
源站的WAF或者应用中间件校验这个头,不合法的请求直接拒绝。这样可以防止攻击者伪造回源请求绕过边缘清洗。
第三是合理配置缓存策略。静态资源在边缘节点缓存命中率越高,回源流量就越小,源站暴露的攻击面也越小。对于动态接口无法缓存的场景,可以考虑配置请求合并、回源限速,确保即使边缘被穿透,源站也不会被瞬间打死。
最后要强调监控和演练。清洗策略不是配完就一劳永逸的,攻击手法在不断进化,业务流量特征也在变化。建议定期查看CDN的攻击报表,关注被误拦截的请求比例,同时做一次模拟压测,验证整套清洗链路在高负载下的实际表现。只有架构吸收、特征识别、多层过滤、源站保护这四个环节都到位,CDN才能真正做到让攻击流量在边缘被消化掉。