在後端服務中建立自訂標頭

本頁面說明如何設定全域外部應用程式負載平衡器所用後端服務的自訂標頭。

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

  • 用戶端延遲時間
  • 用戶端 IP 位址的地理位置
  • TLS 連線參數

後端服務支援自訂要求標頭,後端服務和後端 bucket 則支援自訂回應標頭。

根據預設,負載平衡器會在後端和用戶端之間代理的所有 HTTP(S) 要求和回應中,新增特定標頭。詳情請參閱「目標 Proxy」。

網址對應中的自訂標頭

全域外部應用程式負載平衡器支援網址對應中標頭轉換的類似功能。雖然您可以在後端服務中管理自訂標頭 (如本頁所述),但建議您將標頭轉換作業放在網址對應中,以便在單一位置維護所有標頭轉換作業。

如果網址對應和後端服務中都有自訂標頭設定,系統會套用這兩項設定。不過,如果後端服務和網址對應中都設定了相同的標頭,則網址對應會優先採用,後端服務設定則會遭到忽略。如需網址對應範例,請參閱「設定全域外部應用程式負載平衡器的流量管理」。

事前準備

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

    gcloud components update
    

自訂標頭的運作方式

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

  • 負載平衡器將要求轉送至後端時,會新增要求標頭。

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

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

如要啟用自訂標頭,請在後端服務或後端 bucket 的屬性中指定標頭清單。

請將每個標頭指定為 header-name:header-value 字串。標頭必須包含半形冒號,用來分隔標頭名稱和標頭值。

標頭名稱必須符合下列規定:

  • 標頭名稱必須是有效的 HTTP 標頭欄位名稱定義 (依據 RFC 7230)。
  • Host 標頭可以設定,但須遵守特定限制。
  • 標頭名稱不得為 authority。這是Google Cloud保留的特殊關鍵字。您無法為 Envoy 型負載平衡器 (例如全域外部應用程式負載平衡器) 修改這個標頭。建議您改為建立其他自訂標頭,以免干擾保留的標頭名稱。
  • 標頭名稱不得為 X-User-IP 或 CDN-Loop。
  • 請勿使用下列逐躍點標頭:Keep-Alive、Transfer-Encoding、TE、Connection、Trailer 和 Upgrade。根據 RFC 2616,快取不會儲存這些標頭,目標 Proxy 也不會傳播這些標頭。
  • 標頭名稱開頭不得為 X-Google、X-Goog-、X-GFE 或 X-Amz-。
  • 標頭名稱在新增標頭清單中不可出現超過一次。

標頭值必須符合下列規定:

  • 依據 RFC 7230 的規定,標頭值必須是有效的 HTTP 標頭欄位定義,且不得使用過時格式。
  • 標頭值可以留空。
  • 標頭值可以包含一或多個變數 (以大括號括住),這些變數會展開為負載平衡器提供的值。詳情請參閱「標頭值支援的變數」。

gcloud 指令列工具提供 --custom-request-header 旗標,可用來指定要求標頭。請務必使用這個旗標,將標頭名稱和標頭值括在直單引號 (') 中。

標記的格式大致如下:

    --custom-request-header='HEADER_NAME:[HEADER_VALUE]'

以下是標頭值的範例,其中包含兩個變數 client_region 和 client_city,並以大括號括住。

    --custom-request-header='X-Client-Geo-Location:{client_region},{client_city}'

負載平衡器會對位於加州山景城的用戶端新增以下的標頭:

X-Client-Geo-Location:US,Mountain View

如要建立具有自訂標頭的後端服務,請參閱「設定自訂要求標頭」。

主機標頭

使用全域外部應用程式負載平衡器設定自訂 Host 標頭時,須遵守下列限制:

  • 只有在取代現有 Host 要求標頭時,才能設定自訂 Host 要求標頭。
  • 您無法使用網址對應中的標頭動作,設定自訂 Host 回應標頭。不過,您仍可在後端服務中設定自訂 Host 回應標頭。
  • 此外,要求和回應標頭也適用下列規定:
    • 您無法附加或移除自訂 Host 標頭。
    • 您無法搭配使用變數和自訂 Host 標頭。

標頭值支援的變數

如要將動態、要求專屬的中繼資料插入自訂標頭,可以使用下列變數。在標頭值中,如果這些變數以大括號 ({}) 括住,負載平衡器會將其展開為即時值 (例如用戶端的地理位置、連線參數或快取狀態),然後再將標頭傳遞至後端或用戶端。

變數 說明
cdn_cache_id 用於處理要求的快取執行個體位置代碼和 ID。這個值與 Logging 中 Cloud CDN 要求記錄 jsonPayload.cacheId 欄位填入的值相同。
cdn_cache_status 目前的快取狀態。hit、miss、revalidated、stale、uncacheable 或 disabled,適用於由已啟用 Cloud CDN 的後端提供的任何物件。
origin_request_header 反映跨源資源共享 (CORS) 用途要求中 Origin 標頭的值。
client_rtt_msec 負載平衡器與 HTTP(S) 用戶端之間的預估往返傳輸時間,以毫秒為單位。這是負載平衡器 TCP 堆疊根據 RFC 2988 測得的平滑封包往返時間 (SRTT) 參數。平滑封包往返時間是一種演算法,可在封包往返時間測量結果中,處理可能發生的變化和異常狀況。
client_region 與用戶端 IP 位址關聯的國家 (或地區)。這是 Unicode CLDR 區域代碼,例如 US 或 FR。(對大多數國家/地區來說,這些代碼會直接對應至 ISO-3166-2 代碼)。
client_region_subdivision 與用戶端 IP 位址相關聯的國家/地區行政區,例如省或州。這是 Unicode CLDR 子分區 ID,例如 USCA 或 CAON。(這些 Unicode 代碼衍生自 ISO-3166-2 標準定義的子區域)。
client_city 要求來源城市的名稱,例如 Mountain View 代表加州山景城。這個變數沒有有效的標準值清單。城市名稱可以包含 US-ASCII 字母、數字、空格和下列字元:!#$%&'*+-.^_`|~。
client_city_lat_long 要求來源城市的經緯度,例如 37.386051,-122.083851 代表來自 Mountain View 的要求。
client_ip_address 用戶端的 IP 位址。這通常與用戶端 IP 位址相同,也就是 X-Forwarded-For 標頭中的倒數第二個位址,除非用戶端使用 Proxy 或 X-Forwarded-For 標頭遭到竄改。
client_port 用戶端的來源通訊埠。
client_encrypted 如果用戶端與負載平衡器之間的連線已加密 (使用 HTTPS、HTTP/2 或 HTTP/3),則為 true;否則為 false。
client_protocol 用戶端與負載平衡器之間通訊所用的 HTTP 通訊協定。HTTP/1.0、HTTP/1.1、HTTP/2 或 HTTP/3 之一。
device_request_type

用戶端的裝置,衍生自 User-Agent 標頭值。

可能的值如下:DESKTOP、GAME_CONSOLE、GAME_CONSOLE、MOBILE、SET_TOP_BOX、SMART_SPEAKER、SMART_TV、TABLET、UNDETERMINED、WEARABLE。

server_ip_address 用戶端連線的負載平衡器 IP 位址。如果多個負載平衡器共用相同的後端,這項功能就非常實用。這與 X-Forwarded-For 標頭中的最後一個 IP 位址相同。
server_port 用戶端連線的目的地通訊埠編號。
tls_sni_hostname 伺服器名稱指示 (如 RFC 6066 所定義),前提是用戶端在 TLS 或 QUIC 握手期間提供。主機名稱會轉換為小寫,並移除任何結尾點。
tls_version 用戶端與負載平衡器在 SSL 握手期間協商的 TLS 版本。可能的值包括:TLSv1、TLSv1.1、TLSv1.2 和 TLSv1.3。如果用戶端使用 QUIC (而非 TLS) 連線,則值為 QUIC。
tls_cipher_suite 在 TLS 握手期間交涉的加密套件。這個值是由 IANA TLS 加密套件登錄檔定義的四個十六進位數字,例如 TLS_RSA_WITH_AES_128_GCM_SHA256 的 009C。如果是 QUIC 和未加密的用戶端連線,這個值會是空白。
tls_ja3_fingerprint 如果用戶端使用 HTTPS、HTTP/2 或 HTTP/3 連線,則為 JA3 TLS/SSL 指紋。
tls_ja4_fingerprint 如果用戶端使用 HTTPS、HTTP/2 或 HTTP/3 連線,則為 JA4 TLS/SSL 指紋。
user_agent_family

用戶端的瀏覽器類型,衍生自 User-Agent 標頭值。

可能的值如下:APPLE、APPLEWEBKIT、BLACKBERRY、DOCOMO、GECKO、GOOGLE、KHTML、KOREAN、MICROSOFT、MSIE、NETFRONT、NOKIA、OBIGO、OPERA、OPENWAVE、OTHER、POLARIS、SEMC、SMIT、TELECA、USER_DEFINED。

asn 與用戶端 IP 位址相關聯的自治系統編號 (ASN)。
cloud_trace_id 從 HTTP 要求標頭擷取 (或產生) 的追蹤 ID。
hostname 用戶端在 Host HTTP 要求標頭中指定的主機名稱。這個值會轉換為小寫,並移除所有結尾點。

如果負載平衡器無法判斷變數的值,就會將變數展開為空字串。例如:

  • IP 位址位置不明時的地理位置變數
  • 未使用 TLS 時的 TLS 參數
  • 如果要求不含 Origin 標頭,則為 {origin_request_header}
  • 要求標頭中包含 {cdn_cache_status} 標頭

地理位置值 (區域、子區域和城市) 是根據用戶端的 IP 位址估算而得。Google 會不時更新提供這些值的資料,以提高準確度,並反映地理和政治變化。即使原始 X-Forwarded-For 標頭包含有效的位置資訊,Google 仍會使用負載平衡器收到的封包中包含的來源 IP 位址資訊,來估算用戶端位置。

負載平衡器新增的標頭會覆寫任何名稱相同的既有標頭。標頭名稱不區分大小寫。標頭名稱傳送至 HTTP/2 後端時,HTTP/2 通訊協定會將標頭名稱轉換成小寫編碼。

標頭值中的前置空格及後置空格無關緊要,系統並不會將其傳送至後端。為了允許標頭值使用大括號,負載平衡器會將兩個左大括號 ({{) 解讀為一個左大括號 ({),並將兩個右大括號 (}}) 解讀為一個右大括號 (})。

雙向 TLS 自訂標頭

如果負載平衡器的 TargetHttpsProxy 已設定雙向 TLS (mTLS),則可使用下列其他標頭變數。

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

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

如果 SPIFFE ID 超過 2048 個位元組,client_cert_error 會設為 client_cert_spiffe_id_exceeded_size_limit。

client_cert_uri_sans

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

如果 client_cert_uri_sans 超過 512 個位元組,client_cert_error 會設為 client_cert_uri_sans_exceeded_size_limit,並將以逗號分隔的清單設為空字串。

client_cert_dnsname_sans

以半形逗號分隔、採用 Base64 編碼的 DNSName 類型 SAN 擴充功能清單。SAN 擴充功能會從用戶端憑證中擷取。

如果 client_cert_dnsname_sans 超過 512 個位元組,client_cert_error 會設為 client_cert_dnsname_sans_exceeded_size_limit,並將以逗號分隔的清單設為空字串。

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

憑證中完整 Issuer 欄位的 Base64 編碼 DER 編碼。

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

client_cert_subject_dn

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

如果 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 編碼,並以冒號分隔。

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

client_cert_chain

已建立的 mTLS 連線中,用戶端憑證鏈結的憑證清單 (以半形逗號分隔,並依標準 TLS 順序排列),其中用戶端憑證已通過驗證,但不含分葉憑證。憑證編碼符合 RFC 9440 規範。

如果 client_cert_leaf 和 client_cert_chain 在 Base64 編碼前的合併大小超過 16 KB,系統會將字串 client_cert_validated_chain_exceeded_size_limit 新增至 client_cert_error,並將 client_cert_chain 設為空字串。

設定自訂要求標頭

控制台

如要將自訂要求標頭新增至現有的後端服務:

  1. 前往「Load balancing」(負載平衡) 摘要頁面。
    前往「Load balancing」(負載平衡) 頁面
  2. 點選「後端」。
  3. 按一下後端服務的名稱。
  4. 按一下「Edit」(編輯)。
  5. 按一下 [Advanced configurations (Session affinity, connection draining timeout, security policies)] (進階設定 (工作階段相依性、連線排除逾時、安全性政策))。
  6. 在「Custom request headers」(自訂要求標頭) 下方,按一下 [Add header] (新增標頭)。
  7. 輸入自訂要求標頭的「Header name」(標頭名稱) 和「Header value」(標頭值)。
  8. 輸入任何其他自訂要求標頭。
  9. 按一下 [Save] (儲存)。

如要從後端服務移除自訂要求標頭:

  1. 前往「Load balancing」(負載平衡) 摘要頁面。
    前往「Load balancing」(負載平衡) 頁面
  2. 點選「後端」。
  3. 按一下後端服務的名稱。
  4. 按一下「Edit」(編輯)。
  5. 按一下 [Advanced configurations (Session affinity, connection draining timeout, security policies)] (進階設定 (工作階段相依性、連線排除逾時、安全性政策))。
  6. 找出要移除的自訂要求標頭,然後按一下名稱旁的「X」X。
  7. 按一下 [儲存]。

gcloud

如要指定自訂要求標頭,請使用 gcloud compute backend-services create 或 gcloud compute backend-services update 指令,並加上 --custom-request-header 旗標。

如要建立具有自訂要求標頭的後端服務,請按照下列步驟操作:

gcloud compute backend-services create BACKEND_SERVICE_NAME \
    --global-health-checks \
    --global \
    --protocol HTTPS \
    --health-checks https-basic-check \
    --custom-request-header='HEADER_NAME:[HEADER_VALUE]'

如要新增更多要求標頭,請重複 --custom-request-header 旗標,指定不重複的標頭名稱和值。

如要將自訂標頭新增至現有後端服務,請按照下列步驟操作:

gcloud compute backend-services update BACKEND_SERVICE_NAME \
    --global \
    --custom-request-header='HEADER_1_NAME:[HEADER_1_VALUE]' \
    --custom-request-header='HEADER_2_NAME:[HEADER_2_VALUE]'

上一個步驟會將後端服務中原有的標頭,替換成您在指令中指定的要求標頭。

如要從後端服務移除所有標頭:

gcloud compute backend-services update BACKEND_SERVICE_NAME \
    --global \
    --no-custom-request-headers

API

對 backendServices.patch 方法發出 PATCH 要求:

PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME
"customRequestHeaders": [
   "client_city:Mountain View"
]

設定自訂回應標頭

控制台

如要將自訂回應標頭新增至現有後端服務,請按照下列步驟操作:

  1. 前往「Load balancing」(負載平衡) 摘要頁面。
    前往「Load balancing」(負載平衡) 頁面
  2. 點選「後端」。
  3. 按一下後端服務的名稱。
  4. 按一下「Edit」(編輯)。
  5. 按一下 [Advanced configurations (Session affinity, connection draining timeout, security policies)] (進階設定 (工作階段相依性、連線排除逾時、安全性政策))。
  6. 在「Custom response headers」(自訂回應標頭) 下方,按一下「Add header」(新增標頭)。
  7. 輸入自訂回應標頭的「Header name」(標頭名稱) 和「Header value」(標頭值)。
  8. 輸入其他自訂回應標頭。
  9. 按一下 [儲存]。

如要從後端服務移除自訂回應標頭,請按照下列步驟操作:

  1. 前往「Load balancing」(負載平衡) 摘要頁面。
    前往「Load balancing」(負載平衡) 頁面
  2. 點選「後端」。
  3. 按一下後端服務的名稱。
  4. 按一下「Edit」(編輯)。
  5. 按一下 [Advanced configurations (Session affinity, connection draining timeout, security policies)] (進階設定 (工作階段相依性、連線排除逾時、安全性政策))。
  6. 找出要移除的自訂回應標頭,然後按一下名稱旁的「X」X。
  7. 按一下 [儲存]。

gcloud

如為後端服務,請使用 gcloud compute backend-services create 或 gcloud compute backend-services update 指令,並加上 --custom-response-header 旗標。

如為後端 bucket,請使用 gcloud compute backend-buckets create 或 gcloud compute backend-buckets update 指令,並加上 --custom-response-header 旗標。

gcloud compute backend-services (create | update) BACKEND_SERVICE_NAME
    --custom-response-header='HEADER_NAME:[HEADER_VALUE]'
gcloud compute backend-buckets (create | update) BACKEND_BUCKET_NAME
    --custom-response-header='HEADER_NAME:[HEADER_VALUE]'

X-Frame-Options 標頭範例:

gcloud compute backend-buckets update gaming-lab \
    --custom-response-header='X-Frame-Options: DENY'

Strict-Transport-Security 標頭範例:

以下範例說明如何新增自訂回應標頭,以支援 HTTP 嚴格傳輸安全性 (HSTS):

gcloud compute backend-services update customer-bs-name \
    --global \
    --custom-response-header='Strict-Transport-Security: max-age=63072000'

API

如為後端 bucket,請使用 Method: backendBuckets.insert 或 Method: backendBuckets.update API 呼叫。

如為後端服務,請使用 Method: backendServices.insert 或 Method: backendServices.update API 呼叫。

請使用下列其中一個 API 呼叫:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets

PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets/BACKEND_BUCKET_NAME

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices

PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME

在 JSON 要求主體中新增下列程式碼片段:

"customResponseHeaders":HEADER_NAME:[HEADER_VALUE]

設定 Cloud Storage 的回應標頭

如需在 Cloud Storage 的回應中設定 HTTP 標頭 (例如跨源資源政策、X-Frame-Options 或 X-XSS-Protection 標頭),Google Cloud 可讓您在 Cloud CDN 搭配 Cloud Storage 使用時,設定自訂標頭。如要這麼做,請在負載平衡器後端 bucket 層級設定自訂標頭,詳情請參閱本頁說明。

只有在用戶端要求傳送至負載平衡器 IP 位址時,系統才會將在後端 bucket 層級設定的自訂回應標頭新增至回應。如果用戶端要求是直接傳送至 Cloud Storage API,則不會在回應中加入自訂標頭。

搭配使用自訂標頭和 Google Cloud Armor

您可以在後端服務上使用 {cloud_trace_id} 變數設定自訂回應標頭,將不重複的追蹤 ID 傳回用戶端,包括 Cloud Armor 安全性政策拒絕要求時。您可以使用這個追蹤 ID,在 Logging 中查詢對應的要求記錄項目。詳情請參閱「在記錄中找出並關聯遭封鎖的要求」。

設定 Cloud Armor 安全性政策時,您也可以設定 Cloud Armor 插入自訂要求標頭和值。如果 Cloud Armor 安全性政策設定為插入與全域外部應用程式負載平衡器或傳統版應用程式負載平衡器自訂標頭相同的自訂標頭名稱,則 Cloud Armor 安全性政策中指定的標頭值會遭到負載平衡器填入的值覆寫。如果不想覆寫 Cloud Armor 政策,請務必使用不同名稱。

限制

與全域負載平衡器搭配使用的自訂標頭有下列限制:

  • 每項後端服務的所有自訂要求標頭 (名稱和值合併,在變數展開之前) 總大小不得超過 8 KB 或 16 個要求標頭。
  • 每項後端服務的所有自訂回應標頭 (名稱和值合併,在變數展開之前) 總大小不得超過 8 KB 或 16 個回應標頭。