URL マップでカスタム ヘッダーを作成する

このページでは、リージョン外部アプリケーション ロードバランサ、リージョン内部アプリケーション ロードバランサ、クロスリージョン内部アプリケーション ロードバランサで使用される URL マップでカスタム ヘッダーがどのように機能するかについて説明します。

カスタム リクエスト ヘッダーとカスタム レスポンス ヘッダーを使用すると、ロードバランサが HTTP(S) のリクエストとレスポンスに追加できる追加のヘッダーを指定できます。ロードバランサで検出された情報に応じて、これらのヘッダーには次の情報が含まれます。

  • クライアントまでのレイテンシ
  • クライアントの IP アドレスの地理的位置
  • TLS 接続のパラメータ

始める前に

必要に応じて、次のコマンドで Google Cloud CLI を最新バージョンに更新します。

gcloud components update

カスタム ヘッダーの動作

カスタム ヘッダーは次のように動作します。

  • ロードバランサがバックエンドにリクエストを行うと、ロードバランサはリクエスト ヘッダーを追加します。

    ロードバランサは、カスタム リクエスト ヘッダーをクライアント リクエストにのみ追加します。ヘルスチェック プローブには追加しません。バックエンドで認可に特定のヘッダーが必要であり、ヘルスチェック パケットにヘッダーが含まれていない場合、ヘルスチェックが失敗する可能性があります。

  • ロードバランサはレスポンス ヘッダーを設定してから、クライアントにレスポンスを返します。

リージョン外部アプリケーション ロードバランサ、リージョン内部アプリケーション ロードバランサ、クロスリージョン内部アプリケーション ロードバランサでカスタム ヘッダーを有効にするには、URL マップ構成でヘッダー名とヘッダー値のリストを指定します。

ヘッダー名のプロパティは次のとおりです。

  • ヘッダー名は有効な HTTP ヘッダー フィールド定義でなければなりません(RFC 7230 に準拠)。
  • ヘッダー名を X-User-IP にすることはできません。
  • ヘッダー名を X-GoogleX-Goog-X-GFE、または X-Amz- で始めることはできません。
  • ヘッダー名を Host または authority にすることはできません。Hostauthority はどちらも Google Cloud が予約する特殊なキーワードです。これらのヘッダーは Envoy ベースのロードバランサでは変更できません。代わりに、予約されたヘッダー名が干渉しないように、他のカスタム ヘッダー(MyHost など)を作成することをおすすめします。
  • ヘッダーのリストに、ヘッダー名を複数回使用することはできません。

ヘッダー名では、大文字と小文字は区別されません。ヘッダー名が HTTP/2 バックエンドに渡されると、HTTP/2 プロトコルによりヘッダー名は小文字としてエンコードされます。

ヘッダー値のプロパティは次のとおりです。

  • ヘッダー値は、HTTP ヘッダー フィールドで有効な定義でなければなりません(RFC 7230 に準拠、古いフォームは使用不可)。
  • ヘッダー値は空白にできません。空白のヘッダーは拒否されます。
  • ヘッダー値には、中括弧で囲まれた 1 つ以上の変数を含めることができます。この変数は、ロードバランサで提供される値に展開されます。ヘッダー値で使用できる変数の一覧については、ヘッダー値に表示できる変数をご覧ください。

ヘッダー値では、先頭の空白と末尾の空白は重要ではなく、バックエンドには渡されません。ヘッダー値で中括弧を許可するために、ロードバランサでは 2 つの左中括弧({{)を単一の左中括弧({)に変換し、2 つの右中括弧(}})を単一の右中括弧(})に変換します。

リクエスト ヘッダーまたはレスポンス ヘッダーを追加する

リクエスト ヘッダーまたはレスポンス ヘッダーを追加するには、gcloud CLI を使用して URL マップを次のように編集します。

リージョン

    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
                 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
    

クロスリージョン

    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_region クライアントの IP アドレスに関連付けられる国(またはリージョン)。これは、USFR などの Unicode CLDR リージョン コードです。(ほとんどの国では、このコードが ISO-3166-2 コードに直接対応しています)
client_rtt_msec ロードバランサと HTTP(S) クライアント間の推定ラウンドトリップ送信時間(ミリ秒単位)。これは、ロードバランサの TCP スタックによって測定される平滑化されたラウンドトリップ時間(SRTT)パラメータです(RFC 2988 を遵守)。平滑化された RTT は、RTT 測定値で発生する可能性のある変動と異常を処理するアルゴリズムです。
client_ip_address クライアントの IP アドレス。通常、これは X-Forwarded-For ヘッダー内で最後から 2 番目にあるアドレス(クライアント IP アドレス)と同じです。ただし、クライアントがプロキシを使用している場合や、X-Forwarded-For ヘッダーが改変されている場合を除きます。
client_port クライアントの送信元ポート。
client_encrypted クライアントとロードバランサ間の接続が暗号化されている場合(HTTPS、HTTP/2 または HTTP/3 を使用)は true、それ以外の場合は false です。
client_protocol クライアントとロードバランサ間の通信に使用される HTTP プロトコル。HTTP/1.0HTTP/1.1HTTP/2HTTP/3、のいずれか。
origin_request_header クロスオリジン リソース シェアリング(CORS)のユースケースのリクエストに含まれる Origin ヘッダーの値を反映したものになります。
server_ip_address クライアントが接続するロードバランサの IP アドレス。これは、複数のロードバランサが共通のバックエンドを共有する場合に便利です。これは、X-Forwarded-For ヘッダーの最後の IP アドレスと同じです。
server_port クライアントが接続する宛先ポート番号。
tls_sni_hostname RFC 6066 で定義されたサーバー名表示(TLS または QUIC handshake 中にクライアントによって提供された場合)。ホスト名は小文字に変換され、末尾のドットはすべて削除されます。
tls_version SSL handshake 中にクライアントとロードバランサの間でネゴシエートされた TLS バージョン。可能な値は TLSv1TLSv1.1TLSv1.2TLSv1.3 です。クライアントが TLS ではなく QUIC を使用して接続した場合、値は QUIC です。
tls_cipher_suite TLS handshake 中にネゴシエートされた暗号スイート。値は、IANA TLS Cipher Suite Registry で定義された 4 桁の 16 進数です。たとえば、TLS_RSA_WITH_AES_128_GCM_SHA256 の場合は 009C となります。この値は、QUIC と暗号化されていないクライアント接続の場合には空です。
tls_ja3_fingerprint JA3 TLS / SSL フィンガープリント(クライアントが HTTPS、HTTP/2 または HTTP/3 を使用して接続している場合)。

ロードバランサで値を決定できない場合、変数は空の文字列に展開されます。例:

  • IP アドレスのロケーションが不明な場合の地理的なロケーションの変数
  • TLS が使用されていない場合の TLS パラメータ
  • リクエストに Origin ヘッダーが含まれていない場合の {origin_request_header}

地理的な値は、クライアントの IP アドレスに基づく推定値です。Google では、正確性を高め、地理的、政治的な変化を反映させるため、これらの値を提供するデータを随時更新しています。元の X-Forwarded-For ヘッダーに有効な位置情報が含まれている場合でも、Google はロードバランサで受信したパケットに含まれる送信元 IP アドレス情報を使用して、クライアントの位置を推定します。

相互 TLS カスタム ヘッダー

ロードバランサの TargetHttpsProxy で相互 TLS(mTLS)が構成されている場合、次の追加のヘッダー変数を使用できます。

変数 説明
client_cert_present TLS handshake 中にクライアントが証明書を提供した場合は 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_serial_number_exceeded_size_limitclient_cert_error に設定され、シリアル番号は空の文字列に設定されます。
client_cert_spiffe_id

サブジェクト代替名(SAN)フィールドの SPIFFE ID。値が無効であるか、2,048 バイトを超える場合、SPIFFE ID は空の文字列に設定されます。

SPIFFE ID が 2,048 バイトを超える場合、文字列 client_cert_spiffe_id_exceeded_size_limitclient_cert_error に追加されます。

client_cert_uri_sans

URI 型の SAN 拡張機能のカンマ区切り Base64 エンコード リスト。SAN 拡張機能はクライアント証明書から抽出されます。client_cert_uri_sans フィールドに SPIFFE ID は含まれません。

client_cert_uri_sans が 512 バイトを超える場合、client_cert_uri_sans_exceeded_size_limitclient_cert_error に追加され、カンマ区切りリストは空の文字列に設定されます。

client_cert_dnsname_sans

DNSName タイプの SAN 拡張機能のカンマ区切り Base64 エンコード リスト。SAN 拡張機能はクライアント証明書から抽出されます。

client_cert_dnsname_sans が 512 バイトを超える場合、文字列 client_cert_dnsname_sans_exceeded_size_limitclient_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_limitclient_cert_error に追加され、client_cert_issuer_dn は空の文字列に設定されます。

client_cert_subject_dn

Base64 でエンコードされた証明書の完全なサブジェクト フィールド。

client_cert_subject_dn が 512 バイトを超える場合、文字列 client_cert_subject_dn_exceeded_size_limitclient_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_limitclient_cert_error に追加され、client_cert_leaf が空の文字列に設定されます。

client_cert_chain

クライアント証明書が検証に合格している確立済みの mTLS 接続のクライアント証明書チェーンの証明書のリスト。このリストはカンマ区切りで、標準の TLS 順序になっています(リーフ証明書は含みません)。証明書のエンコードは RFC 9440 に準拠しています。

Base64 エンコード前の client_cert_leafclient_cert_chain の合計サイズが 16KB を超えると、client_cert_validated_chain_exceeded_size_limitclient_cert_error に追加され、client_cert_chain が空の文字列に設定されます。

制限事項

リージョン ロードバランサで使用されるカスタム ヘッダーには、次の制限が適用されます。

  • リージョン外部アプリケーション ロードバランサで使用されるリージョン バックエンド サービス、リージョン内部アプリケーション ロードバランサ、クロスリージョン内部アプリケーション ロードバランサで使用されるグローバル バックエンド サービスにカスタム ヘッダーを構成することはできません。
  • 次のカスタム ヘッダー変数は、リージョン外部アプリケーション ロードバランサではサポートされていません。
    • cdn_cache_id
    • cdn_cache_status
    • client_region_subdivision
    • client_city
    • client_city_lat_long