相互傳輸層安全性總覽

雙向傳輸層安全標準 (mTLS) 是業界標準通訊協定,用於用戶端和伺服器之間的雙向驗證。這項機制會驗證用戶端和伺服器是否持有信任的憑證授權單位 (CA) 核發的有效憑證,確保雙方都能通過驗證。標準 TLS 只會驗證伺服器,但 mTLS 會要求用戶端和伺服器出示憑證,確認雙方身分後才會建立通訊。

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

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

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

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

  • 以任一模式驗證用戶端憑證:

    • 拒絕無效憑證:如果無法驗證用戶端憑證鏈結,系統會拒絕要求,強制執行嚴格的驗證。

    • 允許無效或缺少的憑證:即使缺少或無效的用戶端憑證,仍可將所有要求傳遞至後端,提供彈性。

  • 根據上傳的 PKI 錨點 (根憑證) 驗證用戶端憑證,並可分別新增多個錨點,以便從舊 PKI 無縫遷移至新 PKI,不必停機。

  • 提供其他中繼憑證,協助根據指定的 PKI 錨點 (根憑證) 建構用戶端憑證驗證路徑。如果用戶端未提供完整的憑證鏈,mTLS 就能透過這些中繼憑證運作。

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

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

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

憑證規定

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

  • mTLS 驗證是以現代密碼編譯工具為基礎。憑證必須使用 RSA 或 ECDSA 演算法進行金鑰交換。 雜湊演算法必須使用 SHA-256 或更強大的加密雜湊函式。系統不支援 MD4、MD5 和 SHA-1 等雜湊演算法。
  • 用戶端 (葉節點) 憑證:
    • 基本限制 擴充功能不得包含 CA=true
    • 「擴充金鑰使用方式」 擴充功能必須包含 clientAuth
    • 「擴充金鑰使用方式」擴充功能不得包含 codeSigningtimeStampingOCSPSigning 欄位。
    • 憑證不得過期。
    • 用戶端憑證不得為自行簽署的憑證
  • 根憑證和中繼憑證:
    • 「基本限制」擴充功能必須包含 CA=true
    • 「金鑰使用方式」擴充功能必須設為 keyCertSign
    • 「擴充金鑰使用方式」擴充功能應包含 clientAuth 欄位。
    • 憑證不得過期。

mTLS 部署作業的架構

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

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

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

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

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

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

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

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

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

全球

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

使用全域外部應用程式負載平衡器元件的 mTLS。
使用全域外部應用程式負載平衡器元件的雙向傳輸層安全標準 (按一下可放大)。

區域

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

與區域內部應用程式負載平衡器元件進行相互 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 Proxy 資源。

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

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

用戶端憑證驗證步驟

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

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

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

  2. 驗證信任鏈

    負載平衡器會驗證用戶端憑證與設定的信任設定之間的信任鏈結。驗證檢查包括下列項目:

    • 用戶端、中繼和根憑證符合憑證規定
    • 父項憑證中的主體欄位與子項憑證中的核發者欄位相符。這項驗證可確保父項憑證的身分 (主體) 與子項憑證中列為核發者的身分相同。
    • 父項憑證的主體金鑰 ID (SKID) 與子項憑證中的授權單位金鑰 ID (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 有超過十個中繼憑證,這些憑證共用相同的主體和主體公開金鑰資訊。

不會執行驗證。

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>

您已設定 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 模式下記錄的錯誤

如果用戶端憑證驗證失敗,且用戶端驗證模式設為 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 有超過十個中繼憑證,這些憑證共用相同的主體和主體公開金鑰資訊。

不會執行驗證。

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

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

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

client_cert_validation_search_limit_exceeded
您已設定 mTLS,但未設定 TrustConfig 資源。 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 用戶端憑證驗證期間,已關閉連線的記錄錯誤

限制

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

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

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

  • 從用戶端上傳及傳送的憑證金鑰僅限於下列項目:

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

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

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

後續步驟