DDoS 防护与 WAF 实战

DDoS 攻击分类与防护架构、WAF 规则引擎、Bot 管理、速率限制算法,以及 Cloudflare/AWS Shield/阿里云高防的实战配置。

开篇:DDoS——最古老的网络攻击依然致命

分布式拒绝服务(DDoS)攻击自 1990 年代就已经存在,但直到今天仍然是互联网面临的最普遍威胁之一。从早期的 Ping of Death 到现代的 IoT 僵尸网络发起的 Tbps 级攻击(如 2023 年 Cloudflare 缓解的 3.8Tbps 攻击),DDoS 攻击的规模和复杂度持续增长。

本章将系统介绍 DDoS 攻击的分类与防护架构、Web 应用防火墙(WAF)的规则引擎、Bot 管理技术,以及主流云服务商的防护方案配置。


一、DDoS 攻击分类

1.1 OSI 三层攻击

层级攻击类型描述典型攻击
L3 网络层Volumetric消耗目标带宽UDP Flood、ICMP Flood、Smurf
L4 传输层Protocol消耗连接状态资源SYN Flood、ACK Flood、RST Flood
L7 应用层Application消耗应用服务器资源HTTP Flood、Slowloris、Cache Busting

1.2 攻击详细解析

SYN Flood 攻击原理:

正常握手:                SYN Flood:
Client ──SYN──► Server    Client ──SYN──► Server
Client ◄─SYN/ACK── Server  (伪造源 IP,不回复)
Client ──ACK──► Server    Server 等待 ACK,半开连接累积
                          → 连接队列耗尽,拒绝合法请求

Slowloris 攻击原理:
- 攻击者发送大量不完整的 HTTP 请求
- 每个请求保持连接打开但不完成
- 服务器线程池被耗尽

一句话总结:DDoS 攻击从 L3 到 L7 层层递进,越往上层越难防御(流量特征越难与正常请求区分),需要的防护策略也越复杂。


二、DDoS 防护架构

2.1 多层防护体系

┌─────────────────────────────────────────────────────────┐
│                    边缘防护层                             │
│    Anycast CDN (Cloudflare/AWS CloudFront/阿里云 CDN)   │
│    ├─ 地理分散:流量分散到全球节点                       │
│    ├─ 缓存命中:静态内容不返回源站                       │
│    └─ WAF 过滤:L7 攻击过滤                             │
├─────────────────────────────────────────────────────────┤
│                    流量清洗层                             │
│    DDoS Scrubbing Center                                │
│    ├─ BGP Anycast 引流:攻击流量引向清洗中心             │
│    ├─ 流量分析:基于行为/签名的检测                      │
│    └─ 干净流量回注:合法流量通过 GRE/VXLAN 回注          │
├─────────────────────────────────────────────────────────┤
│                    源站防护层                             │
│    负载均衡 + 源站服务器                                  │
│    ├─ 速率限制:单 IP/用户请求频率控制                   │
│    ├─ 连接限制:TCP 连接数限制                           │
│    └─ 应用优化:慢连接超时、 keepalive 优化             │
└─────────────────────────────────────────────────────────┘

2.2 BGP 黑洞路由

# 当攻击流量过大时,通过 BGP 宣告黑洞路由丢弃流量
# RTBH (Remotely Triggered Black Hole)

# 1. 源站向上游 ISP 发送 BGP 更新
# 宣告被攻击的 /32 IP 指向 NULL0
ip route 203.0.113.10 255.255.255.255 null0 tag 666

# 2. 上游 ISP 通过 iBGP 传播
# 所有邻居将目的为 203.0.113.10 的流量丢弃

# 3. 干净流量通过隧道/VPN 恢复
# 仅受信任的流量通过 GRE 隧道到达源站

一句话总结:DDoS 防护的核心是"吸收和分散"——Anycast 分散地理流量,清洗中心过滤恶意流量,黑洞路由作为极端情况下的保底手段。


三、WAF 实战配置

3.1 OWASP Core Rule Set

# ModSecurity + OWASP CRS (Nginx)
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;

# 自定义规则:防止 SQL 注入
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
    "@rx (?i:(?:select\s*\*\s*from|(?:delete|drop|truncate)\s+table|union\s+select.*from|into\s+(?:outfile|dumpfile)))" \
    "id:1000001,phase:2,deny,status:403,msg:'SQL Injection Detected',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}'"

# 自定义规则:速率限制
SecAction "id:1000002,phase:1,nolog,pass,setvar:ip.request_count=+1,expirevar:ip.request_count=60"
SecRule IP:REQUEST_COUNT "@gt 100" \
    "id:1000003,phase:1,deny,status:429,msg:'Rate Limit Exceeded'"

3.2 Cloudflare WAF 规则示例

# Cloudflare 自定义防火墙规则 (Expression Language)

# 规则 1:阻止已知恶意 IP
(http.host eq "api.example.com" and ip.src in $blacklist)
or
(http.host eq "api.example.com" and ip.geoip.country in {"CN" "RU"})
 Block

# 规则 2:API 速率限制
(http.host eq "api.example.com" and http.request.uri.path contains "/v1/")
 Rate Limit: 100 requests / 10 seconds / IP
   Action: Block for 1 hour

# 规则 3:Bot 管理挑战
(http.host eq "api.example.com" and cf.bot_management.score lt 30)
 Managed Challenge

# 规则 4:防止扫描工具
(http.user_agent contains "sqlmap" or http.user_agent contains "nikto" or http.user_agent contains "nmap")
 Block

一句话总结:WAF 是 L7 防护的核心——OWASP CRS 提供开箱即用的防护基线,Cloudflare/AWS WAF 等托管服务通过机器学习持续优化检测能力。


四、Bot 管理

4.1 Bot 分类

类型例子处理方式
良性 BotGooglebot, Bingbot允许,限制速率
监控 BotUptimeRobot, Pingdom允许,配置白名单
恶意 Bot爬虫、撞库工具、DDoS 僵尸挑战或阻止
灰色 Bot价格监控、内容聚合根据业务策略处理

4.2 挑战机制

// Cloudflare Turnstile(无感知挑战)
// 替代传统 CAPTCHA,用户无感知

// 前端集成
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="your-site-key"></div>

// 后端验证
const verifyTurnstile = async (token) => {
  const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      secret: TURNSTILE_SECRET_KEY,
      response: token,
    }),
  });
  return response.json(); // { success: true, score: 0.9 }
};

一句话总结:现代 Bot 管理从"一刀切阻止"演变为"分类后差异化处理"——良性 Bot 限速放行,恶意 Bot 渐进式挑战,灰色 Bot 根据业务策略灵活处理。


五、速率限制算法

5.1 令牌桶算法

import time
from threading import Lock

class TokenBucket:
    def __init__(self, capacity: int, refill_rate: float):
        self.capacity = capacity      # 桶容量
        self.tokens = capacity        # 当前令牌数
        self.refill_rate = refill_rate  # 每秒补充令牌数
        self.last_refill = time.time()
        self.lock = Lock()
    
    def allow_request(self, tokens_needed: int = 1) -> bool:
        with self.lock:
            now = time.time()
            # 补充令牌
            elapsed = now - self.last_refill
            self.tokens = min(
                self.capacity,
                self.tokens + elapsed * self.refill_rate
            )
            self.last_refill = now
            
            # 检查是否有足够令牌
            if self.tokens >= tokens_needed:
                self.tokens -= tokens_needed
                return True
            return False

# 使用:100 tokens/minute
bucket = TokenBucket(capacity=100, refill_rate=100/60)
if not bucket.allow_request():
    return 429  # Too Many Requests

5.2 分布式限流(Redis)

import redis
import time

class RedisRateLimiter:
    def __init__(self, redis_client: redis.Redis):
        self.redis = redis_client
    
    def sliding_window_check(self, key: str, window: int, limit: int) -> bool:
        """
        滑动窗口限流
        key: 限流标识(如 user:123:api:create)
        window: 窗口大小(秒)
        limit: 窗口内最大请求数
        """
        now = int(time.time())
        window_start = now - window
        
        pipe = self.redis.pipeline()
        
        # 移除窗口外的记录
        pipe.zremrangebyscore(key, 0, window_start)
        
        # 添加当前请求
        pipe.zadd(key, {str(now): now})
        
        # 统计窗口内请求数
        pipe.zcard(key)
        
        # 设置过期时间
        pipe.expire(key, window)
        
        results = pipe.execute()
        current_count = results[2]
        
        return current_count <= limit

# 使用
limiter = RedisRateLimiter(redis_client)
if not limiter.sliding_window_check(f"user:{user_id}:api", 60, 100):
    raise RateLimitExceeded("Too many requests")

一句话总结:令牌桶适合突发流量场景(允许短时间的流量突发),滑动窗口适合严格的 API 限流(精确控制时间窗口内的请求数)。


FAQ

Q1: DDoS 防护和 WAF 有什么区别?

  • DDoS 防护:针对可用性攻击(流量型/资源耗尽型),目标是"让服务继续可用"
  • WAF:针对应用层攻击(SQL 注入/XSS/CC 攻击),目标是"过滤恶意请求"
  • 两者互补:DDoS 防护处理流量洪水,WAF 处理恶意内容

Q2: 如何区分正常流量峰值和 DDoS 攻击?

  • 正常峰值:请求分布均匀,用户行为模式一致
  • DDoS 攻击:源 IP 集中或分散异常,请求模式单一(如固定 User-Agent),地理分布异常
  • 使用基线学习:基于历史流量建立正常行为模型

Q3: 7 层 DDoS(CC 攻击)为什么难防?

因为攻击请求在协议层面与正常请求几乎完全相同——都是合法的 HTTP GET/POST 请求。区别在于攻击者不关心响应内容,只关心消耗服务器资源。防御需要:

  • 行为分析(请求频率、点击模式)
  • JavaScript 挑战(区分浏览器和脚本)
  • 渐进式延迟(Tar pit)

Q4: 自建 WAF 还是使用云 WAF?

  • 小型项目:云 WAF(Cloudflare/AWS WAF/阿里云 WAF)配置简单、规则持续更新
  • 大型企业:混合方案——云 WAF 处理边缘攻击,本地 WAF 处理内部威胁和合规要求

Q5: Rate Limit 被绕过怎么办?

  • 更细粒度的限流:从 IP 限流升级到用户 ID/会话限流
  • 行为检测:检测异常请求模式(如固定间隔的请求)
  • 渐进式惩罚:首次超限警告,重复超限增加延迟,持续超限封禁

相关阅读

  • https://plumephp.com/security-api-design/ — API 安全设计(含速率限制策略)
  • https://plumephp.com/security-zero-trust-architecture/ — 零信任网络安全架构

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「安全」更多文章

  1. Kubernetes安全体系:RBAC、PodSecurity与NetworkPolicy实战
  2. 安全合规与数据保护
  3. 渗透测试与红蓝对抗