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 实现):
- 若 HTTP/3 当前可用(
shouldAttemptHttp3()且请求允许can_use_http3_),优先使用 HTTP/3 池; - 若 HTTP/3 已标记为 broken 或最近失败,则不再延迟 TCP 尝试(
delay_tcp_attempt = false),立即并行发起 TCP 连接; - 若 HTTP/3 未被通告(alternate protocols cache 中没有记录),请求直接进入混合(TCP)池;
- 若 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 验证与测试佐证
仓库提供两层测试可验证行为:
- 状态追踪器单元测试test/common/http/http3_status_tracker_impl_test.cc:覆盖初始化状态、标记 Broken、指数退避、封顶、Confirmed 重置、Broken→Confirmed→Broken 等全部状态迁移,可用于确认失败记忆逻辑符合预期;
- 连接池网格集成测试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),仅供参考