Créer des en-têtes personnalisés dans les services de backend

Cette page explique comment configurer des en-têtes personnalisés dans les services de backend utilisés par l'équilibreur de charge d'application classique.

Les en-têtes de requêtes et de réponses personnalisés vous permettent de spécifier des en-têtes supplémentaires que l'équilibreur de charge peut ajouter aux requêtes et aux réponses HTTP(S). En fonction des informations détectées par l'équilibreur de charge, ces en-têtes peuvent inclure les informations suivantes :

  • Latence vis-à-vis du client
  • Emplacement géographique de l'adresse IP du client
  • Paramètres de la connexion TLS

Les en-têtes de requêtes personnalisés sont acceptés pour les services de backend, tandis que les en-têtes de réponses personnalisés sont acceptés pour les services de backend et les buckets de backend.

L'équilibreur de charge ajoute par défaut certains en-têtes à toutes les requêtes et réponses HTTP(S) qu'il relaie entre les backends et les clients. Pour en savoir plus, consultez la section Proxys cibles.

Avant de commencer

  • Si nécessaire, installez la dernière version de Google Cloud CLI :

    gcloud components update
    

Fonctionnement des en-têtes personnalisés

Les en-têtes personnalisés fonctionnent comme suit :

  • Lorsque l'équilibreur de charge transmet une requête au backend, il ajoute des en-têtes de requêtes.

    L'équilibreur de charge n'ajoute des en-têtes de requêtes personnalisés qu'aux requêtes client, et non aux vérifications d'état. Si votre backend nécessite un en-tête spécifique pour l'autorisation qui ne figure dans le paquet de vérification d'état, la vérification d'état peut échouer.

  • L'équilibreur de charge définit des en-têtes de réponse avant de renvoyer les réponses au client.

Pour activer les en-têtes personnalisés, vous devez spécifier une liste d'en-têtes dans une propriété du service de backend ou du bucket de backend.

Spécifiez chaque en-tête en tant que chaîne header-name:header-value. Le nom (header-name) et la valeur (header-value) de l'en-tête doivent être séparés par deux points.

Les noms d'en-têtes doivent répondre aux exigences suivantes :

  • Le nom d'en-tête doit être une définition de nom de champ d'en-tête HTTP valide (conformément à la RFC 7230).
  • Le nom d'en-tête ne peut pas être X-User-IP ni CDN-Loop.
  • Les en-têtes de saut par saut suivants ne doivent pas être utilisés : Keep-Alive, Transfer-Encoding, TE, Connection, Trailer, Upgrade, Proxy-Authorization et Proxy-Authenticate. Conformément à la norme RFC 2616, ces en-têtes ne sont pas stockés par les caches et ne sont pas propagés par les proxys cibles.
  • Le nom d'en-tête ne doit pas commencer par X-Google, X-Goog-, X-GFE ou X-Amz-.
  • Un nom d'en-tête ne doit pas apparaître plus d'une fois dans la liste des en-têtes ajoutés.

Les valeurs d'en-tête doivent répondre aux exigences suivantes :

  • La valeur d'en-tête doit être une définition de champ d'en-tête HTTP valide (conformément à la RFC 7230, les formats obsolètes n'étant pas acceptés).
  • La valeur de l'en-tête peut être vide.
  • La valeur de l'en-tête peut contenir une ou plusieurs variables, délimitées par des accolades. C'est à l'équilibreur de charge de fournir les valeurs nécessaires à l'expansion des variables. Vous trouverez une liste des variables autorisées pour la valeur d'en-tête dans la section qui suit.

L'outil de ligne de commande gcloud possède un indicateur permettant de spécifier des en-têtes de requêtes : --custom-request-header. Veillez à placer le nom et la valeur de l'en-tête entre guillemets simples droits (') avec cette option.

Le format général de cet indicateur est le suivant :

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

Voici un exemple de valeur d'en-tête avec deux variables, client_region et client_city, placées entre accolades.

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

Pour les clients situés à Mountain View, en Californie, l'équilibreur de charge ajoute l'en-tête ci-dessous :

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

Pour créer un service de backend avec des en-têtes personnalisés, consultez la section Configurer des en-têtes de requête personnalisés.

Variables compatibles avec les valeurs d'en-tête

Les variables suivantes peuvent apparaître dans les valeurs d'en-têtes personnalisés.

Variable Description
cdn_cache_id Code d'emplacement et ID de l'instance de cache utilisée pour diffuser la requête. Il s'agit de la même valeur que celle indiquée dans le champ jsonPayload.cacheId des journaux de requêtes Cloud CDN dans Logging.
cdn_cache_status État actuel du cache. Les valeurs peuvent être hit, miss, revalidated, stale, uncacheable ou disabled pour tout objet diffusé par un backend sur lequel Cloud CDN est activé.
origin_request_header Correspond à la valeur de l'en-tête Origin dans la requête pour les cas d'utilisation CORS (Cross-Origin Resource Sharing).
client_rtt_msec Temps de transmission aller-retour estimé entre l'équilibreur de charge et le client HTTP(S), en millisecondes. Il s'agit du paramètre de temps d'aller-retour lissé (SRTT, Smoothed Round-Trip Time) mesuré par la pile TCP de l'équilibreur de charge, conformément à la RFC 2988. Le DAR lissé est un algorithme qui traite les variations et les anomalies pouvant se produire dans les mesures de latence DAR.
client_region Pays (ou région) associé à l'adresse IP du client. Il s'agit d'un code de région CLDR au format Unicode, tel que US ou FR. Pour la plupart des pays, ces codes correspondent directement aux codes ISO-3166-2.
client_region_subdivision Subdivision (une province ou un État, par exemple) du pays associée à l'adresse IP du client. Il s'agit d'un ID de subdivision CLDR au format Unicode, tel que USCA ou CAON. Ces codes Unicode sont dérivés des subdivisions définies par la norme ISO-3166-2.
client_city Nom de la ville d'origine de la requête, par exemple Mountain View pour Mountain View en Californie. Il n'existe pas de liste canonique de valeurs valides pour cette variable. Les noms de villes peuvent contenir des lettres, des chiffres et des espaces au format US-ASCII, ainsi que les caractères suivants : !#$%&'*+-.^_`|~.
client_city_lat_long Latitude et longitude de la ville d'origine de la requête, par exemple 37.386051,-122.083851 pour une requête provenant de Mountain View.
client_ip_address Adresse IP du client. Cette valeur est généralement identique à l'adresse IP du client qui figure comme avant-dernière adresse dans l'en-tête X-Forwarded-For, sauf si le client utilise un proxy ou si l'en-tête X-Forwarded-For a été altéré.
client_port Port source du client.
client_encrypted true si la connexion entre le client et l'équilibreur de charge est chiffrée (via HTTPS, HTTP/2 ou HTTP/3), sinon false.
client_protocol Protocole HTTP utilisé pour la communication entre le client et l'équilibreur de charge. Valeurs possibles : HTTP/1.0, HTTP/1.1, HTTP/2 ou HTTP/3.
server_ip_address Adresse IP de l'équilibreur de charge auquel le client se connecte. Cela peut être utile lorsque plusieurs équilibreurs de charge partagent des backends communs. Cette valeur est identique à la dernière adresse IP de l'en-tête X-Forwarded-For.
server_port Numéro du port de destination auquel le client se connecte.
tls_sni_hostname Indication du nom du serveur (telle que définie dans la RFC 6066), si ce nom est fourni par le client lors du handshake TLS ou QUIC. Le nom d'hôte est converti en minuscules et tous les points se trouvant à la fin du nom sont supprimés.
tls_version Version de TLS négociée entre le client et l'équilibreur de charge lors du handshake SSL. Les valeurs possibles sont TLSv1, TLSv1.1, TLSv1.2 et TLSv1.3. Si le client se connecte à l'aide de QUIC au lieu de TLS, la valeur est QUIC.
tls_cipher_suite Suite de chiffrement négociée lors du handshake TLS. La valeur se compose de quatre chiffres hexadécimaux. Elle est définie par le Registre de l'IANA portant sur la suite de chiffrement TLS. Par exemple, 009C correspond à TLS_RSA_WITH_AES_128_GCM_SHA256. Cette valeur est vide pour QUIC et pour les connexions clientes non chiffrées.
tls_ja3_fingerprint Empreinte TLS/SSL JA3 si le client se connecte via HTTPS, HTTP/2 ou HTTP/3.

L'équilibreur de charge procède à l'expansion des variables sous forme de chaînes vides lorsqu'il ne peut pas déterminer leur valeur. Par exemple :

  • Variables représentant des emplacements géographiques lorsque l'emplacement de l'adresse IP est inconnu
  • Paramètres TLS lorsque TLS n'est pas utilisé
  • Valeur {origin_request_header} lorsque la requête n'inclut pas d'en-tête Origin.
  • En-tête {cdn_cache_status} lorsqu'il est inclus dans un en-tête de requête

Les valeurs géographiques (régions, subdivisions et villes) sont des estimations basées sur l'adresse IP du client. De temps à autre, Google actualise les données qui fournissent ces valeurs afin d'améliorer la précision et de refléter les changements géographiques et politiques. Même si l'en-tête X-Forwarded-For d'origine contient des informations de localisation valides, Google estime les emplacements des clients à l'aide des informations d'adresse IP source contenues dans les paquets reçus par l'équilibreur de charge.

Les en-têtes ajoutés par l'équilibreur de charge écrasent les en-têtes existants portant le même nom. Les noms d'en-têtes ne sont pas sensibles à la casse. Lorsque des noms d'en-têtes sont transmis à un backend HTTP/2, le protocole HTTP/2 les encode en minuscules.

Dans les valeurs d'en-tête, les espaces de début et de fin n'ont aucune importance et ne sont pas transmis au backend. Pour permettre l'utilisation des accolades dans les valeurs d'en-tête, l'équilibreur de charge interprète deux accolades ouvrantes ({{) comme une seule ({), et deux accolades fermantes (}}) comme une seule (}).

En-têtes TLS mutuels personnalisés

Les variables d'en-tête supplémentaires suivantes sont disponibles si le protocole TLS mutuel (mTLS) est configuré sur le TargetHttpsProxy de l'équilibreur de charge.

Variable Description
client_cert_present true si le client a fourni un certificat lors du handshake TLS. Sinon, false.
client_cert_chain_verified true si la chaîne de certificats client est validée par rapport à une configuration TrustStore configurée ou false.
client_cert_error Chaînes prédéfinies représentant les conditions d'erreur. Pour plus d'informations sur les chaînes d'erreur, consultez la section Modes de validation des clients mTLS.
client_cert_sha256_fingerprint Empreinte SHA-256 du certificat client, encodée en base64.
client_cert_serial_number Numéro de série du certificat client. Si le numéro de série est plus de 50 octets, client_cert_error est défini sur client_cert_serial_number_exceeded_size_limit et le numéro de série est défini sur une chaîne vide.
client_cert_spiffe_id

L'ID SPIFFE du champ "Autre nom de l'objet (SAN)". Si la valeur n'est pas valide ou dépasse 2 048 octets, l'ID SPIFFE est défini sur une chaîne vide.

Si l'ID SPIFFE dépasse 2 048 octets, le paramètre client_cert_error est défini sur client_cert_spiffe_id_exceeded_size_limit.

client_cert_uri_sans

Liste des extensions SAN de type URI encodées en base64, séparées par une virgule. Les extensions SAN sont extraites du certificat client. L'ID SPIFFE n'est pas inclus dans le champ client_cert_uri_sans.

Si client_cert_uri_sans dépasse 512 octets, client_cert_error est défini sur client_cert_uri_sans_exceeded_size_limit et la liste d'éléments séparés par des virgules est défini sur une chaîne vide.

client_cert_dnsname_sans

Liste des extensions SAN de type DNSName encodées en base64, séparées par une virgule. Les extensions SAN sont extraites du certificat client.

Si client_cert_dnsname_sans dépasse 512 octets, client_cert_error est défini sur client_cert_dnsname_sans_exceeded_size_limit et la liste d'éléments séparés par des virgules est défini sur une chaîne vide.

client_cert_valid_not_before Horodatage (format de chaîne de date RFC 3339) avant lequel le certificat client n'est pas valide. Par exemple, 2022-07-01T18:05:09+00:00.
client_cert_valid_not_after Horodatage (format de chaîne de date RFC 3339) après lequel le certificat client n'est pas valide. Par exemple, 2022-07-01T18:05:09+00:00.
client_cert_issuer_dn

Champ Issuer (émetteur) complet, encodé au format DER en base64, tiré du certificat.

Si client_cert_issuer_dn dépasse 512 octets, la chaîne client_cert_issuer_dn_exceeded_size_limit est ajoutée à client_cert_error et client_cert_issuer_dn est défini sur une chaîne vide.

client_cert_subject_dn

Champ Subject (objet) complet, encodé au format DER en base64, tiré du certificat.

Si client_cert_subject_dn dépasse 512 octets, la chaîne client_cert_subject_dn_exceeded_size_limit est ajoutée à client_cert_error et client_cert_subject_dn est défini sur une chaîne vide.

client_cert_leaf

Certificat d'entité finale du client pour une connexion mTLS établie où le certificat a été validé. L'encodage du certificat est conforme à la norme RFC 9440. Cela signifie que le certificat DER binaire est encodé en base64 et délimitéde chaque côté par des signes deux-points.

Si client_cert_leaf dépasse 16 Ko non encodé, client_cert_validated_leaf_exceeded_size_limit est défini sur client_cert_error et client_cert_leaf est défini sur une chaîne vide.

client_cert_chain

Liste de certificats séparés par une virgule (dans l'ordre TLS standard) de la chaîne de certificats client pour une connexion mTLS établie où le certificat client a été validé, sans inclure le certificat d'entité finale. L'encodage du certificat est conforme à la norme RFC 9440.

Si la taille combinée de client_cert_leaf et client_cert_chain avant encodage en base64 dépasse 16 Ko, la chaîne client_cert_validated_chain_exceeded_size_limit est ajoutée à client_cert_error et client_cert_chain est défini sur une chaîne vide.

Configurer des en-têtes de requête personnalisés

Console

Pour ajouter des en-têtes de requêtes personnalisés à un service de backend existant, procédez comme suit :

  1. Accédez à la page de résumé de l'équilibrage de charge.
    Accéder à la page Équilibrage de charge
  2. Cliquez sur Backends.
  3. Cliquez sur le nom d'un service de backend.
  4. Cliquez sur Modifier .
  5. Cliquez sur Configurations avancées (affinité de session, délai avant expiration du drainage de connexion, règles de sécurité).
  6. Sous En-têtes de requêtes personnalisés, cliquez sur Ajouter un en-tête.
  7. Renseignez les champs Nom de l'en-tête et Valeur d'en-tête pour l'en-tête de requête personnalisé.
  8. Créez d'autres en-têtes de requêtes personnalisés.
  9. Cliquez sur Enregistrer.

Pour supprimer un en-tête de requête personnalisé d'un service de backend, procédez comme suit :

  1. Accédez à la page de résumé de l'équilibrage de charge.
    Accéder à la page Équilibrage de charge
  2. Cliquez sur Backends.
  3. Cliquez sur le nom d'un service de backend.
  4. Cliquez sur Modifier .
  5. Cliquez sur Configurations avancées (affinité de session, délai avant expiration du drainage de connexion, règles de sécurité).
  6. Cliquez sur le X situé à côté du nom de l'en-tête de requête personnalisé que vous souhaitez supprimer.
  7. Cliquez sur Enregistrer.

gcloud

Pour spécifier des en-têtes de requêtes personnalisés, exécutez la commande gcloud compute backend-services create ou gcloud compute backend-services update avec l'option --custom-request-header.

Pour créer un service de backend avec des en-têtes de requêtes personnalisés, exécutez la commande suivante :

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

Pour ajouter d'autres en-têtes de requêtes, spécifiez pour chacun un nom et une valeur d'en-tête uniques en répétant l'option --custom-request-header.

Pour ajouter des en-têtes personnalisés à un service de backend existant, exécutez la commande suivante :

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

L'étape précédente remplace l'intégralité des en-têtes figurant déjà dans le service de backend par les en-têtes de requêtes que vous spécifiez dans la commande.

Pour supprimer tous les en-têtes d'un service de backend, procédez comme suit :

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

API

Envoyez une requête PATCH à la méthode backendServices.patch :

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

Terraform

Pour obtenir un script Terraform créant un équilibreur de charge avec des en-têtes personnalisés, consultez les exemples Terraform pour les équilibreurs de charge d'application externes globaux.

Configurer des en-têtes de réponse personnalisés

Console

Pour ajouter des en-têtes de requêtes personnalisés à un service de backend existant, procédez comme suit :

  1. Accédez à la page de résumé de l'équilibrage de charge.
    Accéder à la page Équilibrage de charge
  2. Cliquez sur Backends.
  3. Cliquez sur le nom d'un service de backend.
  4. Cliquez sur Modifier .
  5. Cliquez sur Configurations avancées (affinité de session, délai avant expiration du drainage de connexion, règles de sécurité).
  6. Sous En-têtes de réponse personnalisés, cliquez sur Ajouter un en-tête.
  7. Renseignez les champs Nom de l'en-tête et Valeur d'en-tête pour l'en-tête de réponse personnalisé.
  8. Créez d'autres en-têtes de réponse personnalisés.
  9. Cliquez sur Enregistrer.

Pour supprimer un en-tête de réponse personnalisé d'un service de backend, procédez comme suit :

  1. Accédez à la page de résumé de l'équilibrage de charge.
    Accéder à la page Équilibrage de charge
  2. Cliquez sur Backends.
  3. Cliquez sur le nom d'un service de backend.
  4. Cliquez sur Modifier .
  5. Cliquez sur Configurations avancées (affinité de session, délai avant expiration du drainage de connexion, règles de sécurité).
  6. Cliquez sur le signe X situé à côté du nom de l'en-tête de réponse personnalisé que vous souhaitez supprimer.
  7. Cliquez sur Enregistrer.

gcloud

Pour les services de backend, exécutez la commande gcloud compute backend-services create ou gcloud compute backend-services update avec l'option --custom-response-header.

Pour les buckets backend, exécutez la commande gcloud compute backend-buckets create ou gcloud compute backend-buckets update avec l'option --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]'

Exemple avec l'en-tête X-Frame-Options :

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

Exemple avec l'en-tête Strict-Transport-Security :

L'exemple suivant montre comment ajouter un en-tête de réponse personnalisé compatible avec HSTS (HTTP Strict Transport Security) :

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

API

Pour les buckets backend, utilisez l'appel d'API Method: backendBuckets.insert ou Method: backendBuckets.update.

Pour les services de backend, utilisez l'appel d'API Method: backendServices.insert ou Method: backendServices.update.

Utilisez l'un des appels d'API suivants :

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

Ajoutez l'extrait suivant au corps de la requête JSON :

"customResponseHeaders":HEADER_NAME:[HEADER_VALUE]

Terraform

Pour obtenir un script Terraform créant un équilibreur de charge avec des en-têtes personnalisés, consultez les exemples Terraform pour les équilibreurs de charge d'application externes globaux.

Définir des en-têtes de réponse pour Cloud Storage

Si vous devez configurer des en-têtes HTTP dans les réponses issues de Cloud Storage, telles que la règle CORS X-Frame-Options ou les en-têtes X-XSS-Protection, Google Cloud offre la possibilité d'utiliser des en-têtes personnalisés pour Cloud CDN avec Cloud Storage. Pour ce faire, configurez les en-têtes personnalisés au niveau du bucket backend de l'équilibreur de charge, comme décrit sur cette page.

Les en-têtes de réponse personnalisés configurés au niveau du bucket backend ne sont ajoutés aux réponses que si la requête du client est envoyée à l'adresse IP de l'équilibreur de charge. Les en-têtes personnalisés ne sont pas ajoutés aux réponses si la requête du client a été envoyée directement à l'API Cloud Storage.

Utiliser des en-têtes personnalisés avec Google Cloud Armor

Lorsque vous configurez une stratégie de sécurité Google Cloud Armor, vous pouvez configurer Google Cloud Armor pour insérer un en-tête et une valeur personnalisés. Si votre stratégie de sécurité Google Cloud Armor est configurée pour insérer le même nom d'en-tête personnalisé que les en-têtes personnalisés de votre équilibreur de charge d'application externe global ou de votre équilibreur de charge d'application classique, alors la valeur d'en-tête spécifiée dans votre stratégie de sécurité Google Cloud Armor est écrasée par la valeur renseignée par l'équilibreur de charge. Si vous ne souhaitez pas que la stratégie Google Cloud Armor soit écrasée, assurez-vous de ne pas utiliser le même nom.

Limites

Les limites suivantes s'appliquent aux en-têtes personnalisés utilisés avec les équilibreurs de charge globaux :

  • La taille totale de l'ensemble des en-têtes de requêtes personnalisés (nom et valeur combinés, avant expansion des variables) pour chaque service de backend ne doit pas dépasser 8 Ko ou 16 en-têtes de requête.
  • La taille totale de l'ensemble des en-têtes de réponse personnalisés (nom et valeur combinés, avant expansion des variables) pour chaque service de backend ne doit pas dépasser 8 Ko ou 16 en-têtes de réponse.

Étape suivante