Envoy 上游多证书支持:custom_tls_certificate_selector 与 max_session_keys=0 解锁客户端 TLS 多证书

发布时间:2026/9/14 1:57:15

Envoy 上游多证书支持:custom_tls_certificate_selector 与 max_session_keys=0 解锁客户端 TLS 多证书 Envoy 上游多证书支持custom_tls_certificate_selector 与 max_session_keys0 解锁客户端 TLS 多证书【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇文章聚焦 Envoy 在客户端上游TLS 上下文中引入的一项新能力当CommonTlsContext显式配置了custom_tls_certificate_selector且UpstreamTlsContext.max_session_keys设为 0 时客户端上下文可以携带多张tls_certificates证书并由自定义选择器在握手阶段根据服务器 Hello 与传输套接字选项动态选证。读完本文你将理解该能力的启用条件、底层握手与选证实现原理、证书选择器与证书映射器的扩展生态并获得可直接落地的 upstream 与 downstream 配置示例。背景为什么客户端上下文此前只允许单张证书在 Envoy 的 TLS 架构中服务端downstream上下文历来支持在同一CommonTlsContext下关联多张证书用于同时承载 RSA 与 ECDSA 证书、以及基于 SNI 的证书选择见 tls.proto 中tls_certificates字段的注释说明。但客户端upstream上下文长期被限制为只允许单张证书。这一限制并非没有道理。在 client_context_impl.cc 的构造逻辑中Envoy 对证书数量做了显式校验// If a custom TLS certificate selector is used and maxSessionKeys is set to 0 // then allow multiple certificates. // // newSSL() installs a cached session before certificate selection callback, // and is only keyed by SNI, so its possible that a session created for // cert A can be resumed by a connection that would choose cert B. Therefore // to prevent incorrect TLS session resumption, maxSessionKeys should be 0. if (!(config.tlsCertificateSelectorFactory() config.maxSessionKeys() 0) tls_contexts_.size() ! 1) { creation_status absl::InvalidArgumentError(Client TLS context supports only a single certificate); return; }从源码注释可以清晰看到限制的根因newSSL()在证书选择回调之前就安装了缓存的 TLS 会话而会话缓存仅以 SNI 作为键。如果同一 SNI 下可能选择证书 A 或证书 B那么为证书 A 创建的会话有可能被本应选择证书 B 的连接复用造成错误的会话恢复。因此除非显式关闭会话恢复否则多证书会引入安全隐患。核心变更自定义选择器 max_session_keys0 解锁多证书本次 changelog 记录tls__multiple-upstream-certificates-with-certificate-selector.rst正式放开了这一限制Allow multipletls_certificatesin a client context, forCommonTlsContext, when acustom_tls_certificate_selectoris explicitly defined withmax_session_keysset to 0.即满足以下两个条件同时成立时客户端上下文允许配置多张证书CommonTlsContext中显式配置了custom_tls_certificate_selector自定义 TLS 证书选择器UpstreamTlsContext.max_session_keys显式设置为 0。这与 tls.proto 中tls_certificates字段的官方注释完全对应Only a single TLS certificate is supported in client contexts unlesscustom_tls_certificate_selectoris explicitly defined withmax_session_keysset to 0. In server contexts, Multiple TLS certificates can be associated with the same context to allow both RSA and ECDSA certificates and support SNI-based selection.关键配置字段详解CommonTlsContext.custom_tls_certificate_selector该字段是config.core.v3.TypedExtensionConfig类型的扩展点tls.proto官方注释对其行为做了精确定义downstream TLS 套接字基于 TLS ClientHello 选择证书若为空则回退到原生选择逻辑——从证书的 DNS SAN 或 Subject Common Name 提取服务器名模式来匹配 SNIupstream TLS 套接字基于 TLS ServerHello 以及传输套接字选项transport socket options选择证书。该字段归属的扩展类别为envoy.tls.certificate_selectors下游与envoy.tls.upstream_certificate_selectors上游。UpstreamTlsContext.max_session_keys该字段在 tls.proto 中定义为google.protobuf.UInt32ValueMaximum number of session keys (Pre-Shared Keys for TLSv1.3, Session IDs and Session Tickets for TLSv1.2 and older) to be stored for session resumption. Defaults to 1, setting this to 0 disables session resumption.默认值1即默认开启会话恢复缓存设为 0完全禁用会话恢复这也是多证书场景的强制要求。在客户端实现中max_session_keys_控制两处行为构造时通过SSL_CTX_sess_set_new_cb安装新会话回调client_context_impl.cc以及newSsl()时从上下文缓存或按 SNI 维度设置会话client_context_impl.cc。当max_session_keys_ 0时这些路径全部被跳过从而杜绝多证书下的错误会话复用。源码级原理握手期间的选证回调启用多证书与自定义选择器后上游握手的选证发生在 BoringSSL 的证书回调cert callback中。构造时若存在自定义选择器工厂Envoy 会创建上游选择器并通过SSL_CTX_set_cert_cb注册回调client_context_impl.ccif (add_selector) { if (auto factory config.tlsCertificateSelectorFactory(); factory) { tls_certificate_selector_ factory-createUpstreamTlsCertificateSelector(*this); SSL_CTX_set_cert_cb( tls_contexts_[0].ssl_ctx_.get(), [](SSL* ssl, void*) - int { return static_castClientContextImpl*(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl))) -selectTlsContext(ssl); }, nullptr); } }selectTlsContext(SSL*)是上游选证的核心入口client_context_impl.cc它从 SSL 扩展信息中读取证书选择状态机然后调用选择器状态为NotStarted时发起选择调用tls_certificate_selector_-selectTlsContext(*ssl, *transport_socket_options, callback)选择器同步返回Success时直接完成选证并返回 1握手继续返回Pending例如等待 SDS 证书异步到达时返回 -1握手暂停返回Failed时返回 0握手失败。选择结果通过SelectionResult承载Success/Pending/Failed三种状态该状态机支持异步场景——证书尚未就绪时握手可以被挂起待证书就绪后由回调唤醒恢复。这一机制正是 Envoy 内置 on-demand 选择器实现握手期间按需拉取 SDS 证书的基础。证书选择器与证书映射器扩展生态内置 on-demand 选择器custom_tls_certificate_selector最典型的落地实现是 on-demand 证书选择器扩展名为envoy.tls.certificate_selectors.on_demand_secret同时注册了下游与上游两个工厂见 config.h。其配置结构定义于 config.proto字段类型必填说明config_sourceconfig.core.v3.ConfigSource是证书 SDS 配置源certificate_mapperconfig.core.v3.TypedExtensionConfig是计算秘密资源名的扩展函数下游基于 ClientHello上游基于 transport socket options 与 ServerHelloprefetch_secret_namesrepeated string否配置加载时即开始拉取的秘密资源名列表父资源无需等待拉取完成即可初始化其工作流程为握手期间根据对端 Hello 消息推导出秘密名 → 发起 SDS 资源请求 → 握手暂停 → 收到 SDS 响应后使用所提供证书恢复握手若 SDS 服务器指示资源被删除则握手失败并停止对该资源的订阅。官方文档还建议 on-demand SDS 配合DELTA_GRPC使用以便在数据面管理秘密删除见 secret.rst。内置证书映射器certificate mapperscertificate_mapper字段支持的扩展位于 cert_mappers 目录envoy.tls.certificate_mappers.sni以 SNI 作为 SDS 秘密名sni/config.henvoy.tls.certificate_mappers.static_name使用静态名称static_name/config.henvoy.tls.certificate_mappers.filter_state_override从下游过滤器链写入的 filter state 中读取动态值filter_state_override/config.h。on-demand 选择器统计指标on-demand 选择器会为下游监听器listener.stat_prefix.on_demand_secret.*与上游集群cluster.stat_prefix.on_demand_secret.*产生以下指标见 config.h 与 secret.rst指标名类型说明cert_requestedCounter新建 SDS 订阅的总次数cert_updatedCounter证书更新总次数cert_activeGauge当前活跃的证书订阅与证书数配置示例示例一上游多证书 自定义选择器核心新能力以下UpstreamTlsContext配置利用filter_state_override映射器动态选证展示了本次新能力的最小形态显式定义custom_tls_certificate_selector同时将max_session_keys设为 0 以允许携带多张证书配置结构参考 secret.rst 的上游示例tls_context: common_tls_context: custom_tls_certificate_selector: name: on-demand typed_config: type: type.googleapis.com/envoy.extensions.transport_sockets.tls.cert_selectors.on_demand_secret.v3.Config config_source: api_config_source: api_type: DELTA_GRPC grpc_services: - envoy_grpc: cluster_name: some_xds_cluster certificate_mapper: name: filter_state_override typed_config: type: type.googleapis.com/envoy.extensions.transport_sockets.tls.cert_mappers.filter_state_override.v3.Config default_value: default_secret # 客户端上下文多证书仅在配置了自定义选择器且 max_session_keys0 时合法 tls_certificates: - certificate_chain: filename: /etc/envoy/certs/cert_a.pem private_key: filename: /etc/envoy/certs/key_a.pem - certificate_chain: filename: /etc/envoy/certs/cert_b.pem private_key: filename: /etc/envoy/certs/key_b.pem max_session_keys: 0要让上游的filter_state_override生效下游过滤器链需要先写入对应的 filter state 值secret.rstname: envoy.filters.network.set_filter_state typed_config: type: type.googleapis.com/envoy.extensions.filters.network.set_filter_state.v3.Config on_new_connection: - object_key: envoy.tls.certificate_mappers.on_demand_secret factory_key: envoy.hashable_string format_string: text_format_source: inline_string: my_secret_name shared_with_upstream: ONCE示例二下游基于 SNI 的按需选证对照参考下游场景中custom_tls_certificate_selector配合 SNI 映射器可从 ClientHello 推导秘密名secret.rst。注意下游示例同时显式关闭了无状态与有状态会话恢复common_tls_context: custom_tls_certificate_selector: name: on-demand typed_config: type: type.googleapis.com/envoy.extensions.transport_sockets.tls.cert_selectors.on_demand_secret.v3.Config config_source: api_config_source: api_type: DELTA_GRPC grpc_services: - envoy_grpc: cluster_name: some_xds_cluster certificate_mapper: name: sni typed_config: type: type.googleapis.com/envoy.extensions.transport_sockets.tls.cert_mappers.sni.v3.SNI default_value: default_host prefetch_secret_names: - default_host disable_stateless_session_resumption: true disable_stateful_session_resumption: trueprefetch_secret_names用于在收到任何请求之前提前拉取常用证书适合高频域名静态名称映射器envoy.tls.certificate_mappers.static_name则适用于秘密名固定、仅需按需拉取的场景。注意事项与限制会话恢复必须禁用这是硬性约束而非建议。由于客户端会话缓存仅以 SNI 为键多证书 会话恢复可能导致为证书 A 建立的会话被本应选择证书 B 的连接复用因此max_session_keys必须为 0对 on-demand 证书官方文档明确Session resumption is currently not supported for on-demand certificatessecret.rst。SDS 更新联动通过 on-demand SDS 获取的证书与普通 TLS 证书一样应用父上下文的全部设置若父 TLS 上下文发生动态更新如验证上下文 SDS 更新on-demand 证书上下文也会同步更新握手恢复时使用最新版本的 CA 秘密secret.rst。xDS 协议选择建议使用 DELTA_GRPC 管理秘密删除使用普通 GRPC xDS 协议时每个映射秘密的订阅会一直保持活跃直到父资源监听器或集群被删除。字段互斥关系tls_certificate_provider_instance存在时tls_certificates被忽略tls_certificates存在时tls_certificate_sds_secret_configs被忽略tls.proto。校验失败行为若不满足自定义选择器 max_session_keys0而配置了多张证书配置加载会直接报错Client TLS context supports only a single certificate上下文创建失败。测试验证参考该能力及 on-demand 选择器在上游/下游两种形态下均有集成测试覆盖参数化的upstream_selector_标志贯穿握手、SDS 交互与统计断言integration_test.cc配置解析与扩展工厂注册则在 config_test.cc 中验证。如需深入源码可继续阅读 client_context_impl.h、ssl_handshaker.cc 与 default_tls_certificate_selector.cc。总结本 changelog 为 Envoy 客户端 TLS 上下文补齐了与服务端对称的多证书能力只要显式配置custom_tls_certificate_selector并将max_session_keys置 0即禁用会话恢复即可在CommonTlsContext.tls_certificates中声明多张证书由选择器在握手阶段依据 ServerHello 与 transport socket options 动态选证。结合内置的 on-demand 选择器与 SNI / static_name / filter_state_override 三类证书映射器上游侧可以按租户、按 SNI 或按下游携带的动态元数据灵活选择出站证书为多租户网关与双向 TLS 场景提供了安全且可扩展的配置路径。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/12 23:41:16

基于柯西分布QPSO的LTE基站覆盖率优化与Matlab实现

做网络规划仿真或者课程设计研究时,最绕不开的一类问题就是基站选址。LTE基站覆盖率优化属于典型的高维、非凸、多峰优化问题:覆盖率和基站位置、发射功率、传播环境、地形遮挡全都耦合在一起,你几乎没法用穷举或者传统梯度方法去找到全局最优…

2026/9/12 23:41:16

Windows下Redis安装全攻略:原生包、Docker与WSL2对比及避坑指南

搞 Windows 开发的人,几乎都绕不开一个尴尬:项目在 Linux 服务器上跑得好好的 Redis,本地 Windows 环境却总是要折腾半天。要么下载页面看不懂,要么装完启动报错,要么重启电脑服务就丢了。网上搜“Redis 下载与安装 教…

2026/9/14 1:53:31

智能高边驱动芯片:汽车电子保险丝的芯片化革命

1. 项目概述:当保险丝开始“思考”——汽车电子保护机制的代际跃迁“汽车里的保险丝,怎么变成芯片了?”——这句话最近在汽修厂、4S店技术群和新能源车主论坛里反复刷屏。它不是一句调侃,而是真实发生在你我每天驾驶的车辆底盘下、…

2026/9/14 1:53:31

相邻交换法详解:从贪心排序证明到跳跃游戏2的对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 1:53:31

IBM Planning Analytics Assistant:自然语言驱动的智能商业分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 1:48:31

Cahn-Hilliard方程数值求解:谱方法与有限差分混搭实践

简介:这是一份面向计算物理、材料科学及数值计算学习者的Python项目,完整演示了用有限差分法和谱方法求解Cahn-Hilliard方程的过程。Cahn-Hilliard方程描述相分离动力学,其在合金、高分子混合物等系统的扩散与界面演化研究中十分常见。压缩包…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码