Envoy 修复 CVE-2026-48521:基于 ALPN 自动协商上游协议时 HTTP/3 空指针崩溃深度解析

Envoy 修复 CVE-2026-48521:基于 ALPN 自动协商上游协议时 HTTP/3 空指针崩溃深度解析

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

本指南围绕 Envoy 上游链路中一项重要的安全修复展开:当集群配置为基于 ALPN(Application-Layer Protocol Negotiation)自动选择与上游服务器之间的通信协议,且上游通过 HTTP/3 响应时,Envoy 可能因空指针解引用(null dereference)发生异常进程终止(即 CVE-2026-48521,对应 GitHub 安全公告 GHSA-5vff-j9p4-38j3)。读完本文,你将理解该崩溃的触发场景、上游 HTTP/3 与自动协议协商的底层架构原理,掌握如何正确配置 auto_config + HTTP/3 上游、识别潜在空指针风险点,并通过源码与测试用例验证修复行为。

一、漏洞概要:一次异常进程终止

该修复记录于仓库的 changelog/current/bug_fixes 目录,属于current未发布变更集中 bug_fixes 类别的安全修复条目。其描述的核心事实如下:

  • 受影响场景:Envoy 被配置为基于 ALPN 与上游服务器自动选择协议;
  • 触发条件:上游服务器使用 HTTP/3;
  • 影响:进程异常终止(abnormal process termination),即服务崩溃而非优雅退出;
  • 根因:空指针解引用(null deref)。

对于边缘/中间/服务型代理而言,进程级崩溃意味着所有经过该实例的在途连接被瞬间切断,属于需要优先处理的高危缺陷。该条目标记为 CVE-2026-48521,说明这是一次具有安全影响的公开漏洞修复。

二、问题场景还原:auto_config + ALPN + HTTP/3 上游

要理解崩溃为何发生,必须先弄清"基于 ALPN 自动选择协议"这一配置模式的语义。它对应 envoy.extensions.upstreams.http.v3.HttpProtocolOptions 中的auto_config(AutoHttpConfig)分支,而不是固定协议(explicit_http_config)或跟随下游(use_downstream_protocol_config)。

2.1 AutoHttpConfig 的协商语义

从 AutoHttpConfig 的 proto 定义 可以看到关键约束:

  • 使用该配置时,集群可以在 HTTP/1 与 HTTP/2 之间选择,具体使用哪个协议由与上游的 ALPN 协商结果决定;
  • 如果上游不支持 ALPN,则回退(fail over)到 HTTP/1;
  • 该模式只能用于支持 ALPN 的传输套接字,使用不支持 ALPN 的传输套接字会导致配置加载失败;
  • 传输层可以配置自定义 ALPN,但集群默认(或自定义 ALPN 失败时)的 ALPN 列表为"h2,http/1.1"。

与 HTTP/1、HTTP/2 不同,HTTP/3 不会被无条件启用:只有在配置中存在http3_protocol_options,且有服务器端支持 HTTP/3 的明确通告(advertisement)时才会使用。这正是本文漏洞场景的核心——自动协商链路中混入了 HTTP/3 这一"条件性"协议。

2.2 HTTP/3 上游的特殊性

上游 HTTP/3 架构说明 指出,HTTP/3 上游支持比 HTTP/1/2 复杂得多,原因在于:

  • 当auto_config中配置了 HTTP/3 时,Envoy只对通告了 HTTP/3 支持的服务器发起 HTTP/3 连接尝试,通告来源是 HTTP Alt-Svc(RFC 7838)或 HTTPS DNS 资源记录;
  • 没有这类通告时,回退使用 HTTP/2 或 HTTP/1;
  • HTTP/3 运行在 QUIC(基于 UDP)之上,而 HTTP/1、HTTP/2 基于 TCP。网络设备经常拦截 UDP 流量,导致上游 HTTP/3 连接尝试被网络阻断而失败,此时必须回退到 HTTP/2;
  • 因此上游连接代码需要跟踪 HTTP/3 连接尝试是否持续失败,避免发起注定失败的连接;而在 HTTP/3 工作正常的网络上,又要避免无谓地尝试 HTTP/2。

这套"既要探测、又要回退、还要记忆失败状态"的机制,引入了比固定协议模式更多的状态对象与异步回调路径,一旦某个状态对象在特定时序下尚未初始化就被访问,空指针解引用便可能发生——这正是本 CVE 的典型土壤。

三、上游 HTTP/3 的核心组件(源码级拆解)

围绕上述机制,仓库中对应实现了三个核心组件(可参见 ConnPoolGrid 实现 与 HTTP/3 上游文档)。

3.1 ConnectivityGrid:QUIC 与 TCP 双池路由

ConnectivityGrid是一个ConnectionPool,内部同时包装:

  • Http3ConnPoolImpl(QUIC 连接池,即createHttp3Pool()创建的池,见 conn_pool_grid.cc);
  • HttpConnPoolImplMixed(TCP 混合连接池,即createHttp2Pool(),见 conn_pool_grid.cc)。

请求分派逻辑(见 newStream 实现):

  1. 若 HTTP/3 当前可用(shouldAttemptHttp3()且请求允许can_use_http3_),优先使用 HTTP/3 池;
  2. 若 HTTP/3 已标记为 broken 或最近失败,则不再延迟 TCP 尝试(delay_tcp_attempt = false),立即并行发起 TCP 连接;
  3. 若 HTTP/3 未被通告(alternate protocols cache 中没有记录),请求直接进入混合(TCP)池;
  4. 若 HTTP/3 已通告且工作正常,请求走 HTTP/3 池;若 300ms 内未成功,则同时向混合池发起请求,谁先成功谁胜出(对应 conn_pool_grid.cc 中的kDefaultTimeoutMs = 300)。

这套双池竞速(race)逻辑中,http3_pool_、http3_alternate_pool_等成员均为惰性创建(getOrCreateHttp3Pool()),若在创建/回调时序上出现空指针访问,就会直接触发崩溃。

3.2 HttpServerPropertiesCache:HTTP/3 通告的来源

HttpServerPropertiesCache(实现在 http_server_properties_cache_impl.cc)负责追踪哪些服务器通告了 HTTP/3。通告来源是 Alt-Svc 响应头(未来还将支持 HTTPS DNS RR),目前只存储与请求相同主机名和端口的通告。

与之对应的配置结构是 AlternateProtocolsCacheOptions,关键字段包括:

字段说明默认值
name缓存名称;同名缓存在不同配置组件中被引用时各字段必须完全一致,否则配置加载失败必填
max_entries缓存最大条目数;实现为近似值,在每个 worker 线程上独立执行,实际条目数可能因时序略超配置值1024
key_value_store_config可选持久化 KV 存储,将条目刷盘;目前仅在并发度为 1 时支持无
prepopulated_entries预置条目,以 7 天生命周期预填充 HTTP/3 条目,使 Envoy 对未通告的上游也尝试 HTTP/3;会被 Alt-Svc 响应头覆盖无
canonical_suffixes可选主机名后缀列表,用于在可共享后缀的多个主机间共享 Alt-Svc 条目,条目必须以.开头无

3.3 HTTP/3 状态追踪:失败记忆与退避

Broken HTTP/3 追踪器负责"记住"哪些上游的 HTTP/3 连接不可用。其现代实现是 Http3StatusTrackerImpl,状态机包含:

  • Pending:HTTP/3 待定;
  • Broken:已标记损坏,进入退避;
  • FailedRecently:最近失败;
  • Confirmed:已确认可用。

值得注意的细节:架构文档描述的是"首次损坏 5 分钟、再次损坏翻倍、上限 1 天",但当前源码实现实际为:初始损坏期为 1 秒(DefaultExpirationTime{1}),每次被标记损坏后按1 << consecutive_broken_count_指数翻倍,最大连续损坏计数为 17(MaxConsecutiveBrokenCount = 17,即最长约 2^17 秒 ≈ 36 小时),一旦被标记为Confirmed则计数归零、恢复初始 1 秒。以源码为准,这在单元测试中有完整验证,例如MarkBrokenWithBackoff用例依次断言损坏期为 1s → 2s → 4s → 8s(见 测试文件第 67-99 行),MarkBrokenWithBackoffMax用例则验证 2^17 秒封顶(第 101-124 行)。

四、空指针风险的来源与修复要点

由于 changelog 条目仅声明修复了"空指针解引用导致的异常进程终止",未披露具体修复代码,我们只能结合源码结构推断该场景下可能的空指针来源(以下为基于代码结构的推断,非官方修复细节):

  • 惰性池成员访问:ConnectivityGrid的http3_pool_、http2_pool_均为惰性创建,若在回调路径(如onPoolFailure、onPoolReady、WrapperCallbacks的回调)中某成员尚未通过getOrCreateXxxPool()创建即被解引用,即为典型的空指针风险点。测试用例DoubleFailureThenSuccessSerial(见 conn_pool_grid_test.cc 第 323-357 行)专门覆盖了"HTTP/3 池失败 → 交替池失败 → HTTP/2 池成功"的完整回退链,正说明这些回调路径节点密集、易出问题;
  • 状态追踪器未就绪:Http3StatusTracker与HttpServerPropertiesCache::Origin关联,若alternate_protocols_缓存尚未创建或 origin 解析失败,追踪器访问同样可能解引用空指针;
  • 配置校验兜底:仓库已在配置解析层强制约束——当auto_config启用 HTTP/3 时,必须同时配置alternate_protocols_cache_options,否则配置加载直接报错"alternate protocols cache must be configured when HTTP/3 is enabled with auto_config"(见 upstreams/http/config.cc 第 92-98 行)。这一校验从配置入口堵住了"HTTP/3 已启用但缓存缺失"的空状态。

从工程角度,此类修复通常包含两部分:在崩溃路径上增加空指针判空/提前返回,以及补充覆盖该时序的回归测试。建议运维侧以升级到包含该修复的版本为第一优先级。

五、如何正确配置 auto_config + HTTP/3 上游

结合 AutoHttpConfig proto 与 上游 HTTP/3 文档 的"Required configuration"章节,完整配置需要三处配合。

5.1 集群侧:auto_config 必须完整声明三种协议

static_resources: clusters: - name: upstream_with_h3 connect_timeout: 5s type: STRICT_DNS load_assignment: cluster_name: upstream_with_h3 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: upstream.example.com port_value: 443 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: upstream.example.com typed_extension_protocol_options: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions auto_config: http_protocol_options: {} http2_protocol_options: {} http3_protocol_options: {} alternate_protocols_cache_options: name: default_alternate_protocols_cache max_entries: 1024

要点说明:

  • auto_config下三种协议选项都必须出现(HTTP/1、HTTP/2、HTTP/3),缺一不可;
  • http3_protocol_options只负责"允许" HTTP/3,实际是否启用仍取决于上游是否通告(Alt-Svc/HTTPS DNS RR);
  • alternate_protocols_cache_options在启用 HTTP/3 时为必填,由 config.cc 校验逻辑 强制保证,其name用于标识缓存实例;
  • 由于AutoHttpConfig依赖 ALPN,transport_socket必须是支持 ALPN 的 TLS 套接字,例如envoy.transport_sockets.tls的UpstreamTlsContext(默认 ALPN 为"h2,http/1.1")。

5.2 过滤器侧:启用 Alternate Protocols Cache Filter

为了让 Alt-Svc 响应头被解析并写入缓存,还需要在 HTTP 连接管理器(HttpConnectionManager)的过滤器链中启用 alternate protocols cache 过滤器:

http_filters: - name: envoy.filters.http.alternate_protocols_cache typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig

注意:该过滤器的配置类型 FilterConfig 中原本的alternate_protocols_cache_options字段已标记废弃(deprecated,计划在 3.0 移除),注释明确指出该字段会被忽略——过滤器将直接使用请求路由所对应集群的缓存。因此新的配置方式应为:在集群auto_config.alternate_protocols_cache_options中声明缓存(如 5.1 所示),并确保该缓存名称与过滤器引用一致。

5.3 验证与测试佐证

仓库提供两层测试可验证行为:

  1. 状态追踪器单元测试test/common/http/http3_status_tracker_impl_test.cc:覆盖初始化状态、标记 Broken、指数退避、封顶、Confirmed 重置、Broken→Confirmed→Broken 等全部状态迁移,可用于确认失败记忆逻辑符合预期;
  2. 连接池网格集成测试test/common/http/conn_pool_grid_test.cc:其中Success用例验证了"HTTP/3 通告存在 → 走 QUIC 池 → 握手完成后标记 Confirmed"(第 286-304 行);DoubleFailureThenSuccessSerial用例则验证了"HTTP/3 池失败 → 不向上抛错 → 交替池失败 → 回退 HTTP/2 池成功 → 最终标记 HTTP/3 为 broken"(第 323-357 行),这正是该场景下保证不崩溃、可优雅降级的核心路径。

运行相关测试(需要 Bazel 构建环境)可参考bazel test //test/common/http:conn_pool_grid_test与//test/common/http:http3_status_tracker_impl_test对应的目标。

六、升级与防护建议

  • 优先升级:包含 CVE-2026-48521 修复的 Envoy 版本是首要动作,尤其对使用auto_config且上游可能通告 HTTP/3 的集群;
  • 审视配置:确认集群的auto_config是否完整声明三种协议、是否已配置alternate_protocols_cache_options,避免因缺少缓存配置导致的配置加载失败;
  • 关注 UDP 可达性:若上游实际部署在网络会拦截 UDP 的环境中,HTTP/3 连接将持续失败,此时依赖状态追踪器的退避机制回退 TCP——这正是本文所讲修复所保护的核心路径;
  • 跟踪回归:以 HTTP/3 状态追踪测试 和 连接池网格测试 为基线,确认升级后上述失败回退与空指针防护行为仍被测试覆盖。

参考依据(仓库内证据索引)

  • 修复条目:changelogs/current/bug_fixes/http3__fixed-crash-due-to-null-deref.rst
  • 架构说明:source/docs/http3_upstream.md
  • 协议定义:api/envoy/extensions/upstreams/http/v3/http_protocol_options.proto、api/envoy/config/core/v3/protocol.proto
  • 过滤器定义:api/envoy/extensions/filters/http/alternate_protocols_cache/v3/alternate_protocols_cache.proto
  • 核心实现:source/common/http/conn_pool_grid.cc、source/common/http/http3_status_tracker_impl.cc、source/common/http/http_server_properties_cache_impl.cc、source/extensions/upstreams/http/config.cc
  • 测试用例:test/common/http/conn_pool_grid_test.cc、test/common/http/http3_status_tracker_impl_test.cc、test/common/http/http_server_properties_cache_impl_test.cc

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考