相互傳輸層安全性總覽

相互傳輸層安全標準 (mTLS) 是業界標準通訊協定,用於在用戶端和伺服器之間進行雙向驗證。這項機制會驗證用戶端和伺服器是否都持有受信任憑證授權單位 (CA) 核發的有效憑證,確保雙方互相驗證。與標準 TLS 僅驗證伺服器不同,mTLS 要求用戶端和伺服器都必須提供憑證,在建立通訊前確認雙方身分。

所有應用程式負載平衡器的目標 HTTPS Proxy 資源都已設定 mTLS:

  • 全域外部應用程式負載平衡器
  • 傳統版應用程式負載平衡器
  • 區域性外部應用程式負載平衡器
  • 區域性內部應用程式負載平衡器
  • 跨區域內部應用程式負載平衡器

mTLS 會使用公用金鑰基礎架構 (PKI),驗證透過網路通訊的實體身分。基礎架構包含三個元件:用戶端、伺服器和憑證授權單位 (CA)。負載平衡器的 mTLS 支援下列功能:

  • 確認出示憑證的用戶端擁有私密金鑰。

  • 使用其中一種用戶端驗證模式驗證用戶端憑證。

  • 根據上傳的 PKI 錨點 (根憑證) 驗證用戶端憑證,並可選擇分別新增多個錨點,以便在不停機的情況下,順暢地從舊 PKI 遷移至新 PKI。

  • 提供額外的中繼憑證,協助建構用戶端憑證驗證路徑,以便與指定的 PKI 錨點 (根憑證) 進行比對。這些中繼憑證可讓 mTLS 與未提供完整憑證鏈的用戶端搭配運作。

  • 產生憑證指紋,並以自訂要求標頭的形式傳遞至後端。

  • 使用自訂標頭,將從憑證擷取的所選欄位傳遞至後端。

  • 使用自訂標頭將驗證結果和任何驗證錯誤傳遞至後端。

憑證規定

為 mTLS 設定憑證時,請確認憑證符合下列規定:

  • 新式密碼編譯工具是 mTLS 驗證的基礎。憑證必須使用 RSA 或 ECDSA 演算法交換金鑰。

  • 用戶端 (分葉) 憑證:

    • 基本限制擴充功能「不得」包含 CA=true。

    • 擴充金鑰使用方式擴充功能必須包含 clientAuth。

    • 擴充金鑰用途擴充功能「不得」包含 codeSigning、timeStamping 或 OCSPSigning 欄位。

    • 憑證必須在有效期限內。

    • 用戶端憑證不得為自行簽署的憑證。

  • 根憑證和中繼憑證:

mTLS 部署作業的架構

使用 mTLS 時,您可以設定信任設定資源,其中包含信任存放區。信任存放區會封裝信任錨點 (根憑證),以及一或多個中繼憑證 (選用)。負載平衡器收到用戶端憑證時,會建立從用戶端憑證到設定的信任錨點的信任鏈結,藉此驗證憑證。

以下簡要說明為負載平衡器設定 mTLS 時,需要設定的不同資源:

  • 信任設定。包含單一信任存放區資源,其中封裝了信任錨點 (根憑證),以及一或多個中繼憑證 (屬於選用性質)。信任設定用於在用戶端憑證和信任錨點之間建立信任鏈。詳情請參閱「信任設定」。

    (選用) 如果您需要使用自行簽署、已過期或無效的憑證,或者您無法存取根憑證和中繼憑證,可以在 allowlistedCertificates 欄位中將該憑證新增至信任設定。您不需要信任存放區,即可將憑證加入許可清單。

    將憑證加入許可清單後,只要憑證可剖析、已建立私密金鑰擁有權證明,且符合憑證 SAN 欄位的限制,系統就會一律視為有效。

  • 信任存放區。包含信任錨點和中繼憑證授權單位 (CA) 憑證,用於建立信任鏈結及驗證用戶端憑證。CA 會為用戶端核發信任的憑證。CA 是由負載平衡器的信任錨點 (根憑證) 或中繼 CA 憑證識別。

    您可以將下列類型的根憑證和中繼憑證上傳至信任存放區:

  • 用戶端驗證 (也稱為 ServerTLSPolicy)。 指定驗證用戶端憑證時要使用的用戶端驗證模式和信任設定資源。如果用戶端向負載平衡器提供無效憑證或未提供憑證,用戶端驗證模式會指定如何處理用戶端連線。您可以在伺服器 TLS 政策中指定所有 mTLS 驗證相關參數。用戶端驗證 (ServerTLSPolicy) 資源會附加至目標 HTTPS Proxy 資源。

下圖顯示附加至全域和區域性應用程式負載平衡器目標 HTTPS Proxy 資源的不同 mTLS 元件。

全球

下圖顯示外部應用程式負載平衡器部署作業的元件。這個架構也適用於跨區域內部應用程式負載平衡器,這是一種使用全域元件的內部應用程式負載平衡器。

全域外部應用程式負載平衡器元件的 mTLS。
採用全域外部應用程式負載平衡器元件的雙向 TLS (按一下即可放大)。

區域

下圖顯示區域性內部應用程式負載平衡器部署作業的元件。這個架構也適用於區域性外部應用程式負載平衡器,也就是使用區域性元件的外部應用程式負載平衡器。

區域性內部應用程式負載平衡器元件的 mTLS。
雙向 TLS 與區域性內部應用程式負載平衡器元件 (按一下即可放大)。

用戶端驗證模式

用戶端驗證 (ServerTLSPolicy) 資源的 clientValidationMode 屬性會指定負載平衡器處理用戶端連線的方式。模式會決定是否嚴格拒絕無效或缺少的用戶端憑證 (REJECT_INVALID)、拒絕特定寬鬆 X.509 檢查以外的憑證 (ALLOW_VALIDATION_RELAXATIONS),或轉送至後端 (ALLOW_INVALID_OR_MISSING_CLIENT_CERT)。

用戶端驗證模式如下:

  • 允許無效或缺少的用戶端憑證 (ALLOW_INVALID_OR_MISSING_CLIENT_CERT)
  • 拒絕無效的用戶端憑證 (REJECT_INVALID)
  • 允許放寬驗證規定 (ALLOW_VALIDATION_RELAXATIONS)

允許無效或缺少的用戶端憑證

ALLOW_INVALID_OR_MISSING_CLIENT_CERT 模式允許用戶端連線,即使用戶端憑證未通過驗證或用戶端未提供憑證也一樣。在這種模式下,無論是否能建立信任鏈,負載平衡器都會允許用戶端連線,並將所有要求傳遞至後端。

用戶端憑證出示時,系統一律會檢查私密金鑰的持有證明。如果用戶端無法證明擁有私密金鑰,即使在用戶端驗證模式允許無效或缺少用戶端憑證的情況下,TLS 握手也會終止。

拒絕無效的用戶端憑證

如果用戶端未提供憑證或憑證驗證失敗,REJECT_INVALID 模式會拒絕連線。在這種模式下,如果負載平衡器無法建立從用戶端憑證到信任錨點的信任鏈,就會終止用戶端連線。

允許放寬驗證規定

ALLOW_VALIDATION_RELAXATIONS 模式會強制執行用戶端憑證驗證,但允許放寬特定驗證檢查,例如在遷移期間,舊版用戶端憑證不符合所有嚴格的憑證規定。如果 REJECT_INVALID 模式中已有 ServerTLSPolicy 資源,可以更新為使用 ALLOW_VALIDATION_RELAXATIONS 模式,並指定要允許的驗證放寬清單。

您可以在 clientValidationRelaxations 欄位中指定下列一或多個值:

  • ALLOW_MISSING_EKU:允許用戶端憑證省略擴充金鑰用途 (EKU) 擴充功能。

    ALLOW_MISSING_EKU 只允許完全沒有 EKU 擴充功能的憑證,不會忽略用途錯誤的 EKU 擴充功能。舉例來說,如果用戶端憑證中有 EKU 擴充功能,則仍須包含憑證規定中指定的 clientAuth 金鑰用途 (OID 1.3.6.1.5.5.7.3.2)。如果憑證具有 EKU 擴充功能,且列出其他用途 (例如 serverAuth),但未列出 clientAuth,系統會拒絕連線。

  • ALLOW_SHA1_HASHING:允許以舊版 SHA-1 訊息摘要簽署的用戶端憑證鏈結通過驗證。

  • ALLOW_EXPIRED_LEAF_CERTIFICATE:允許分葉憑證已過期的用戶端通過驗證。負載平衡器會驗證過期的用戶端分葉憑證,就像目前時間是有效期限結束前一秒 (notAfter 減一秒)。這樣一來,用戶端分葉憑證就能通過到期檢查。這項放寬措施僅適用於用戶端分葉憑證,不適用於鏈結中的中繼或根憑證。尚未生效的用戶端分葉憑證 (目前時間早於 notBefore 時間戳記) 仍會遭到拒絕。

ALLOW_VALIDATION_RELAXATIONS 模式需要用戶端憑證,並會根據設定的信任設定資源驗證憑證鏈結,同時套用您在 clientValidationRelaxations 欄位中指定的特定驗證放寬條件。

選取 ALLOW_VALIDATION_RELAXATIONS 時,必須指定至少一項放寬驗證規定。如果選取多個放寬條件,系統會同時套用所有選取的放寬條件。只要用戶端提供的憑證在套用所選放寬條件後仍有效,負載平衡器就會接受連線。舉例來說,如果您設定 ALLOW_MISSING_EKU 和 ALLOW_SHA1_HASHING,負載平衡器會接受用戶端連線,前提是用戶端提供的憑證有效,但省略擴充金鑰用途 (EKU) 擴充功能,並使用 SHA-1 雜湊。

如果用戶端未提供憑證,或憑證驗證因任何原因失敗,且不符合設定的放寬條件,負載平衡器就會終止連線,並將錯誤記錄到 Cloud Logging。

Google Cloud 建議僅在憑證遷移期間,將放寬驗證條件做為暫時解決方案。使用 ALLOW_VALIDATION_RELAXATIONS 比使用 ALLOW_INVALID_OR_MISSING_CLIENT_CERT 更安全,因為負載平衡器仍會強制執行所有其他驗證檢查,且後端不需要自訂驗證邏輯。

在負載平衡器上設定 mTLS

以下簡要說明在負載平衡器上設定 mTLS 的重要步驟:

  1. 建立信任設定資源,其中包含信任錨點 (根憑證) 和中繼憑證,做為信任根。

  2. 將信任設定連結至用戶端驗證 (ServerTLSPolicy) 資源,該資源會定義用戶端驗證模式。

  3. 將用戶端驗證 (ServerTLSPolicy) 資源附加至負載平衡器的目標 HTTPS Proxy 資源。

  4. 選用:您可以使用自訂 mTLS 標頭,將 mTLS 連線的相關資訊傳遞至後端服務或網址對應。

如要進一步瞭解這項設定,請參閱下列指南:

用戶端憑證驗證步驟

驗證用戶端憑證時,負載平衡器會執行下列操作:

  1. 確認用戶端擁有私密金鑰。

    用戶端在握手程序中產生簽章,證明自己擁有與憑證中公開金鑰相關聯的私密金鑰。負載平衡器會使用用戶端的公開金鑰驗證這項簽章。如果簽章驗證失敗,表示用戶端並非憑證擁有者,在這種情況下,即使設定允許無效或缺少的用戶端憑證,TLS 握手也會終止。全域外部應用程式負載平衡器不會記錄任何錯誤,但區域性外部應用程式負載平衡器和內部應用程式負載平衡器會在 proxyStatus 欄位中記錄 TLS 錯誤。

  2. 驗證信任鏈。

    負載平衡器會根據信任設定中設定的憑證驗證用戶端憑證,藉此驗證信任鏈。用戶端驗證模式會決定是否嚴格拒絕無效或缺少的用戶端憑證 (REJECT_INVALID)、拒絕但特定寬鬆 X.509 檢查除外 (ALLOW_VALIDATION_RELAXATIONS),或轉送至後端 (ALLOW_INVALID_OR_MISSING_CLIENT_CERT)。

    驗證檢查也包括下列項目:

    • 用戶端、中繼和根憑證符合憑證規定。
    • 父項憑證中的主體欄位與子項憑證中的核發者欄位一致。這項驗證可確保上層憑證的身分 (主體) 與下層憑證中列為核發者的身分相同。
    • 父項憑證的主體金鑰 ID (SKID) 與子項憑證的授權單位金鑰 ID (AKID) 相符。這項比對結果可確認子憑證是由正確的根授權單位核發,且由於根公開金鑰在 AKID 中參照,用於驗證憑證的有效性,因此可以信任。
    • 子憑證的主體別名 (SAN) 不會違反父憑證中的 NameConstraints 欄位。
  3. 將要求轉送至後端。

    如果用戶端憑證驗證成功,系統會使用自訂 mTLS 標頭將要求轉送至後端。

    不過,如果驗證失敗,系統會根據用戶端驗證模式的值採取行動:

    • ALLOW_INVALID_OR_MISSING_CLIENT_CERT:要求會連同自訂 mTLS 標頭一併轉送,標頭會指出驗證失敗的原因。如果是跨區域內部應用程式負載平衡器、區域性外部應用程式負載平衡器和區域性內部應用程式負載平衡器,除了自訂 mTLS 標頭外,您還可以設定 mTLS 選用欄位,檢查失敗原因。

    • REJECT_INVALID 和 ALLOW_VALIDATION_RELAXATIONS:連線會終止,錯誤則會記錄到 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 有超過十個中繼憑證,這些憑證共用相同的主體和主體公開金鑰資訊。

未執行驗證。

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>

用戶端憑證沒有包含 clientAuth 的 Extended 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>

嘗試驗證憑證鏈結時,已達到深度或疊代限制。

憑證鏈結的深度上限為十層,包括根憑證和用戶端憑證。疊代次數上限為 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>

您已設定 mTLS,但未設定 TrustConfig 資源。

無法執行驗證,但憑證雜湊會轉送至後端。

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 標頭變數值是以 Base64 編碼的字串,代表二進位唯一編碼規則 (DER) 憑證資料。您可以使用自選工具或軟體程式庫,解碼 Base64 編碼字串。例如:

  • macOS 和 Linux 系統可以使用指令列 base64 工具,這是這兩種作業系統都包含的核心公用程式。如要使用 base64 公用程式解碼 Base64 編碼字串,請將編碼字串做為標準輸入內容傳遞至 base64 指令,並使用 -d 旗標解碼字串,如下所示:

    echo BASE_64_ENCODED_STRING | base64 -d
    
  • Python 包含 base64 模組,可用於解碼 Base64 編碼字串,如下所示:

    import base64
    encoded_string=BASE_64_ENCODED_STRING
    decoded_string=base64.b64decode(encoded_string).decode()
    print(decoded_string) # Note that a newline character (\n) is added to the end of the string.
    

錯誤處理和記錄

應用程式負載平衡器提供詳細的記錄功能,可讓您監控用戶端憑證驗證、找出潛在問題,以及排解連線問題。本節概述 mTLS 驗證期間可能發生的不同錯誤類型,以及記錄方式。

REJECT_INVALID 和 ALLOW_VALIDATION_RELAXATIONS 模式中記錄的錯誤

如果用戶端憑證驗證失敗,且用戶端驗證模式設為 REJECT_INVALID 或 ALLOW_VALIDATION_RELAXATIONS,連線就會終止,且錯誤會記錄到 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 有超過十個中繼憑證,這些憑證共用相同的主體和主體公開金鑰資訊。

未執行驗證。

client_cert_pki_too_large

用於驗證的中繼憑證含有超過 10 個名稱限制條件。

client_cert_chain_max_name_constraints_exceeded

用戶端憑證沒有包含 clientAuth 的 Extended Key Usage (EKU) 擴充功能。

client_cert_chain_invalid_eku

嘗試驗證憑證鏈結時,超過時間限制。 client_cert_validation_timed_out

嘗試驗證憑證鏈結時,已達到深度或疊代限制。

憑證鏈結的深度上限為十層,包括根憑證和用戶端憑證。疊代次數上限為 100 次 (檢查憑證以驗證用戶端憑證鏈結)。

client_cert_validation_search_limit_exceeded
您已設定 mTLS,但未設定 TrustConfig 資源。 client_cert_validation_not_performed
握手期間,用戶端未提供要求的憑證。 client_cert_not_provided
用戶端憑證無法透過 TrustConfig 資源通過驗證。 client_cert_validation_failed

已記錄的連線關閉錯誤

設定用戶端驗證模式後,特定錯誤會導致連線關閉,並記錄到 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 用戶端憑證驗證記錄。

限制

  • 負載平衡器不會對用戶端憑證執行撤銷檢查。

  • 應用程式負載平衡器可讓您上傳含有單一信任存放區的信任設定,其中最多包含:200 個信任錨點和中繼憑證 (中繼憑證數量上限為 100 個),以及 500 個加入許可清單的憑證。所有中繼憑證共用相同主體和主體公開金鑰資訊的憑證不得超過三個。詳情請參閱「配額與限制」。

  • 憑證鏈結的深度上限為十層,包括根憑證和用戶端憑證。嘗試建立信任鏈時,中繼憑證的評估次數上限為 100 次。詳情請參閱「配額與限制」。

  • 從用戶端上傳及傳遞的憑證金鑰僅限下列類型:

    • RSA 金鑰位元數可介於 2048 到 4096 之間。詳情請參閱配額與限制一文。
    • ECDSA 金鑰可以使用 P-256 或 P-384 曲線。
  • 從用戶端收到的可接受憑證鏈結,最多只能有 16 KB 和 10 個憑證。詳情請參閱「配額與限制」。

  • 用於驗證的根憑證不得含有超過 10 個名稱限制條件。詳情請參閱「配額與限制」。

  • 第 1 層 Google Front End (GFE) 會強制執行不可設定的 10 秒逾時,讓用戶端在 TLS 握手期間提供憑證。在尖峰負載下,這個逾時時間可能會縮短。用戶端必須在這段時間內完成憑證提供,才能成功建立 mTLS 連線。

後續步驟