ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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),仅供参考
返回列表