TLS¶
当和上游集群连接的时候,Envoy 在监听器中同时支持 TLS 终结 和 TLS 发起 。这种有效的支持确保了 Envoy 能够在现代 web 服务中发挥标准边缘代理的职责,以及和那些有高级 TLS 需求(TLS1.2、SNI 等等)的外部服务发起连接。Envoy 支持以下的 TLS 特性:
可配置的加密 :每一个 TLS 监听器和客户端可以指定那些他们支持的加密算法。
客户端证书 :除了服务器证书验证外,上游/客户端连接还能够提供客户端证书。
证书验证和固定 :证书验证选项包括基本的证书链验证、持有者名称验证以及哈希固定。
证书撤销 :如果 提供 了证书撤销列表(CRL), Envoy 可以根据它来检查对端证书。
ALPN :TLS 监听器支持 ALPN。HTTP 连接管理器使用这种信息(除了协议接口外)来决定一个客户端在用 HTTP/1.1 还是 HTTP/1.2。
SNI :SNI 同时支持服务器连接(监听器)和客户端连接(上游)。
会话(session)恢复 :服务器连接支持通过 TLS 会话凭证来恢复之前的会话(查看 RFC 5077 )。可以在热重启时和并行 Envoy 的实例之间执行会话恢复(在前段代理配置中是非常有用的)。
BoringSSL 私钥方法 :TLS 私钥操作(签名和解密)可以通过 扩展 来异步执行。这允许通过扩展 Envoy 来支持多个 key 的管理方案(比如 TPM)和 TLS 加速。这种机制使用了 BoringSSL 私钥方法接口 。
OCSP Stapling : 在线证书绑定协议(Online Certificate Stapling Protocol)响应可能要被绑定到证书中。
FIPS 140-2¶
BoringSSL 可以在 FIPS 合规模式 创建,使用 --define boringssl=fips
Bazel 选项,根据 BoringCrypto 模块安全政策 的指导来创建。目前,这个选项只在 Linux-x86_64 上有效。
FIPS 创建的正确性可以通过检查 –version 选项的输出中是否存在 BoringSSL-FIPS
字样来验证。
需要特别注意,对于 TIPS 合规来讲使用 FIPS-compliant 模式是非常必要的,但仅仅靠这个是远远不不够的,还需要依赖于上下文,或者还需要一些其他的步骤。其他的需求可能包含只使用经过批准的算法和/或者仅仅使用在 FIPS 合规模式下操作的模块所产生的私钥。关于更多内容,可以参考 BoringCrypto 模块安全政策 和/或者 认证的 CMVP 实验室 。
请注意 FIPS 合规构建是基于 BoringSSL 的老版本,而不是非 FIPS 构建,而且它并不支持最新的 QUIC API。
开启证书验证¶
上下游连接的证书验证是没开启的,除非验证信息指定了一个或者多个受信任的证书签发机构。
配置示例¶
static_resources:
listeners:
- name: listener_0
address: { socket_address: { address: 127.0.0.1, port_value: 10000 } }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
# ...
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
validation_context:
trusted_ca:
filename: /usr/local/my-client-ca.crt
clusters:
- name: some_service
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: some_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.2
port_value: 1234
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_certificates:
certificate_chain: { "filename": "/cert.crt" }
private_key: { "filename": "/cert.key" }
ocsp_response: { "filename": "/ocsp_response.der" }
validation_context:
match_subject_alt_names:
exact: "foo"
trusted_ca:
filename: /etc/ssl/certs/ca-certificates.crt
在 Debian 系统上 /etc/ssl/certs/ca-certificates.crt 是系统 CA 包文件的的默认路径。trusted_ca 和 match_subject_alt_names 能够使 Envoy 在验证 127.0.0.2:1234 的服务器标识为 “foo” 时,使用与标准安装在 Debian 系统上的 cURL 用相同的方式。在 Linux 和 BSD 系统上的系统 CA 包的常见路径如下:
/etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu/Gentoo etc.)
/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (CentOS/RHEL 7)
/etc/pki/tls/certs/ca-bundle.crt (Fedora/RHEL 6)
/etc/ssl/ca-bundle.pem (OpenSUSE)
/usr/local/etc/ssl/cert.pem (FreeBSD)
/etc/ssl/cert.pem (OpenBSD)
其他 TLS 选项可参考 UpstreamTlsContexts 和 DownstreamTlsContexts 。
Attention
如果只指定了 trusted_ca, 则 Envoy 将会验证所提供证书的证书链, 而不验证其主题名称、哈希等。根据部署,通常需要其他验证上下文配置。
证书选择¶
DownstreamTlsContexts 支持多个 TLS 证书。这些可能是 RSA 和 P-256 ECDSA 证书的一种混合。以下规则适用:
只有特定类型(RSA 或者ECDSA)中的一个证书被指定。
Non-P-256 服务器 ECDSA 证书被拒绝。
如果客户端支持 P-256 ECDSA,且在 DownstreamTlsContext 存在 P-256 ECDSA 证书,那么这个证书就会被选择,这和 OCSP 策略是一致的。
如果客户端只支持 RSA 证书,且在 DownstreamTlsContext 存在 RSA 证书,那么这个证书就会被选择。
否则,列取的第一个证书将会被使用。如果客户端只支持 RAS 证书而服务器端只支持 ECDSA 证书的话,这将会导致握手失败。
静态和 SDS 证书可能不会被混何在 DownstreamTlsContext 中。
被选择的证书必须符合 OCSP 策略。如果没找到符合条件的证书,连接会被拒绝。
目前只提供单个 TLS 证书 UpstreamTlsContexts 。
安全发现服务(SDS)¶
TLS 证书可以在静态资源中指定或者从远端获取。静态资源的证书轮换是支持的,可以通过 SDS 文件系统配置 或者从 SDS 服务器端获取更新信息来实现。详细信息请看 SDS 。
OCSP Stapling¶
DownstreamTlsContexts 支持在握手阶段把在线证书状态协议(OCSP)响应绑定到 TLS 证书上。
ocsp_staple
字段允许操作者在上下文中为每一个证书提供一个预先估算的 OCSP 响应。单个响应可能与多个证书无关。如果提供了响应,则 OCSP 响应必须是有效且需要检验证书没有被撤销。过期的 OCSP 响应也可被接受,但是可能会引起下游连接错误,这取决于 OCSP 的绑定策略。
DownstreamTlsContexts 支持使用 ocsp_staple_policy
字段来控制,当与证书相关联的 OCSP 响应丢失或者过期时,Envoy 是否应该停止使用证书还是继续无绑定运行。标记为 must-staple 的证书需要一个有效的 OCSP 响应,而这与 OCSP 的绑定策略无关。是实践中,一个 must-staple 证书让 Envoy 具有和 OCSP 绑定策略是 MUST_STAPLE 时一样的行为。在 OCSP 响应过期以后, Envoy 将不会在新连接中使用一个 must-staple 证书。
OCSP 响应将从来不会被绑定到那些通过 status_request
扩展来实现 OCSP 绑定的 TLS 请求上。
通过以下提供的运行时标志,可以调整 OCSP 的响应需求和复写 OCSP 策略。这些标志的默认值都是 true
。
envoy.reloadable_features.require_ocsp_response_for_must_staple_certs
:禁用此标志可允许操作者在配置中忽略 must-staple 证书的 OCSP 响应。envoy.reloadable_features.check_ocsp_policy
:禁用此标志可以禁用 OCSP 的策略检查功能。如果客户端支持 OCSP 响应,可在 OCSP 响应可用时进行绑定,即使 OCSP 响应已过期。如果没有响应存在,绑定会被跳过。
OCSP 响应会被 UpstreamTlsContexts 所忽略。
认证过滤器¶
Envoy 提供了一个网络过滤器,这个过滤器通过从 REST VPN 服务获取的信息中来匹配当前客户端证书的哈希值,以此来决定连接是否被允许。可选项 IP 允许列表也是可以被配置的。在 web 基础设施中此功能可被用来构建边缘代理的 VPN 支持。
客户端 TLS 认证过滤器 configuration reference 。
定制的握手器(handshaker)扩展¶
CommonTlsContext 有一个
custom_handshaker
扩展,可以被用来完全重写 SSL 握手行为。这对那些很难通过回调来表达 TLS 行为的实现是非常有用的。写一个使用私钥方法的定制化握手器其实是不必要的,可以查看上面描述的 私钥方法接口 。
为了避免重复实现所有的 Ssl::ConnectionInfo 接口,可以选择一个定制化的实现来扩展 Envoy::Extensions::TransportSockets::Tls::SslHandshakerImpl 。
定制化的握手器需要通过 握手器能力 来显式声明。默认的 Envoy 握手器将会管理剩余的事情。
一个名为 SslHandshakerImplForTest
的握手器示例,可在 这个测试 中查看,且演示了特殊情况下 SSL_ERROR
的处理和回调。
故障排除¶
当和上游集群发生连接的时候,Envoy 会发起 TLS,任何错误都会被记录在 UPSTREAM_TRANSPORT_FAILURE_REASON 字段或者 AccessLogCommon.upstream_transport_failure_reason<envoy_v3_api_field_data.accesslog.v3.AccessLogCommon.upstream_transport_failure_reason> 字段。
SDS 没有提供加密信息(Secret is not supplied by SDS)
:Envoy 一直在等待 SDS 能够传递 key/cert 或者 root 证书。SSLV3_ALERT_CERTIFICATE_EXPIRED
: 对端证书过期且在配置中不被允许。SSLV3_ALERT_CERTIFICATE_UNKNOWN
: 对端证书不在指定的 SPKI 配置中。SSLV3_ALERT_HANDSHAKE_FAILURE
:握手失败,通常是由于上游需要客户端证书,但是却没有提供。TLSV1_ALERT_PROTOCOL_VERSION
:TLS 协议版本不匹配。TLSV1_ALERT_UNKNOWN_CA
:对端证书的签发机构不在受信任的签发机构名单中。
更多由 BoringSSL 引发的错误的详细列表信息可以在 这儿 找到。