DNAT dans un conteneur VPN : transfert, pas INPUT
Après DNAT, une requête vers l'adresse du tunnel devient du trafic transféré. Cadrez la règle de transfert, lisez la chaîne Docker et choisissez une voie de retour à dessein.
La requête arrive adressée à l'IP du tunnel et quitte le même conteneur adressée à un service voisin. Entre ces deux instants, DNAT a réécrit la destination, et le paquet n'était plus une entrée pour le conteneur VPN. Il est désormais du trafic transféré, jugé par une autre règle. Ce basculement explique pourquoi une règle de pare-feu qui semble correcte pour l'adresse du tunnel n'a aucun effet sur la connexion traduite.
Suivez le paquet après la traduction
Prenez un pool de clients 10.90.0.0/24 et une adresse de tunnel 10.90.0.1. Deux conteneurs sont sur un même pont : 192.0.2.2 exécute le VPN et 192.0.2.3 exécute l'application. Un client se connecte à 10.90.0.1:8080, et la règle DNAT de l'espace de noms du conteneur VPN la réécrit vers l'adresse et le port réels de l'application. Une route envoie ensuite le paquet sur le pont. Ces adresses sont illustratives, pas une recette de déploiement.
Le port sur lequel l'application écoute réellement peut différer de tout port publié sur l'hôte. Lisez l'écouteur à l'intérieur du conteneur au lieu de supposer que les deux nombres coïncident.
L'autorisation relève du chemin de transfert
Le conteneur VPN a besoin du transfert IP et d'une décision de transfert limitée au pool de clients, à l'adresse de l'application et au port prévu. Les réponses établies ont besoin de leur propre autorisation. Une règle qui correspond à l'adresse d'origine du tunnel ne correspondra pas après DNAT, car la destination a déjà changé. Une autorisation INPUT est le mauvais point d'accroche pour du trafic qui n'est plus adressé à cet hôte.
Gardez le périmètre étroit : une plage source, une destination, un service. Une règle de transfert permissive est plus facile à écrire et bien plus difficile à défendre ensuite.
docker exec vpn-container ip route get 192.0.2.3
docker exec vpn-container iptables -t nat -S
docker exec vpn-container iptables -S FORWARD
Les chaînes de Docker ne sont pas celles de votre conteneur
Les règles dans l'espace de noms du conteneur ne sont pas celles de l'hôte Docker. Quand le trafic passe de l'interface du tunnel au pont, le pare-feu du pont de l'hôte peut prendre une autre décision. Avec le backend iptables de Docker, les chaînes de transfert documentées et les points de correspondance après DNAT sont là où cette décision apparaît.
La référence du pare-feu Docker décrit ces chaînes et la correspondance après DNAT. Ne corrigez pas une acceptation manquante en désactivant la gestion du pare-feu de Docker ou en rendant chaque chaîne permissive, car cela supprime la frontière que vous cherchez à utiliser.
Faites de la voie de retour un choix délibéré
Si l'adresse source est conservée, l'application voit 10.90.0.x et doit renvoyer les réponses via le conteneur VPN. Sinon, sa passerelle Docker ordinaire les enverra à l'hôte, qui ne possède pas le tunnel. L'alternative est une traduction de source étroitement cadrée au conteneur VPN, qui simplifie la réponse mais cache le client à l'application. Choisissez à dessein et notez laquelle vous avez choisie.
Testez une nouvelle connexion autorisée depuis un client ordinaire, puis confirmez que les ports sans rapport restent fermés. Quand un paquet disparaît, inspectez l'espace de noms VPN, celui de l'application et le journal propre à l'application. Un ping vers la passerelle du pont n'est pas un test d'acceptation du service.
Gardez les règles dans la configuration de démarrage prise en charge du conteneur, car les modifications interactives disparaissent à sa recréation. La publication d'un port sur l'hôte est une autre voie d'exposition et n'est pas nécessaire simplement parce que le service est joignable par le tunnel.