Résumé
ForwardedetX-Forwarded-Fortransmettent des déclarations de trajet, non une identité client authentifiée. L’observation de départ reste le pair de la connexion ; les adresses plus anciennes n’acquièrent de valeur qu’à travers une délégation explicite.- Un contrôle sérieux conserve les lignes reçues et leur ordre, la version du parseur, la politique de confiance, la première rupture de chaîne et la décision qui a consommé le résultat.
Une chaîne bien formée peut être fausse
Dire qu’un en-tête « peut être usurpé » n’explique pas assez le défaut. Un en-tête est une entrée fournie par l’émetteur. Le saut dangereux survient lorsque l’application transforme cette entrée en fait sur la connexion.
L’origine connaissait une chose sans l’avoir lue dans HTTP : l’adresse du socket qui venait de la joindre. Ce pair pouvait être un répartiteur, donc pas l’utilisateur final. Il constituait néanmoins le premier maillon observé localement. S’il n’appartenait pas aux mandataires autorisés à certifier le trajet, l’analyse devait s’arrêter là.
Prendre malgré tout la valeur la plus à gauche revenait à laisser un interlocuteur choisir lui-même l’identité réseau dont il voulait bénéficier. La correction n’est donc pas un meilleur découpage par virgules. C’est une règle d’admission des témoins.
La portée exacte de RFC 7239
RFC 7239 définit Forwarded comme un champ facultatif qui expose des informations modifiées ou perdues lors du passage par un mandataire. Dans chaque élément, for, by, host et proto décrivent des dimensions distinctes. Leur rapprochement ne crée ni compte, ni personne, ni droit.
Le texte normatif refuse toute présomption générale d’exactitude : chaque nœud du trajet, client compris, peut modifier le champ par erreur ou malveillance. Vérifier puis autoriser un mandataire donne du poids à ce qu’il a lui-même observé. Cela ne valide pas le préfixe arbitraire qu’il a reçu. Une liaison non protégée entre ce mandataire et l’origine peut, de surcroît, permettre une nouvelle modification.
La syntaxe accepte aussi unknown et des identifiants masqués. Ces valeurs expriment une limite de connaissance ou de divulgation ; elles ne doivent pas devenir une adresse numérique par conversion opportuniste. Le journal doit distinguer absence, masquage, inconnu et erreur de syntaxe.
XFF n’est pas le champ normalisé
X-Forwarded-For précède la normalisation de RFC 7239 et reste un usage de fait. Une ressemblance visuelle — une liste séparée par des virgules — ne rend pas les contrats interchangeables.
AWS ALB offre un exemple utile. Il peut ajouter, préserver ou supprimer XFF. En mode append, il conserve le contenu entrant puis ajoute à droite l’adresse qu’il a observée. Sa propre observation n’authentifie donc pas les valeurs que le demandeur avait placées à gauche.
HAProxy documente séparément l’ajout de XFF et la génération de Forwarded. Le service aval doit connaître le champ exact, la position ajoutée, la politique de nettoyage et la règle de lecture. « Première adresse » ou « dernière adresse » n’a aucun sens universel hors de ce contrat.
Partir de la droite vérifiable
NGINX utilise set_real_ip_from pour désigner les émetteurs réputés fournir une valeur de remplacement correcte. Avec real_ip_recursive on, il retient le dernier élément non fiable après avoir remonté la partie autorisée ; $realip_remote_addr conserve le pair initial.
Apache mod_remoteip examine la liste de droite à gauche et rappelle qu’un utilisateur peut trivialement usurper une adresse si le mécanisme est activé sans intermédiaire fiable. Envoy propose un décompte de sauts depuis la droite, dont le résultat dépend de use_remote_address, ainsi qu’une méthode fondée sur des CIDR fiables.
Ces variantes ne sont pas contradictoires : elles exposent des topologies différentes. Le risque apparaît lorsqu’un nombre de sauts copié d’un schéma reste en place après l’ajout d’un CDN, la suppression d’un relais ou l’ouverture d’une autre route. La topologie est une donnée de sécurité.
Les lignes répétées révèlent les désaccords
RFC 9110 autorise la combinaison ordonnée de lignes répétées lorsqu’un champ possède une syntaxe de liste. Un mandataire peut livrer une chaîne unique, tandis qu’un framework expose un tableau et qu’un journal n’en garde qu’une ligne. Envoyer délibérément des doublons permet de vérifier si le filtre, l’application et la preuve d’audit parlent du même ordre.
IPv6 met en échec les parseurs naïfs : l’adresse contient déjà des deux-points, un port ajoute une autre frontière, et RFC 7239 fait intervenir guillemets et crochets. Les essais doivent couvrir IPv6 cité avec port, IPv4 avec port, espaces, unknown, identifiants masqués et séparateurs invalides.
La normalisation répond à « quelle valeur avons-nous lue ? ». La confiance répond à « pourquoi cet émetteur avait-il le droit de la fournir ? ». Il faut conserver les deux réponses.
Ni host ni proto ne sont des laissez-passer
Après terminaison TLS, les applications restaurent parfois le schéma et l’hôte antérieurs pour composer une redirection, un cookie Secure ou une URL absolue. Un proto=https fourni par le client ne prouve pourtant pas que le bord fiable a vu TLS. Un host relayé n’authentifie pas davantage l’origine.
Chaque paramètre mérite son propre consommateur et sa propre source autorisée. Une architecture peut accepter l’adresse observée par le bord, mais imposer l’hôte depuis une table de routage. Faire confiance à tout le champ parce qu’un seul élément est utile dilate le pouvoir sans le dire.
Le protocole PROXY appartient à un autre registre
Le protocole PROXY transmet source et destination avant HTTP. Sa position plus basse ne l’authentifie pas. Le récepteur doit l’attendre sur une écoute réservée ou strictement filtrée et n’accepter le préambule que d’émetteurs autorisés. Sinon, n’importe quel client peut déclarer une fausse source avant même le premier octet HTTP.
Le pair réel, l’état attendu ou accepté du préambule, l’adresse déclarée, puis les champs HTTP doivent rester séparés. Les rabattre dans une seule variable client_ip efface la chaîne de garde.
Les tests négatifs font foi
Depuis l’extérieur, tenter d’abord l’accès direct à l’origine. Si le modèle l’interdit, la connexion doit échouer avant HTTP. Envoyer ensuite une adresse autorisée dans XFF depuis un pair non fiable et vérifier qu’elle n’est jamais adoptée.
Par le bord légitime, préfixer une fausse adresse, insérer un relais non autorisé, retirer un saut attendu puis en ajouter un. Tester les doublons et les formes IPv6 difficiles. Comparer l’adresse retenue par le bord, l’origine, le framework, le limiteur de débit, l’autorisation et le journal. Enfin, envoyer un préambule PROXY depuis une source interdite.
Une configuration relue prouve une intention. Ce corpus de divergences prouve le comportement exécuté.
Briefing des membres
Contexte approfondi du profil
Connectez-vous avec le bon niveau d'adhésion pour débloquer le briefing complet et les notes de source.
Réservé à Strategic Circle
Strategic Circle
Ouvert à tous les lecteurs. Débloquez les briefings de profil après adhésion et connexion.
Rejoindre Strategic CircleRéservé aux membres de Leadership Alliance
Leadership Alliance
Réservé aux propriétaires et dirigeants qualifiés d'actifs IP ; connectez-vous pour débloquer les briefings Alliance.
Rejoindre Leadership Alliance