Pair de socket ou en-tête transmis : à quelle adresse se fier ?
Le pair de socket et un en-tête transmis sont des preuves différentes. Comparez ce que chacun démontre, et ne faites confiance à l’en-tête qu’à travers une chaîne de proxy que vous contrôlez.
Une requête qui arrive dans votre application porte deux types de preuves d’adresse : le pair qui a ouvert la connexion réseau, et un champ HTTP qui revendique l’adresse d’un client antérieur. Ils répondent à des questions différentes. Le pair de socket est observé, tandis que l’en-tête est affirmé par celui qui l’a écrit, et aucun ne devrait remplacer silencieusement l’autre dans un journal ou une règle d’accès. La comparaison ci-dessous les garde séparés, puis montre le seul agencement dans lequel l’en-tête devient utilisable.
Décrivez le chemin avant de comparer quoi que ce soit :
Client -> approved reverse proxy -> application originDans cet agencement, le pair de socket de l’origine est normalement le proxy, et un en-tête de transmission peut porter l’affirmation du proxy sur le client. Sa valeur vient de la relation maîtrisée avec ce proxy, non du nom de l’en-tête.
Deux types de preuves d’adresse
Le pair de socket est un fait concernant une connexion TCP : quelque chose a terminé une poignée de main depuis cette adresse. Ce n’est pas nécessairement la personne, l’appareil ou le compte qui vous importe, car un VPN ou une sortie Tor peuvent légitimement être la source qu’un service observe. Il reste la seule adresse que l’hôte lui-même a vérifiée, et c’est là toute sa valeur.
Un champ de transmission est une métadonnée sur une chaîne. X-Forwarded-For, X-Real-IP et le champ normalisé Forwarded peuvent être écrits par tout client qui atteint un point de terminaison qui les renvoie, si bien que leur fiabilité dépend entièrement de qui a été autorisé à les définir.
Gardez les deux dans le contexte de la requête sous des noms distincts. Une application qui écrase le pair avec l’en-tête perd la capacité de reconstituer plus tard une erreur de confiance, et c’est précisément le moment où vous en avez besoin.
Un en-tête ne réachemine jamais la connexion
Écrire une adresse dans un champ de transmission ne change pas la source de la connexion TCP qui arrive au serveur, et ne modifie le routage nulle part sur le chemin. Le routage VPN ordinaire ou le NAT source achemine le trafic sans aucun en-tête HTTP. De même, une passerelle de transit ne réécrit pas un échange HTTPS correctement protégé sans changer l’agencement du point de terminaison TLS.
L’erreur inverse est tout aussi courante : HTTPS ne rend pas véridique un en-tête de transmission fourni par le client. Il protège le transport d’une affirmation fausse exactement aussi bien que celui d’une vraie.
Si un collègue propose de modifier un en-tête pour corriger un problème de routage, le diagnostic a déjà mal tourné. Corrigez le chemin, ou corrigez la configuration du proxy qui écrit l’en-tête.
Nommez le proxy autorisé à affirmer
Deux règles rendent un champ de transmission utilisable, et toutes deux relèvent de la configuration et non du code. La périphérie normalise ou supprime tout ce qui vient de l’extérieur, selon son propre comportement documenté pour ces champs. L’origine prend ensuite une adresse de remplacement dans le chemin de proxy que vous avez nommé, et nulle part ailleurs. Cette seconde règle ne tient que tant que les clients ne peuvent pas atteindre l’origine autrement, car une origine qui répond à la fois aux requêtes directes et aux requêtes via proxy ne sait pas laquelle elle sert.
Le module d’IP réelle de NGINX montre la séparation clairement. set_real_ip_from nomme les expéditeurs dont l’affirmation compte, et real_ip_header dit quel champ la porte ; le premier exerce la confiance, le second indique seulement où regarder.
set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on - walk the list back past every trusted address
Une directive de sélection d’en-tête, à elle seule, n’établit toujours rien sur qui a envoyé la valeur.
La sécurité du transport doit courir sur tout le trajet entre les composants auxquels vous faites confiance. Une périphérie qui normalise correctement perd cette valeur au moment où un saut non protégé en aval laisse quelqu’un d’autre modifier l’affirmation pendant son trajet.
Gérez délibérément les chaînes à plusieurs sauts
Plusieurs proxys exigent un modèle de chaîne explicite. Ne prenez pas la valeur la plus à gauche ou la plus à droite séparée par des virgules parce qu’un article de blog l’a fait ; découvrez lequel de vos proxys ajoute, lequel remplace et lequel conserve le champ entrant. NGINX, par exemple, peut parcourir la liste à rebours par rapport à son ensemble de confiance et s’arrêter à la première adresse qu’il ne possède pas, et c’est la règle de ce produit, non une loi que suivrait chaque cadre de travail. Lisez la documentation de votre propre proxy avec les deux mêmes questions : quelle valeur sélectionne-t-il, et en quels expéditeurs croit-il ?
Écrivez la chaîne : ordre des sauts, quel saut définit le champ et quel saut supprime les copies entrantes. Gardez ensuite cette note à côté de la configuration du proxy, pas seulement dans le ticket. Puis testez-la en envoyant une requête avec un en-tête falsifié via le processus de validation approuvé et en confirmant que l’origine l’ignore.
Lorsque vous ajoutez un saut, révisez ce document. Un nouvel équilibreur de charge inséré devant le proxy de confiance peut changer quelle adresse gagne sans que personne ne modifie l’application.
Gardez les deux observations dans le journal
Là où le diagnostic est autorisé, journalisez le pair de la connexion et l’adresse client normalisée comme deux champs distincts, et n’ajoutez que les métadonnées de transmission dont l’objectif a réellement besoin. Prouvez ensuite le déploiement avec deux requêtes : une via le proxy qui devrait enregistrer les deux valeurs de façon sensée, et une tentative directe vers l’origine qui doit être refusée.
Rappelez-vous ce que le couple signifie. L’en-tête ajoute un contexte fourni par un composant que vous avez choisi de croire ; le pair reste la seule adresse que votre hôte a réellement vue. Aucun des deux n’est une preuve d’identité individuelle, et une conception qui traite l’un ou l’autre comme une preuve se trompera sur quelqu’un.