在網址對應中建立自訂標頭

本頁說明區域內部應用程式負載平衡器和跨區域內部應用程式負載平衡器所用網址對應中的自訂標頭運作方式。

自訂要求和回應標頭可讓您指定其他標頭,供負載平衡器新增至 HTTP(S) 要求和回應。視負載平衡器偵測到的資訊而定,這些標頭可能包含下列資訊:

  • 用戶端延遲時間
  • TLS 連線的參數

事前準備

請視需要更新至最新版 Google Cloud CLI:

gcloud components update

自訂標頭的運作方式

自訂標頭的運作方式如下:

  • 負載平衡器向後端提出要求時,會新增要求標頭。

    負載平衡器只會將自訂要求標頭新增至用戶端要求,不會新增至健康狀態檢查探測。如果後端需要授權專用的標頭,但健康狀態檢查封包中沒有,健康狀態檢查可能會失敗。

  • 負載平衡器會在將回應傳回用戶端前,設定回應標頭。

如要為區域內部應用程式負載平衡器和跨區域內部應用程式負載平衡器啟用自訂標頭,請在網址對應設定檔中指定標頭名稱和標頭值清單。

標頭名稱應具有以下特性:

  • 標頭名稱必須是有效的 HTTP 標頭欄位名稱定義 (根據 RFC 7230 的規定)。
  • 標頭名稱不得為 X-User-IP
  • 標頭名稱不得以 X-GoogleX-Goog-X-GFEX-Amz- 開頭。
  • 不得使用下列逐一躍點標頭:Keep-AliveTransfer-EncodingTEConnectionTrailerUpgrade。根據 RFC 2616,這些標頭不會由快取儲存,也不會由目標 Proxy 傳播。
  • 標頭名稱不得為 HostauthorityHostauthority 都是 Google Cloud保留的特殊關鍵字。您無法修改 Envoy 型負載平衡器的這些標頭。建議您改為建立其他自訂標頭 (例如 MyHost),以免干擾保留的標頭名稱。
  • 標頭名稱在標頭清單中不可出現超過一次。

標頭名稱不區分大小寫。標頭名稱傳送至 HTTP/2 後端時,HTTP/2 通訊協定會將標頭名稱轉換成小寫編碼。

標頭值應具有以下特性:

  • 標頭值必須是有效的 HTTP 標頭欄位定義 (根據 RFC 7230 的規定,您將無法使用已過時的表單)。
  • 標頭值不得空白。空白標頭會遭到拒絕。
  • 標頭值可以包含一個或多個變數 (由大括號括住),以囊括負載平衡器提供的值。如需標題值中允許包含的變數完整清單,請參閱「可以出現在標題值中的變數」。

標頭值中的前置空格及後置空格無關緊要,系統並不會將其傳送至後端。為了能在標頭值中使用大括號,負載平衡器會將雙左大括號 ({{) 解譯成單左括號 ({),並將雙右大括號 (}}) 解譯成單右括號 (})。

新增要求或回應標頭

如要新增要求或回應標頭,請使用 gcloud CLI 編輯網址對應,如下所示:

區域

    gcloud compute url-maps edit URL_MAP_NAME \
        --region=REGION
    

以下是 YAML 檔案範例,說明如何在自訂標頭中使用變數:

   defaultService: regions/REGION/backendServices/BACKEND_SERVICE_1
   name: regional-lb-map
   region: region/REGION
   hostRules:
   - hosts:
     - '*'
     pathMatcher: matcher1
   pathMatchers:
   - defaultService: regions/REGION/backendServices/BACKEND_SERVICE_1
     name: matcher1
     routeRules:
       - matchRules:
           - prefixMatch: /PREFIX
         priority: PRIORITY # 0 is highest
         routeAction:
           weightedBackendServices:
             - backendService: regions/REGION/backendServices/BACKEND_SERVICE_1
               weight: 100
               headerAction:
                 requestHeadersToAdd:
                 - headerName: X-header-1-client-region
                   headerValue: "{client_region}"
                 - headerName: X-header-2-client-ip-port
                   headerValue: "{client_ip_address}, {client_port}"
                   replace: True
                 requestHeadersToRemove:
                 - header-3-name
                 responseHeadersToAdd:
                 - headerName: X-header-4-server-ip-port
                   headerValue: "{server_ip_address}, {server_port}"
                   replace: True
                 responseHeadersToRemove:
                 - header-5-name
                 - header-6-name
    

跨區域

    gcloud compute url-maps edit URL_MAP_NAME \
        --global
    

以下是 YAML 檔案範例,說明如何在自訂標頭中使用變數:

   defaultService: global/backendServices/BACKEND_SERVICE_1
   name: global-lb-map
   hostRules:
   - hosts:
     - '*'
     pathMatcher: matcher1
   pathMatchers:
   - defaultService: global/backendServices/BACKEND_SERVICE_1
     name: matcher1
     routeRules:
       - matchRules:
           - prefixMatch: /PREFIX
         priority: PRIORITY # 0 is highest
         routeAction:
           weightedBackendServices:
             - backendService: global/backendServices/BACKEND_SERVICE_1
               weight: 100
               headerAction:
                 requestHeadersToAdd:
                 - headerName: X-header-1-client-region
                   headerValue: "{client_region}"
                 - headerName: X-header-2-client-ip-port
                   headerValue: "{client_ip_address}, {client_port}"
                   replace: True
                 requesteHeadersToRemove:
                 - header-3-name
                 responseHeadersToAdd:
                 - headerName: X-header-4-server-ip-port
                   headerValue: "{server_ip_address}, {server_port}"
                   replace: True
                 responseHeadersToRemove:
                 - header-5-name
                 - header-6-name
    

請注意下列行為:

  • 如果含有自訂變數的回應標頭解析為空白字串,系統會移除該標頭。
  • 如果含有自訂變數的要求標頭解析為空白字串,系統會保留該標頭,並以空白字串預留位置取代。
  • 如果自訂要求標頭包含自訂變數,且傳入的用戶端要求也包含相同標頭,系統會將用戶端要求標頭值,替換為負載平衡器自訂標頭提供的新值。

可以出現在標題值中的變數

以下變數可以出現在自訂標頭值中。

變數 說明
client_rtt_msec 負載平衡器與 HTTP(S) 用戶端之間的預估往返傳輸時間,以毫秒為單位。這是負載平衡器的 TCP 堆疊根據 RFC 2988 測量出的順暢往返時間 (SRTT) 參數。平滑 RTT 演算法可處理 RTT 測量中可能發生的變化和異常狀況。
client_ip_address 用戶端的 IP 位址。除非用戶端使用 Proxy 或 X-Forwarded-For 標頭遭到竄改,否則這通常與 X-Forwarded-For 標頭中倒數第二個位址的用戶端 IP 位址相同。
client_port 用戶端的來源通訊埠。
client_encrypted true (如果用戶端與負載平衡器之間的連線已加密 (使用 HTTPS、HTTP/2 或 HTTP/3);否則為 false)。
client_protocol 用戶端與負載平衡器之間通訊所用的 HTTP 通訊協定。只能設為以下任一種:HTTP/1.0HTTP/1.1HTTP/2HTTP/3
origin_request_header 反映要求中 Origin 標頭的值,適用於跨源資源共享 (CORS) 用例。
server_ip_address 用戶端連線的負載平衡器 IP 位址。如果多個負載平衡器共用後端,這個做法就非常實用。這與 X-Forwarded-For 標頭中的最後一個 IP 位址相同。
server_port 用戶端連線的目標通訊埠編號。
tls_sni_hostname 伺服器名稱指標 (如 RFC 6066 中的定義),如果用戶端在 TLS 或 QUIC 交握期間提供。系統會將主機名稱轉換為小寫,並移除任何的尾隨點。
tls_version 在 SSL 交握期間,用戶端與負載平衡器之間協商的 TLS 版本。可能的值包括:TLSv1TLSv1.1TLSv1.2TLSv1.3。如果用戶端使用 QUIC 而非 TLS 進行連線,則值為 QUIC
tls_cipher_suite 在 TLS 交握期間協商的加密套件。這個值是由 IANA TLS 加密套件登錄檔定義的四個十六進位數字,例如 TLS_RSA_WITH_AES_128_GCM_SHA256 的值為 009C。對於 QUIC 和未加密的用戶端連線,該值為空。
tls_ja3_fingerprint JA3 TLS/SSL 指紋 (如果用戶端使用 HTTPS、HTTP/2 或 HTTP/3 連線)。

當負載平衡器無法確定變數的值時,會將其代換為空字串。例如:

  • 未使用 TLS 時的 TLS 參數
  • 要求不含 Origin 標頭時的 {origin_request_header}

地理值是根據用戶端 IP 位址判斷的預估值。Google 會不時更新這些值的資料,以提高準確度及反映地理和政治上的變化。即使原始 X-Forwarded-For 標頭包含有效的位置資訊,Google 仍會使用負載平衡器收到的封包所含來源 IP 位址資訊,估算用戶端位置。

雙向傳輸層安全標準 (TLS) 自訂標頭

如果在負載平衡器的 TargetHttpsProxy 上設定相互 TLS (mTLS),則可以使用下列額外標頭變數。

變數 說明
client_cert_present true 如果用戶端在 TLS 交握期間提供憑證;否則為 false
client_cert_chain_verified true (如果已根據設定的 TrustStore 驗證用戶端憑證鏈結);否則為 false
client_cert_error 代表錯誤情況的預先定義字串。如要進一步瞭解錯誤字串,請參閱「mTLS 用戶端驗證模式」。
client_cert_sha256_fingerprint 用戶端憑證的 Base64 編碼 SHA-256 指紋。
client_cert_serial_number 用戶端憑證的序號。 如果序號長度超過 50 個位元組,系統會將 client_cert_serial_number_exceeded_size_limit 字串加到 client_cert_error,並將序號設為空字串。
client_cert_spiffe_id

主體別名 (SAN) 欄位中的 SPIFFE ID。如果值無效或超過 2048 個位元組,SPIFFE ID 會設為空白字串。

如果 SPIFFE ID 長度超過 2048 個位元組,系統會將 client_cert_spiffe_id_exceeded_size_limit 字串加到 client_cert_error

client_cert_uri_sans

以逗號分隔的 Base64 編碼清單,列出 URI 類型的 SAN 擴充功能。 系統會從用戶端憑證擷取 SAN 擴充功能。 SPIFFE ID 不會包含在 client_cert_uri_sans 欄位中。

如果 client_cert_uri_sans 長度超過 512 個位元組,系統會將字串 client_cert_uri_sans_exceeded_size_limit 新增至 client_cert_error,並將以半形逗號分隔的清單設為空字串。

client_cert_dnsname_sans

以逗號分隔的 Base64 編碼清單,列出 DNSName 類型的 SAN 擴充功能。系統會從用戶端憑證擷取 SAN 擴充功能。

如果 client_cert_dnsname_sans 長度超過 512 個位元組,系統會將 client_cert_dnsname_sans_exceeded_size_limit 字串加到 client_cert_error,並將以半形逗號分隔的清單設為空字串。

client_cert_valid_not_before 時間戳記 (RFC 3339 日期字串格式),指出用戶端憑證失效的時間。例如:2022-07-01T18:05:09+00:00
client_cert_valid_not_after 用戶端憑證失效的時間戳記 (RFC 3339 日期字串格式)。例如:2022-07-01T18:05:09+00:00
client_cert_issuer_dn

憑證中 Base64 編碼的完整簽發者欄位。

如果 client_cert_issuer_dn 長度超過 512 個位元組,系統會將字串 client_cert_issuer_dn_exceeded_size_limit 新增至 client_cert_error,並將 client_cert_issuer_dn 設為空字串。

client_cert_subject_dn

憑證中 Base64 編碼的完整「主體」欄位。

如果 client_cert_subject_dn 長度超過 512 個位元組,系統會將字串 client_cert_subject_dn_exceeded_size_limit 新增至 client_cert_error,並將 client_cert_subject_dn 設為空字串。

client_cert_leaf

已建立 mTLS 連線的用戶端葉子憑證,且該憑證已通過驗證。憑證編碼符合 RFC 9440: 二進位 DER 憑證會使用 Base64 編碼 (不含換行符、 空格或 Base64 字母以外的其他字元),並以兩側的半形冒號做為分隔符。

如果 client_cert_leaf 超過 16 KB (未編碼),系統會將字串 client_cert_validated_leaf_exceeded_size_limit 新增至 client_cert_error,並將 client_cert_leaf 設為空字串。

client_cert_chain

以半形逗號分隔的憑證清單 (採用標準 TLS 順序),適用於已建立的 mTLS 連線,且用戶端憑證已通過驗證 (不含葉節點憑證)。憑證編碼符合 RFC 9440 規範。

如果 client_cert_leafclient_cert_chain 在 Base64 編碼前的總大小超過 16 KB,系統會在 client_cert_error 中加入字串 client_cert_validated_chain_exceeded_size_limit,並將 client_cert_chain 設為空字串。

限制

限制如下:

  • 您無法在區域內部應用程式負載平衡器和跨區域內部應用程式負載平衡器使用的後端服務上,設定自訂標頭。