双向 TLS 概览

双向 TLS(简称 mTLS)是一种业界标准协议,用于在客户端和服务器之间进行双向身份验证。它通过验证客户端和服务器是否都持有由受信任的证书授权机构 (CA) 颁发的有效证书,确保客户端和服务器相互进行身份验证。与仅对服务器进行身份验证的标准 TLS 不同,mTLS 要求客户端和服务器都提供证书,以便在建立通信之前确认双方的身份。

在所有应用负载平衡器的目标 HTTPS 代理资源上配置 mTLS:

  • 全球外部应用负载均衡器
  • 传统应用负载均衡器
  • 区域级外部应用负载均衡器
  • 区域级内部应用负载均衡器
  • 跨区域内部应用负载均衡器

mTLS 使用公钥基础架构 (PKI) 来验证通过网络通信的实体的身份。该基础架构包括三个组件:客户端、服务器和证书授权机构 (CA)。适用于负载平衡器的 mTLS 支持以下功能:

  • 验证提供证书的客户端是否拥有其私钥。

  • 采用以下两种模式之一验证客户端证书:

    • 拒绝无效证书:如果无法验证客户端证书链,则通过拒绝请求来强制执行严格身份验证。

    • 允许证书无效或缺失:通过将所有请求都传递给后端,实现灵活性,即使客户端证书缺失或无效也是如此。

  • 对上传的 PKI 锚(根证书)进行客户端证书验证,您可以选择单独添加多个锚,以便从旧的 PKI 无缝迁移到新的 PKI,而不会出现停机时间。

  • 提供其他中间证书,以帮助根据指定的 PKI 锚标记(根证书)构建客户端证书验证路径。这些中间证书使 mTLS 能够与未提供完整证书链的客户端搭配使用。

  • 生成证书指纹并将其作为自定义请求标头传递给后端。

  • 使用自定义标头将从证书中提取的选定字段传递给后端。

  • 使用自定义标头,将验证结果和任何验证错误传递给后端。

证书要求

为 mTLS 配置证书时,请确保证书符合以下要求:

  • 现代加密工具是 mTLS 身份验证的基础。证书必须使用 RSA 或 ECDSA 算法进行密钥交换。哈希算法必须使用 SHA-256 或更强的加密哈希函数。不支持 MD4、MD5 和 SHA-1 等哈希算法。
  • 对于客户端(叶)证书:
  • 对于根证书和中间证书:

mTLS 部署的架构

借助 mTLS,您可以配置信任配置资源,其中包含信任库。受信任证书存储区封装了信任锚(根证书)以及(可选)一个或多个中间证书。当负载均衡器收到客户端证书时,会通过从客户端证书建立信任链(一直延伸到配置的信任锚点)来验证该证书。

以下简要概述了您需要配置哪些不同的资源才能为负载均衡器设置 mTLS:

  • 信任配置。包含单个受信任证书存储区资源,而该受信任证书存储区包含信任锚(根证书)以及(可选)一个或多个中间证书。信任配置用于在客户端证书和信任锚之间建立信任链。如需了解详情,请参阅信任配置

    您可以选择性地添加自签名证书、已过期证书或其他无效证书,或者如果您无权访问根证书和中间证书,则可以将该证书添加到 allowlistedCertificates 字段中的信任配置中。您无需信任存储区即可将证书添加到许可名单。

    将证书添加到许可名单意味着,只要证书可解析、已建立私钥所有权证明并满足针对证书 SAN 字段的限制条件,该证书就会始终被视为有效。

  • 受信任证书存储区。包含用于建立信任链和验证客户端证书的信任锚和中间证书授权机构 (CA) 证书。CA 用于为客户端颁发可信证书。CA 由负载均衡器的信任锚(根证书)或中间 CA 证书进行标识。

    您可以将以下类型的根证书和中间证书上传到信任存储区:

  • 客户端身份验证(也称为 ServerTLSPolicy)。指定在验证客户端证书时使用的客户端验证模式和信任配置资源。当客户端向负载均衡器提供无效证书或未提供证书时,客户端验证模式指定客户端连接的处理方式。您可以在服务器 TLS 政策中指定所有 mTLS 身份验证相关参数。客户端身份验证 (ServerTLSPolicy) 资源会附加到目标 HTTPS 代理资源。

下图展示了附加到全球和区域应用负载平衡器的目标 HTTPS 代理资源的不同 mTLS 组件。

全局

下图展示了外部应用负载均衡器部署的组件。此架构也适用于跨区域内部应用负载均衡器,即使用全球组件的内部应用负载均衡器。

使用全球外部应用负载均衡器组件的双向 TLS。
使用全球外部应用负载平衡器组件的双向 TLS(点击可放大)。

区域级

下图展示了区域级内部应用负载均衡器部署的组件。此架构也适用于区域级外部应用负载均衡器,即使用区域级组件的外部应用负载均衡器。

使用区域级内部应用负载均衡器组件的双向 TLS。
使用区域级内部应用负载平衡器组件的双向 TLS(点击可放大)。

客户端验证模式

当客户端向负载均衡器提供无效证书或没有证书时,客户端身份验证 (ServerTLSPolicy) 资源上的 clientValidationMode 属性会指定负载均衡器如何处理客户端连接。

客户端验证模式的值如下所示:

  • ALLOW_INVALID_OR_MISSING_CLIENT_CERT。即使客户端证书的验证失败或未提供客户端证书,也会允许从客户端进行连接。在此模式下,无论能否建立信任链,负载均衡器都会允许来自客户端的连接,并将所有请求传递给后端。

    提供客户端证书时,系统始终会检查私钥的所有权证明。如果客户端无法证明自己拥有私钥,则 TLS 握手会终止,即使客户端验证模式允许客户端证书无效或缺失也是如此。

  • REJECT_INVALID。如果客户端未提供证书或者证书验证失败,则拒绝连接。在此模式下,如果负载均衡器无法从客户端证书建立返回信任锚点的信任链,则会终止与客户端的连接。

在负载均衡器上配置 mTLS

以下简要介绍了在负载均衡器上配置 mTLS 时需要遵循的主要步骤:

  1. 创建一个信任配置资源,其中包含信任锚(根证书)和用作信任根的中间证书。

  2. 将信任配置关联到客户端身份验证 (ServerTLSPolicy) 资源,该资源定义了客户端验证模式(ALLOW_INVALID_OR_MISSING_CLIENT_CERTREJECT_INVALID)。

  3. 将客户端身份验证 (ServerTLSPolicy) 资源附加到负载均衡器的目标 HTTPS 代理资源。

  4. 可选:您可以使用自定义 mTLS 标头将 mTLS 连接的相关信息传递给后端服务或网址映射。

如需详细了解此设置,请参阅以下指南:

客户端证书验证步骤

验证客户端证书时,负载均衡器会执行以下操作:

  1. 验证客户端是否拥有私钥

    客户端在握手过程中生成签名,以证明自己拥有与证书中公钥关联的私钥。负载均衡器使用客户端的公钥验证此签名。如果签名验证失败,则表示客户端不是证书的所有者,在这种情况下,即使您的配置允许客户端证书无效或缺失,TLS 握手也会终止。系统不会为全球外部应用负载平衡器记录任何错误,但会在区域级外部应用负载平衡器和内部应用负载平衡器的 proxyStatus 字段中记录 TLS 错误。

  2. 验证信任链

    负载均衡器会验证客户端证书和配置的信任配置之间的信任链。验证检查包括:

    • 客户端、中间证书和根证书符合证书要求
    • 父证书中的正文字段与子证书中的颁发者字段匹配。此验证可确保父证书的身份(正文)与子证书中列为颁发者的身份相同。
    • 父证书的正文密钥标识符 (SKID) 与子证书中的授权机构密钥标识符 (AKID) 匹配。此匹配确认子证书是由正确的根授权机构颁发的,并且可以信任,因为 AKID 中会引用根证书的公钥来验证证书的有效性。
    • 子证书的主题备用名称 (SAN) 未违反父证书中的 NameConstraints 字段。
  3. 将请求转发到后端

    如果客户端证书验证成功,系统会使用自定义 mTLS 标头将请求转发到后端。

    不过,如果验证失败,所采取的操作取决于客户端验证模式的值:

    • ALLOW_INVALID_OR_MISSING_CLIENT_CERT:系统会附带自定义 mTLS 标头转发请求,指明验证失败的原因。对于跨区域内部应用负载平衡器、区域级外部应用负载平衡器和区域级内部应用负载平衡器,除了自定义 mTLS 标头之外,您还可以配置 mTLS 可选字段来检查失败的原因。

    • REJECT_INVALID:连接会终止,并且错误会记录到 Cloud Logging

传递给后端的自定义 mTLS 标头

下表显示了在客户端证书通过验证和未通过验证时传递给后端的自定义 mTLS 标头。如果客户端证书未通过验证,只有在客户端验证模式设置为 ALLOW_INVALID_OR_MISSING_CLIENT_CERT 时,自定义标头才会传递给后端。

客户端证书状态 客户端验证模式 自定义标头

客户端证书链太长(超过 10 个中间证书包含在客户端证书中)。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_chain_exceeded_limit

client_cert_sha256_fingerprint: <cert hash>

客户端证书或中间证书的 RSA 密钥大小无效。

不执行验证。

RSA 密钥可为 2048 位到 4096 位。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_invalid_rsa_key_size

client_cert_sha256_fingerprint: <cert hash>

客户端证书或中间证书使用的是不受支持的椭圆曲线。

不执行验证。

有效的椭圆曲线为 P-256 和 P-384。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_unsupported_elliptic_curve_key

client_cert_sha256_fingerprint: <cert hash>

客户端证书或中间证书使用非 RSA、非 ECDSA 算法。

不执行验证。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_unsupported_key_algorithm

client_cert_sha256_fingerprint: <cert hash>

用于验证的 PKI 具有 10 个以上的中间证书,它们共享相同的主体和主体公钥信息。

不执行验证。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_pki_too_large

client_cert_sha256_fingerprint: <cert hash>

为验证提供的中间证书有超过 10 个名称限制。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_chain_max_name_constraints_exceeded

client_cert_sha256_fingerprint: <cert hash>

客户端证书没有包含 clientAuthExtended Key Usage (EKU) 扩展程序。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_chain_invalid_eku

client_cert_sha256_fingerprint: <cert hash>

尝试验证证书链时超出了时间限制。 ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_validation_timed_out

client_cert_sha256_fingerprint: <cert hash>

在尝试验证证书链时达到深度或迭代限制。

证书链的深度上限为 10,包括根证书和客户端证书。迭代次数上限为 100(为验证客户端证书链所检查的证书)。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_validation_search_limit_exceeded

client_cert_sha256_fingerprint: <cert hash>

您在未设置 TrustConfig 资源的情况下配置了 mTLS。

无法执行验证,但证书哈希会转发到后端。

ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_validation_not_performed

client_cert_sha256_fingerprint: <cert hash>

无客户端证书。 ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: false

client_cert_chain_verified: false

client_cert_error: client_cert_not_provided

client_cert_sha256_fingerprint: <empty>

客户端证书未通过 TrustConfig 资源的验证。 ALLOW_INVALID_OR_MISSING_CLIENT_CERT

client_cert_present: true

client_cert_chain_verified: false

client_cert_error: client_cert_validation_failed

client_cert_sha256_fingerprint: <cert hash>

客户端证书已通过证书验证器验证。 不适用

client_cert_present: true

client_cert_chain_verified: true

client_cert_error: <empty>

client_cert_sha256_fingerprint: <cert hash>

client_cert_serial_number: <serial_number>

client_cert_valid_not_before: <date>

client_cert_valid_not_after: <date>

client_cert_uri_sans: <list>

client_cert_dnsname_sans: <list>

client_cert_issuer_dn: <issuer>

client_cert_subject_dn: <subject>

client_cert_leaf: <certificate>

client_cert_chain: <list>

错误处理和日志记录

应用负载平衡器提供详细的日志记录功能,可让您监控客户端证书验证、识别潜在问题并排查连接问题。本部分概述了 mTLS 验证期间可能会发生的不同类型的错误以及错误的记录方式。

REJECT_INVALID 模式下记录的错误

如果客户端证书验证失败,并且客户端验证模式设置为 REJECT_INVALID,则连接会终止,并将错误记录到 Cloud Logging。下表介绍了这些错误。

客户端证书状态 记录的错误
客户端证书链太长(超过 10 个中间证书包含在客户端证书中)。 client_cert_chain_exceeded_limit

客户端证书或中间证书的 RSA 密钥大小无效。

不执行验证。

RSA 密钥可为 2048 位到 4096 位。

client_cert_invalid_rsa_key_size

客户端证书或中间证书使用的是不受支持的椭圆曲线。

不执行验证。

有效曲线为 P-256 和 P-384。

client_cert_unsupported_elliptic_curve_key

客户端证书或中间证书使用非 RSA、非 ECDSA 算法。

不执行验证。

client_cert_unsupported_key_algorithm

用于验证的 PKI 具有 10 个以上的中间证书,它们共享相同的主体和主体公钥信息。

不执行验证。

client_cert_pki_too_large

为验证提供的中间证书有超过 10 个名称限制。

client_cert_chain_max_name_constraints_exceeded

客户端证书没有包含 clientAuthExtended Key Usage (EKU) 扩展程序。

client_cert_chain_invalid_eku

尝试验证证书链时超出了时间限制。 client_cert_validation_timed_out

在尝试验证证书链时达到深度或迭代限制。

证书链的深度上限为 10,包括根证书和客户端证书。迭代次数上限为 100(为验证客户端证书链所检查的证书)。

client_cert_validation_search_limit_exceeded
您在未设置 TrustConfig 资源的情况下配置了 mTLS。 client_cert_validation_not_performed
客户端在握手期间未提供请求的证书。 client_cert_not_provided
客户端证书未通过 TrustConfig 资源验证。 client_cert_validation_failed

关闭连接时记录的错误

当客户端验证模式设置为 ALLOW_INVALID_OR_MISSING_CLIENT_CERTREJECT_INVALID 时,某些错误会导致连接关闭,并记录到 Cloud Logging。下表介绍了这些错误。

客户端证书状态 请求 记录的错误
客户端证书在握手期间失败签名。 终止 SSL 握手
服务无法执行证书链验证。 终止连接 client_cert_validation_unavailable
验证证书链时发生内部错误。 终止连接 client_cert_validation_internal_error
找不到 TrustConfig 的匹配项。 终止连接 client_cert_trust_config_not_found
客户端证书载荷(包括任何中间证书)过大(超过 16 KB)。 终止连接 client_cert_exceeded_size_limit

如果后端服务上启用了日志记录,您可以查看 mTLS 客户端证书验证期间关闭连接时记录的错误

限制

  • 负载均衡器不会对客户端证书执行撤消检查。

  • 借助应用负载均衡器,您可以上传信任配置,该信任配置的单个受信任证书存储区最多包含 100 个信任锚和 100 个中间证书,以及 500 个已添加到许可名单的证书。所有中间证书不得超过三个共享相同主体和主体公钥信息的证书。如需了解详情,请参阅配额和限制

  • 证书链的深度上限为 10,包括根证书和客户端证书。在尝试构建信任链时,评估中间证书的次数上限为 100。如需了解详情,请参阅配额和限制

  • 从客户端上传和传递的证书的密钥仅限于以下项:

    • RSA 密钥可为 2048 位到 4096 位。如需了解详情,请参阅配额和限制
    • ECDSA 密钥可以使用 P-256 或 P-384 曲线。
  • 从客户端收到的接受证书链限制为最多 16 KB 和 10 个证书。如需了解详情,请参阅配额和限制

  • 用于验证的根证书不得超过 10 个名称限制条件。如需了解详情,请参阅配额和限制

后续步骤