针对API网关的DDoS防护,核心在于不要只盯着单一维度做流量清洗,而是把请求大小(Body Size)和请求速率(Rate)联合起来做过滤策略。简单说,攻击者要么发大量小包打满连接数,要么发超大请求体压垮后端解析,单一规则都防不住。真正有效的方案是:在API网关层同时配置基于请求体大小的阈值拦截和基于时间窗口的速率限制,并且两者之间建立联动关系——比如当某个IP的请求速率接近阈值时,自动收紧其允许的最大请求体大小,反之亦然。这套联合过滤机制,能在流量到达业务服务之前,把绝大多数DDoS攻击流量挡在门外。

为什么单独做速率限制或者单独做请求大小过滤都不够

很多团队在API网关上只配了Rate Limiting,比如每秒限制100次请求。这能防住高频小包攻击,但防不住慢速大包攻击——攻击者每秒只发5个请求,每个请求体10MB,专门针对需要解析大JSON或上传文件的接口。反过来,如果只限制请求体大小不超过1MB,攻击者可以发海量500KB的请求,照样把后端打崩。所以必须两个维度同时卡,而且要根据接口特征动态调整阈值,不能一刀切。

请求大小过滤的具体实施策略

在API网关层面做请求大小过滤,通常有三个层次。第一层是在接入层(如Nginx、Envoy、Kong)直接限制request body size,超过阈值直接返回413状态码。第二层是在网关的插件或过滤器中,对不同API路径设置不同的body size上限,比如登录接口限制2KB,文件上传接口限制50MB。第三层是对Content-Type做区分,application/json和multipart/form-data的大小限制策略应该不同,因为前者通常是结构化数据不会太大,后者涉及文件上传需要更宽松的阈值。

具体配置示例(以Kong网关为例):

# Kong插件配置:限制请求体大小
{
  "name": "request-size-limiting",
  "config": {
    "allowed_payload_size": 1024,  // 单位KB,这里限制1MB
    "size_unit": "kilobytes",
    "content_type_whitelist": [
      "application/json",
      "application/xml"
    ]
  }
}

请求速率过滤的精细化配置

速率限制不能只看全局QPS,要分维度做。第一,按IP做限速,这是基础。第二,按API路径做限速,因为不同接口的正常调用频率差异很大。第三,按用户身份或API Key做限速,防止单个账号被滥用后拖垮整个服务。第四,引入滑动窗口算法而不是固定窗口,避免窗口边界的突发流量穿透问题。

滑动窗口的实现逻辑可以用令牌桶或漏桶算法。令牌桶允许一定程度的突发,适合API场景;漏桶则强制平滑输出,适合对后端保护更严格的场景。实际部署中,建议在网关层用令牌桶做粗粒度限速,在应用层用漏桶做细粒度控制。

# 令牌桶限速伪代码实现
class TokenBucket:
    def __init__(self, rate, capacity):
        self.rate = rate          # 每秒生成令牌数
        self.capacity = capacity  # 桶容量
        self.tokens = capacity
        self.last_time = time.now()

    def acquire(self, requested=1):
        now = time.now()
        elapsed = now - self.last_time
        self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
        self.last_time = now
        if self.tokens >= requested:
            self.tokens -= requested
            return True
        return False

请求大小与速率的联合过滤:核心逻辑设计

联合过滤的关键在于建立两者之间的动态关联。具体做法是定义一个"风险评分"模型:每个请求同时携带两个属性——请求体大小S和请求速率R。当S超过基准值且R超过基准值时,直接拦截。当S超过基准值但R正常时,进入观察队列。当R超过基准值但S正常时,降低该IP的允许最大请求体大小。这样就形成了一个动态调整的防护网。

举个实际场景:正常用户调用某个查询接口,请求体通常在500B以内,每秒调用不超过10次。如果某个IP突然每秒发50次请求,每个请求体2KB,虽然单独看速率没到极端值、大小也没到极端值,但联合起来就异常了。系统应该自动把这个IP的最大允许请求体降到500B,同时把速率限制降到每秒5次,观察后续行为。

# 联合过滤策略伪代码
def joint_filter(request):
    ip = request.ip
    size = request.body_size
    rate = get_current_rate(ip)  # 当前滑动窗口内的请求频率

    # 基础阈值
    SIZE_THRESHOLD = 1024 * 1024  # 1MB
    RATE_THRESHOLD = 100          # 100次/秒

    # 动态调整因子
    if rate > RATE_THRESHOLD * 0.7:
        dynamic_size_limit = SIZE_THRESHOLD * 0.5  # 速率偏高时收紧大小限制
    else:
        dynamic_size_limit = SIZE_THRESHOLD

    if size > dynamic_size_limit and rate > RATE_THRESHOLD * 0.5:
        block(ip, reason="joint_filter_triggered")
    elif size > SIZE_THRESHOLD:
        block(ip, reason="size_exceeded")
    elif rate > RATE_THRESHOLD:
        block(ip, reason="rate_exceeded")
    else:
        allow(request)

不同类型DDoS攻击的针对性防御

DDoS攻击类型很多,联合过滤对不同类型的效果差异明显。对于 volumetric attack(大流量攻击),速率限制是主力,请求大小过滤辅助识别异常大包。对于 protocol attack(协议层攻击,如慢速攻击),请求大小过滤配合连接超时策略更有效。对于 application layer attack(应用层攻击,如CC攻击),需要结合请求大小、速率、URI频率、User-Agent等多维度联合判断。特别是针对API的CC攻击,攻击者往往模拟正常请求但频率稍高、请求体稍大,这种"温水煮青蛙"式的攻击只有联合过滤才能识别。

API网关选型与联合过滤的落地

目前主流API网关都支持这种联合过滤,但实现深度不同。Kong通过插件机制可以组合request-size-limiting和rate-limiting插件,但两者默认是独立运行的,需要额外开发插件实现联动。Envoy的本地速率限制和请求大小限制都在filter层面,可以通过Lua脚本或WASM扩展实现联合逻辑。APISIX原生支持多种限流插件,并且支持通过serverless插件做自定义逻辑,灵活性最高。如果是自研网关,建议在filter chain中把大小检查放在速率检查之前,先过滤掉明显的大包攻击,减轻速率计算的压力。

阈值设定的实战经验

阈值设定是联合过滤最难的部分,设太低误杀正常用户,设太高防不住攻击。建议分三步走:第一步,先用生产流量跑一周,统计每个接口的P50、P95、P99请求体大小和调用频率,以此为基准。第二步,在基准值上加20%-30%作为告警阈值,加50%-100%作为拦截阈值。第三步,上线后持续监控误杀率和漏放率,每周调整一次。特别注意,文件上传、批量导入这类接口的阈值要单独设置,不能和普通查询接口用同一套规则。

监控与告警体系的配套建设

联合过滤不是设完就不管了,必须配套实时监控。重点监控三个指标:一是被拦截请求的数量和占比,如果突然飙升说明可能在被攻击;二是误杀率,如果正常用户频繁被拦截需要立刻调整阈值;三是各维度的流量分布,比如请求体大小的直方图,如果出现异常峰值要及时响应。建议用Prometheus采集网关指标,Grafana做可视化,配合告警规则实现分钟级响应。

联合过滤的局限性与补充手段

必须承认,API网关层的联合过滤只能处理应用层和部分传输层的DDoS,对于网络层的大流量攻击(如SYN Flood、UDP Flood)无能为力,这些需要在更上游的CDN或运营商层面处理。另外,联合过滤对分布式攻击(大量不同IP同时发起低速率攻击)的识别能力有限,需要引入IP信誉库和行为分析引擎做补充。还有一点,加密流量(HTTPS)下无法检查请求体大小,需要在TLS终止之后、网关之前的位置做解密和过滤,这对性能有一定影响,需要权衡。

总结:联合过滤是API网关DDoS防护的必选项

把请求大小和速率联合起来做过滤,不是什么新技术,但真正做到位的团队不多。大多数人要么只做限速,要么只限大小,要么两者独立运行没有联动。真正有效的防护一定是动态的、多维度的、有反馈机制的。在API网关这个位置做联合过滤,性价比最高——离业务近、延迟低、规则灵活。把这套机制建好,再配合上游流量清洗和下游应用层防护,就能构建一个比较完整的API安全防护体系。