13.2 DDoS 防护
一句话
DDoS 的防护目标不是 “挡住所有攻击”,而是让攻击成本高于收益、让正常用户还能用:按层分流(网络层清洗、传输层抗 SYN、应用层限流与人机),并提前把 “阈值、动作、通知人” 写死。
三类攻击,三层防护
| 类型 | 例子 | 特征 | 防护位置 |
|---|---|---|---|
| 流量型(L3/L4) | UDP/ICMP 反射放大、SYN Flood | 带宽被打满,源站不可达 | 云清洗 / anycast / 运营商 |
| 协议型 | SYN Flood、连接耗尽 | 半连接队列满、连接表耗尽 | syncookies、连接限速 |
| 应用层(L7) | CC 攻击、慢速攻击、爬虫 | 请求看起来 “合法”,CPU/DB 被打满 | WAF、限流、人机校验、缓存 |
各层的标准动作
| 层 | 手段 | 说明 |
|---|---|---|
| 网络 | anycast + 清洗中心 | 把流量分散到全球入口,异常流量牵引清洗 |
| 传输 | SYN cookies、somaxconn、连接限速 | 半连接不占队列;注意会丢失部分 TCP 选项 |
| 应用 | 令牌桶限流(按 IP/用户/接口)、WAF 规则、JS 挑战 | 见 35.7 限流 |
| 架构 | 静态资源上 CDN、动态接口可降级 | 把攻击面推到边缘(见 9.0 CDN 全景:它到底是什么) |
阈值与演练:没演练等于没有
| 项 | 建议 |
|---|---|
| 清洗阈值 | 按 “正常峰值 × 1.5” 设自动清洗,避免误杀 |
| 限流阈值 | 按接口 P99 容量设,超限返回 429 而不是排队 |
| 通知 | 触发即通知值班 + 业务方,附 “已采取动作” |
| 演练 | 每季度一次小流量压测,验证清洗与降级链路 |
落到数字:三类攻击的判据
| 攻击 | 关键指标 | 阈值参考 | 动作 |
|---|---|---|---|
| 流量型 | 入向带宽 / pps | 超正常峰值 1.5× | 牵引清洗、运营商联动 |
| SYN Flood | 半连接队列长度、SYN 重传 | netstat -s 的 SYN 重传暴涨 | 开 syncookies、限速 |
| CC / 慢速 | 单 IP/单接口 QPS、并发连接数 | 超接口容量基线 | 限流、人机校验、WAF |
netstat -s 2>/dev/null | grep -iE "SYNs to LISTEN|retransmit" ; ss -s | head -3
nstat -az 2>/dev/null | grep -iE "TcpExtSyncookies|ListenOverflows" | head -5
实测:三种限流策略在 80% 攻击流量下的表现
10 万请求、80% 为攻击、攻击者轮换 5000 个 IP(本机模拟):
| 策略 | 攻击放行 | 正常放行 | 误杀 | 正常放行率 |
|---|---|---|---|---|
| 不设防 | 79,832 | 20,168 | 0 | 100% |
| 按 IP 限流 | 79,832 | 20,168 | 0 | 100%(完全无效) |
| 接口级令牌桶 + 人机校验 | 1,591 | 19,990 | 114 | 99.95% |
结论:按 IP 限流在 IP 轮换面前等于没做;真正有效的是 “接口维度配额 + 人机校验”。代价是 114 条误杀(0.57%),这也是为什么必须提供申诉/白名单通道。
反模式
| 反模式 | 后果 |
|---|---|
| 只靠 WAF 挡 L3/L4 流量 | 带宽先被打满,WAF 根本没机会工作 |
| 限流按 IP 且不区分接口 | NAT 后大量正常用户被误杀 |
| 攻击时临时找厂商 | 开通与牵引需要时间,错过窗口 |
| 没有降级预案 | 只能眼睁睁看着核心接口被打死 |
| 只配清洗阈值、不做应用层限流 | 小流量慢速攻击直接穿透 |
| 攻击期间改架构/扩容 | 来不及且放大故障,应先止血再优化 |
三条铁律
🔑 分层防护:网络层挡量、应用层挡 “像正常请求” 的攻击。
🔑 阈值与动作预先写死,攻击时只执行不讨论。
🔑 演练过的预案才算预案。
自检
Q1 攻击流量 200Gbps,源站带宽 10Gbps,先做什么?
▸ 答案:先牵引清洗(云清洗/anycast),而不是调源站参数:源站带宽根本接不住,任何应用层手段都无效。牵引后再看是流量型还是混合型;同时通知业务方准备降级,避免清洗期间正常请求也受影响。
Q2 SYN Flood 为什么可以用 syncookies 缓解?代价是什么?
▸ 答案:因为 syncookies 让服务器不保存半连接状态,把状态编码进 SYN-ACK 的序列号,收到 ACK 再重建。代价是无法携带全部 TCP 选项(如窗口缩放),极端情况下吞吐略降;它适合 “攻击期间临时开启”,而不是常态。
Q3 应用层 CC 攻击为什么难防?
▸ 答案:因为请求语法完全合法(真实 IP、正常 header、慢速但持续的请求),只是量大或资源消耗高。防线只能靠 “行为特征 + 限流 + 人机校验 + 缓存”,并且要接受一定误杀;纯靠扩容会被成本拖垮。
Q4 为什么 “按 IP 限流” 容易误杀?
▸ 答案:因为大量正常用户共享出口 IP(企业 NAT、运营商 CGNAT、移动网络),按 IP 限流会把整栋楼/整片区域一起限掉。改进:按 “用户维度(登录态)+ 接口维度” 限流,IP 维度只做粗筛,并给白名单与申诉通道。
Q6 为什么 “源站带宽还有 50%” 也可能已经被 DDoS 打挂?
▸ 答案:因为瓶颈常在连接表/半连接队列/应用线程而不是带宽:SYN Flood 用极低带宽打满队列,CC 用合法请求耗尽工作线程。只看带宽会误判 “没被打”,要看 pps、连接数与错误率。
Q5 为什么 “按 IP 限流” 在实测中完全无效?
▸ 答案:因为攻击者用 5000 个 IP 轮换,每个 IP 的请求数都低于阈值,限流器根本不会触发。IP 维度只适合 “单点暴力攻击”,对分布式/代理池攻击必须换维度:账号、设备指纹、接口配额、人机校验。
Q6 实测误杀 114 条正常请求,怎么进一步降低?
▸ 答案:三招:分维度配额(按登录态/租户而不是全局)、白名单与灰度豁免(已知合作方/内部流量)、自适应阈值(按近期基线动态调整,而不是固定值)。注意:完全零误杀通常意味着限流太松,要接受 “少量误杀 + 快速申诉” 的平衡。
Q7 清洗阈值设 “正常峰值 1.5×”,攻击只有 1.2× 时怎么办?
▸ 答案:清洗设备不会触发,此时靠应用层限流兜底:接口配额 + 排队 + 降级。这也说明 “DDoS 防护” 不是单点设备,而是分层:网络层挡大流量、应用层挡 “像正常请求” 的慢速攻击。
关联
- 前置:35.7 限流
- 并列:9.0 CDN 全景:它到底是什么
- 下游:38.6 常见攻击、56.2 故障演练