订阅以接收新文章的通知:

QUIC 行动:修补一个广播地址放大漏洞

2025-02-10

7 分钟阅读时间
这篇博文也有 English繁體中文版本。

Cloudflare 最近接到了一组匿名安全研究人员的联系,他们通过 QUIC 互联网测量研究发现了一个广播放大漏洞。我们的团队通过公开漏洞悬赏计划与这些研究人员合作,并且已经努力完全修补了一个影响 Cloudflare 基础设施的危险漏洞。

自从收到关于此漏洞的通知以来,Cloudflare 已经实施了一项缓解措施,帮助保护我们的基础设施。根据我们的分析,Cloudflare 已经完全修补了此漏洞,广播放大攻击手段不再存在。

放大攻击概述

QUIC 是一种默认加密的互联网传输协议。它提供与传输控制协议 (TCP) 和传输层安全性协议 (TLS) 相同的功能,但与此同时它使用的握手序列更短,这有助于缩短建立连接的时间。QUIC 在用户数据报协议 (UDP) 上运行。

研究人员发现,针对广播 IP 目标地址的单个客户端 QUIC 初始数据包可能会触发大量初始数据包响应。这同时表现为服务器 CPU 放大攻击和反射放大攻击。

传输与安全握手

如果使用 TCP 和 TLS,则有两次握手交互。首先,是 TCP 三步传输握手。客户端向服务器发送 SYN 包,服务器以 SYN-ACK 响应给客户端,然后客户端以 ACK 响应。此过程会验证客户端 IP 地址。其次,是 TLS 安全握手。客户端向服务器发送 ClientHello,服务器执行一些加密操作,然后以包含服务器证书的 ServerHello 响应。客户端验证证书,确认握手并发送应用流量,例如 HTTP 请求。

QUIC 遵循类似的过程,只不过握手序列更短,因为传输与安全握手结合在一起。客户端向服务器发送包含 ClientHello 的初始数据包,服务器执行一些加密操作,然后以包含 ServerHello 和服务器证书的初始数据包响应。客户端验证证书,然后发送应用数据。

QUIC 握手不要求首先验证客户端 IP 地址,然后开始安全握手。这意味着,攻击者可以仿冒客户端 IP,导致服务器完成加密工作并将数据发送到目标受害者 IP(也称为反射攻击)。RFC 9000 仔细描述了由此带来的风险,并提供了降低风险的应对机制(例如,请参阅第 8 和第 9.3.1 部分)。在验证客户端地址之前,服务器采用反放大限制,发送的字节数最多是其接收的字节数的 3 倍。此外,服务器可以通过响应一个重试数据包来启动地址验证,然后进行加密握手。但是,这种重试机制在 QUIC 握手序列的基础上增加了额外的往返,从而抵消了其相对于 TCP 的一些优势。真实的 QUIC 部署会使用一系列策略和启发式方法,来检测流量负载并启用不同的缓解措施。

为了了解研究人员如何克服这些 QUIC 防护措施来触发放大攻击,我们首先需要深入了解 IP 广播的工作原理。

广播地址

在互联网协议版本 4 (IPv4) 寻址过程中,任何指定子网中的最终地址都是一个特殊的广播 IP 地址,用于将数据包发送到 IP 地址范围内的每个节点。同一子网内的每个节点都会接收发送到这个广播地址的任何数据包,这让某个发送者发送一则消息后,该消息可能会被数百个相邻节点“听到”。大多数连网系统都默认启用这种行为,并且这对于发现同一 IPv4 网络中的各种设备至关重要。

广播地址自然而然会带来 DDoS 放大风险;因为每发送一个数据包,就有数百个节点必须处理流量。

处理预期的地址广播

为了应对广播地址带来的风险,默认情况下,大多数路由器会拒绝来自其 IP 子网之外的数据包,这些数据包是针对它们本地连接的网络的广播地址。只允许在同一 IP 子网内转发广播数据包,从而防止来自互联网的攻击将全球各地的服务器作为攻击目标。

如果指定的路由器未直接连接到指定的子网,则通常不会应用相同的技术。只要地址在本地不被视为广播地址,边界网关协议 (BGP) 或其他路由协议会继续将来自外部 IP 的流量路由到子网中的最后一个 IPv4 地址。从本质上讲,这意味着“广播地址”仅与通过以太网连接在一起的路由器和主机的本地范围相关。对于互联网上的路由器和主机,广播 IP 地址的路由方式与任何其他 IP 相同。

将 IP 地址范围绑定到主机

每台 Cloudflare 服务器都应该能够为 Cloudflare 网络上的每一个网站提供内容。由于 Cloudflare 网络使用 Anycast 路由,因此,每台服务器必须监听我们网络中使用的每个 Anycast IP 地址(并能够从这些地址返回流量)。

为此,我们利用了每台服务器上的环回接口。与物理网络接口不同,当绑定到环回接口时,指定 IP 地址范围内的所有 IP 地址都可供主机使用(并将由内核在本地进行处理)。

其工作机制非常简单易懂。在传统路由环境中,使用最长前缀匹配来选择路由。在最长前缀匹配原则下,将会优先选择更具体的 IP 地址块(例如 192.0.2.96/29,8 个地址范围)的路由,而不是较笼统的 IP 地址块(例如 192.0.2.0/24,256 个地址范围)的路由。

虽然 Linux 使用最长前缀匹配,但它在立即搜索匹配项之前会执行一个额外步骤,查询路由策略数据库 (RPDB)。RPDB 包含一个路由表列表,其中可能包含路由信息及各自的优先级。默认的 RPDB 如下所示:

$ ip rule show
0:	from all lookup local
32766:	from all lookup main
32767:	from all lookup default

Linux 将按照数字升序查询每个路由表,尝试找到匹配的路由。一旦找到,便会终止搜索并立即使用路由。

如果您以前使用过 Linux 系统中的路由规则,您可能会熟悉主表的内容。与其中存在的名为“default”的表相反,“main”表通常用作默认的查找表。它也是包含我们传统上与路由表信息关联的内容的表。

$ ip route show table main
default via 192.0.2.1 dev eth0 onlink
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.2

但是,这并不是第一个要查询的路由表。相反,该任务落入了本地表:

$ ip route show table local
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
local 192.0.2.2 dev eth0 proto kernel scope host src 192.0.2.2
broadcast 192.0.2.255 dev eth0 proto kernel scope link src 192.0.2.2

查看表格,我们看到两种新型路由:本地路由和广播路由。顾名思义,二者具有两种截然不同的功能:本地处理的路由,以及将导致数据包被广播的路由。本地路由提供所需的功能,即:任何包含本地路由的前缀都会由内核处理该范围内的所有 IP 地址。广播路由将导致将数据包被广播到指定范围内的所有 IP 地址。如果 IP 地址绑定到接口,则会自动添加这两种类型的路由(并且,如果某个范围绑定到环回 (lo) 接口,则该范围本身将作为本地路由添加)。

漏洞发现

QUIC 部署高度依赖于其所处的负载平衡和数据包转发基础设施。虽然 QUIC 的 RFC 描述了风险和缓解措施,但仍然可能存在攻击手段,具体取决于服务器部署的性质。报告漏洞的研究人员研究了互联网上的 QUIC 部署,并且发现,向 Cloudflare 的某个广播地址发送 QUIC 初始数据包会触发大量响应。响应数据的总量超过了 RFC 的 3 倍放大限制。

通过查看示例 Cloudflare 系统的本地路由表,我们发现了一个潜在的原因:

$ ip route show table local
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
local 192.0.2.2 dev eth0 proto kernel scope host src 192.0.2.2
broadcast 192.0.2.255 dev eth0 proto kernel scope link src 192.0.2.2
local 203.0.113.0 dev lo proto kernel scope host src 203.0.113.0
local 203.0.113.0/24 dev lo proto kernel scope host src 203.0.113.0
broadcast 203.0.113.255 dev lo proto kernel scope link src 203.0.113.0

在这个示例系统中,已使用标准工具将 Anycast 前缀 203.0.113.0/24 绑定到环回 (lo) 接口。该工具严格遵守 IPv4 标准,为接口分配了两种特殊类型的路由:一是用于 IP 范围本身的本地路由,二是用于该范围内最终地址的广播路由。

虽然流向 Cloudflare 路由器直连子网的广播地址的流量会按预期被过滤出去,但针对我们路由的 Anycast 前缀的广播流量仍然会到达 Cloudflare 服务器本身。通常情况下,到达环回接口的广播流量不会造成什么问题。绑定到整个地址范围内特定端口的服务,将接收发送到该广播地址的数据并继续正常运行。但遗憾的是,当期望破灭时,这种相对简单的特征就会失效。

Cloudflare 的前端由多个 Worker 进程组成,每个进程独立绑定到 UDP 端口 443 上的整个 Anycast 范围。为了使多个进程能够绑定到同一端口,我们使用 SO_REUSEPORT 套接字选项。虽然 SO_REUSEPORT 会带来额外的好处,但它也会导致发送到广播地址的流量被复制到每一个监听器。

每个 QUIC 服务器 worker 都独立运行。它们都对同一客户端初始请求做出反应,从而导致服务器端的重复工作以及生成流向客户端 IP 地址的响应流量。因此,单个数据包可能会触发一次显著的流量放大。虽然具体情况因实施而异,但在 128 核系统上,典型的每核一个监听器堆栈(发送重试消息来响应假定的超时)可能会导致为每个发送到广播地址的数据包生成并发送 384 个回复。

虽然研究人员展示了针对 QUIC 的这种攻击,但潜在漏洞可能会影响以相同方式使用套接字的其他 UDP 请求/响应协议。

缓解

作为一种通信方式,广播通常并不适合 Anycast 前缀。因此,缓解此问题的最简单方法就是禁用每个范围内最终地址的广播功能。

理想情况下,可以通过修改工具来实现这一点:只在本地路由表中添加本地路由,完全跳过广播路由的方式。遗憾的是,唯一可行的机制是修补和维护 Cloudflare iproute2 套件的内部分叉工具,但这是解决当前问题的一种相当笨拙的办法。

相反,我们决定专注于移除路由本身。与任何其他路由类似,可以使用标准工具将其移除:

$ sudo ip route del 203.0.113.255 table local

为了大规模地这样做,我们对部署系统进行了微调更改:

  {%- for lo_route in lo_routes %}
    {%- if lo_route.type == "broadcast" %}
        # All broadcast addresses are implicitly ipv4
        {%- do remove_route({
        "dev": "lo",
        "dst": lo_route.dst,
        "type": "broadcast",
        "src": lo_route.src,
        }) %}
    {%- endif %}
  {%- endfor %}

如此一来,我们可以有效确保移除那些附加到环回接口的所有广播路由,从而确保以同样的方式来处理规范定义的广播地址与该范围内的其他地址,以此来缓解风险。

后续步骤

虽然此漏洞特别影响了我们 Anycast 范围内的广播地址,但它很可能已经扩展到 Cloudflare 基础设施之外。除非采取缓解措施,否则任何拥有满足相对狭窄标准的基础设施(多 worker、基于 UDP 服务的多监听器,该服务绑定到计算机上的所有 IP 地址并附加可路由的 IP 前缀,从而暴露广播地址)的客户都会受到影响。我们鼓励网络管理员和安全专业人员评估其各自的系统,了解可能存在局部放大攻击手段的配置。

我们保护整个企业网络,帮助客户高效构建互联网规模的应用程序,加速任何网站或互联网应用程序抵御 DDoS 攻击,防止黑客入侵,并能协助您实现 Zero Trust 的过程

从任何设备访问 1.1.1.1,以开始使用我们的免费应用程序,帮助您更快、更安全地访问互联网。要进一步了解我们帮助构建更美好互联网的使命,请从这里开始。如果您正在寻找新的职业方向,请查看我们的空缺职位
安全网络EdgeDDoSHTTP3漏洞悬赏计划

在 X 上关注

Bryton Herdes|@next_hopself
Lucas Pardue|@SimmerVigor
Cloudflare|@cloudflare

相关帖子