Conserver l’adresse du client VPN jusqu’à l’application fait que chaque ligne de journal et chaque entrée de la liste d’autorisation signifient la même chose. La réécrire à la lisière du cloud rend la table de routage plus simple et les journaux moins utiles. Aucun des deux choix n’est faux en soi, et l’argument qui tranche porte rarement sur la performance. Trois conditions tranchent : si l’application doit savoir quel humain s’est connecté, si la fabrique cloud acceptera la source que vous comptez envoyer, et qui acceptera d’assumer la route de retour ensuite.

Trois conditions tranchent

Partez de l’exigence de l’application, pas du schéma réseau. Si l’autorisation ou l’audit dépendent de l’adresse individuelle du client, alors la conserver est une exigence fonctionnelle et la traduire est une régression. Si l’application a seulement besoin de savoir que le trafic est arrivé par le chemin d’accès distant, une adresse traduite suffit et coûte bien moins cher à exploiter.

La deuxième condition est mécanique. Un réseau virtuel ne fait pas confiance automatiquement à un paquet qui revendique une adresse qui n’a pas été attribuée à l’interface émettrice. La plupart des fabriques cloud l’imposent, de manières et sous des noms différents, et une conception qui l’ignore paraîtra correcte sur un schéma et disparaîtra silencieusement en production.

La troisième est organisationnelle. Conserver les sources signifie que la table de routage du sous-réseau applicatif doit pointer vers la passerelle pour le préfixe client, et chaque équipe qui ajoute un sous-réseau ensuite doit maintenir cette route cohérente. C’est un coût faible une fois, et récurrent sur des dizaines de comptes. Décidez qui le paie avant de promettre le comportement.

Une route n’est pas une autorisation d’usurper

Ajouter une route de retour indique à votre sous-réseau où doivent aller les réponses. Cela n’indique pas à la fabrique que l’instance qui transfère ces paquets a le droit de les émettre avec une source étrangère. Sur AWS, le contrôle pertinent est la vérification source et destination, et il est visible par instance :

aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
  --query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
  --no-source-dest-check

Désactivez-la uniquement pour l’instance dont le travail documenté est le transfert, et pour rien d’autre. Chaque VM applicative qui garde le contrôle activé est une machine de moins qui peut servir à émettre du trafic avec une source empruntée. Si votre plateforme n’est pas AWS, cherchez le réglage équivalent d’anti-usurpation ou d’adresses autorisées au lieu de supposer que le comportement se transpose.

Une capture de paquets rapide tranche la question plus vite que la lecture de la console. Si les réponses sortent et que le client ne les voit jamais, c’est la fabrique qui écarte la source usurpée, et non l’application qui échoue.

Ce que la traduction achète, et ce qu’elle coûte

Réécrire la source à la passerelle supprime le problème du chemin de retour. L’application voit une adresse qu’elle sait déjà joindre, et le préfixe client n’a jamais à apparaître dans une table de routage cloud. Sous Linux, la règle tient en une ligne, et il vaut la peine d’écrire la version la plus étroite possible :

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10

Notez ce que l’application enregistre désormais : 10.40.3.10 pour chaque utilisateur, à chaque connexion, pour toujours. Toute liste d’adresses autorisées bâtie sur cette valeur accorde maintenant l’accès à toute la population d’accès distant, et toute revue d’incident doit revenir à la passerelle pour répondre à la question de savoir qui c’était.

La solution n’est pas d’abandonner la traduction, elle est de cesser de faire comme si l’adresse était une identité. Portez l’identité du client dans un champ authentifié, journalisez-la à la passerelle avec le tuple traduit, et laissez l’application faire la jointure dessus. Sans la clé de jointure, la traduction transforme un problème réseau en problème forensique permanent.

Le relais est une autre interface

Un proxy inverse devant l’application contourne entièrement la question du chemin routé. Le proxy ouvre sa propre connexion backend, si bien que le préfixe client n’a jamais besoin d’être routable dans le réseau virtuel, et l’application peut recevoir l’identité dans un en-tête que le proxy définit.

Cet en-tête n’est digne de confiance que lorsque le backend l’accepte du proxy et de rien d’autre. En termes nginx, cela signifie nommer explicitement le pair de confiance au lieu de croire tout ce qui arrive :

set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Tout client capable d’atteindre le backend directement peut falsifier le même en-tête, donc le backend doit être injoignable sauf via le proxy. C’est un fait de pare-feu, pas une opinion de configuration, et c’est l’hypothèse que les gens sautent quand ils copient l’extrait.

Le relais change aussi ce que vous achetez. Vous obtenez une identité au niveau applicatif et un endroit naturel pour la journaliser ; vous abandonnez la généralité, car chaque nouveau protocole a besoin de son propre support proxy. Pour les services HTTP, cet échange est généralement bon, et pour tout ce qui n’est pas HTTP, il n’est généralement pas disponible du tout.

Écrivez ce que chaque frontière voit

Quoi que vous choisissiez, la revue de conception devrait se terminer par un tableau qui nomme l’adresse source et l’identité démontrable à chaque saut. Sans lui, le premier incident produit trois équipes qui décrivent chacune un client différent.

BoundarySource the next hop seesWhat is actually proven
Client to gateway172.20.8.14A certificate or credential was presented
Gateway to app subnet, preserved172.20.8.14The same session, if the return route exists
Gateway to app subnet, translated10.40.3.10Only that traffic came through the gateway
Proxy to backend10.40.3.10 plus a headerThe proxy asserted an identity it authenticated

Puis choisissez. Conservez quand l’autorisation de l’application dépend réellement de l’adresse du client et que vous pouvez assumer la route. Traduisez quand ce n’est pas le cas et que vous pouvez porter l’identité hors bande, et utilisez les recommandations AWS pour les instances de transfert pour les réglages de transfert propres à la plateforme. Recourez à un relais quand le service parle HTTP et que vous voulez que l’identité cesse d’être une adresse.

Articles similaires