Pages : 1
#1 Le 31/12/2018, à 00:19
- blueduck
[Résolu] Docker modifie iptables et bloque OpenVPN
Bonsoir,
Je rencontre une difficulté avec Docker qui, lorsqu'il démarre, modifie les règles d'iptables.
Or je me suis aperçu que ces modifications "parasitent" la communication entre mon LAN et celui du bureau, qui sont reliés par OpenVPN.
Si je désactive Docker au démarrage, les deux LAN communiquent parfaitement, et les chaînes iptables sont les suivantes :
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere 192.168.10.40 tcp dpt:58051
ACCEPT tcp -- anywhere 192.168.10.40 tcp dpt:58050
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Puis j'active Docker et je le démarre ; je liste à nouveau les chaînes d'iptables, ce qui donne alors ce résultat :
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere 192.168.10.40 tcp dpt:58051
ACCEPT tcp -- anywhere 192.168.10.40 tcp dpt:58050
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Avec ces modifications, seul le serveur OpenVPN peut encore communiquer avec le LAN du bureau : aucun des postes de la maison n'y arrive plus, et inversement les postes du bureau ne "voient" plus ceux de la maison (en-dehors du serveur OpenVPN lui-même).
Comme je suis très ignorant du fonctionnement d'iptables, je n'arrive pas à identifier laquelle des règles mises en place par Docker bloque le VPN. Je comprends vaguement que la politique par défaut de la chaîne FORWARD passe de ACCEPT à DROP, mais je ne sais pas dire si c'est de là que vient le problème, ni comment et dans quel ordre les chaînes interagissent entre elles.
Si j'y arrivais, je me dis que peut-être il serait possible d'ajouter une ou deux règles pour rétablir les communications à travers le VPN, sans pour autant gêner le fonctionnement de Docker.
Quelqu'un peut-il m'expliquer ce qui se passe et comment y remédier ?
Cordialement,
Blue Duck
Dernière modification par blueduck (Le 25/03/2020, à 18:29)
Poste de travail : Kubuntu « Impish Indri » 22.10 64 bits - AMD Ryzen 3900X @ 3.8 GHz - Palit GeForce RTX 2070 Super
Serveur domestique : Ubuntu Server « Jammy Jellyfish » 22.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz
Hors ligne
#2 Le 13/01/2019, à 00:29
- Junkaria
Re : [Résolu] Docker modifie iptables et bloque OpenVPN
Salut,
Je te conseille vivement de suivre un petit cours sur IPTables, franchement ce n'est pas si compliqué qu'il n'y parait, et ça te permettra de comprendre ce que tu fais plutôt que de suivre des conseils qui peuvent t'induire en erreur et qui peuvent foutre un peu la merde, et tu finiras par tout virer parce que tu en aura marre d’enchaîner les galères
Pour commencer, tes règles pour le VPN ne sont pas complètes, ce qui brouille déjà le trajet de tes packets.
Comment les modifies-tu ? Script bash ?
Ubuntu 08.04-11.04 | Linux Mint | ArchLinux
Hors ligne
#3 Le 24/01/2019, à 21:21
- blueduck
Re : [Résolu] Docker modifie iptables et bloque OpenVPN
Bonsoir, et merci pour ta réponse.
J'ai en effet pris le temps de me documenter un peu plus sur iptables (essentiellement là : http://olivieraj.free.fr/fr/linux/infor … 03-01.html) et, si j'ai bien compris, cela confirme l'origine de ma difficulté.
Au point de départ (c'est-à-dire avant d'installer Docker), je n'utilise pas iptables : les chaînes par défaut sont toutes vides et laissent tout passer (policy ACCEPT), en particulier FORWARD qui est la seule à m'intéresser en ce qui concerne mon problème. Comme le serveur est derrière un routeur, je n'en fais pas une histoire, et cela permet à OpenVPN de fonctionner.
Quand Docker démarre, comme il est (un peu) moins permissif, il isole ses conteneurs (qui communiquent par son interface virtuelle docker0) en les faisant passer à travers des chaînes utilisateurs qu'il crée, et il modifie le réglage par défaut de la chaîne FORWARD à DROP, sans se poser la question de savoir si d'autres services n'auraient pas besoin de FORWARDer des paquets (je trouve d'ailleurs ça un peu moyen comme fonctionnement, mais bon).
Pour régler (provisoirement) mon problème, j'ai utilisé deux scripts que j'avais et qui étaient déjà appelés par OpenVPN lors de son lancement et de son arrêt (leur rôle premier est d'ajouter ou de supprimer l'interface virtuelle d'OpenVPN à mon bridge ethernet). Lors du lancement d'OpenVPN, j'ai ajouté :
iptables -P FORWARD ACCEPT
et lors de son arrêt (plus par acquit de conscience, compte-tenu qu'OpenVPN est lancé 99,99 % du temps...) :
iptables -P FORWARD DROP
Le résultat dans iptables donne ceci :
$ sudo iptables -L -n -v
Chain INPUT (policy ACCEPT 7570K packets, 30G bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58051
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58050
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58051
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58050
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58051
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.40 tcp dpt:58050
Chain FORWARD (policy ACCEPT 514K packets, 156M bytes)
pkts bytes target prot opt in out source destination
519K 160M DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
519K 160M DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
2628 3895K ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
1793 113K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 7359K packets, 3303M bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:443
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:9980
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
1793 113K DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
519K 160M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
1793 113K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
519K 160M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Cela fonctionne, mais il subsiste deux problèmes.
Premièrement, c'est moche : quitte à mettre des règles dans iptables, autant en créer une spécifique pour OpenVPN et laisser le réglage par défaut de la chaîne FORWARD à DROP.
Deuxièmement, et même si je crée une telle règle dans un script, il ne faut pas qu'il soit appelé par OpenVPN. D'abord, parce que pendant la phase de boot, j'ai l'impression que Docker est lancé après OpenVPN : donc, les règles qui seraient mises en place par un script appelé par OpenVPN seraient ensuite écrasées par le démarrage de Docker (c'est d’ailleurs déjà le cas : il faut que je relance OpenVPN après le boot pour qu'il rebascule FORWARD à ACCEPT) ; ensuite, parce que même si j'arrivais à configurer systemd pour qu'OpenVPN se lance après Docker au moment du boot (et franchement, gérer l'ordre des lancements des services par systemd n'a pas l'air d'être une mince affaire...), il est quand même assez fréquent que je doive faire un restart sur Docker pour une raison ou pour une autre, et dans ce cas, à nouveau, Docker écrase les réglages iptables et remet FORWARD sur DROP.
Donc, la solution que je vois, c'est que ce script, qui ajouterait une règle à la chaîne FORWARD pour laisser transiter les paquets de mon bridge ethernet, soit appelé par le lancement de Docker. Il semble d'ailleurs que la chaîne utilisateur DOCKER-USER soit faite pour cela, mais je n'ai pas encore tout bien lu la documentation.
Maintenant, s'il y a une autre solution plus simple, plus sure, ou plus élégante, je suis preneur...
Blue Duck
Dernière modification par blueduck (Le 25/01/2019, à 08:57)
Poste de travail : Kubuntu « Impish Indri » 22.10 64 bits - AMD Ryzen 3900X @ 3.8 GHz - Palit GeForce RTX 2070 Super
Serveur domestique : Ubuntu Server « Jammy Jellyfish » 22.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz
Hors ligne
#4 Le 25/03/2020, à 18:16
- blueduck
Re : [Résolu] Docker modifie iptables et bloque OpenVPN
Bonjour,
Auto-réponse, pour la satisfaction de passer le sujet en résolu et pour le cas (bien improbable si j'en crois le peu de matière que j'ai trouvé lors de mes recherches) où quelqu'un rencontrerait ce problème.
Je résume la problématique, qui est en fait liée à l'utilisation d'un bridge ethernet.
Pour isoler ses containers, Docker crée directement ses propres règles dans iptables (https://docs.docker.com/network/iptables/). Si l'on n'utilise pas iptables, cela ne pose pas de problème particulier, pas même avec OpenVPN en situation classique client-serveur.
En revanche, si iptables est déjà configuré avec des règles personnalisées, celles ajoutées par Docker peuvent perturber le fonctionnement. Je ne m'étends pas là-dessus, d'abord parce que ce n'est pas mon cas (je n'ai pas de règle personnalisée dans iptables), et ensuite par incompétence (ceux qui ont des règles personnalisées dans iptables maîtrisent cela bien mieux que moi, et ont probablement déjà rencontré et réglé ce problème avec Docker).
Mon problème vient que je n'utilise pas OpenVPN en situation client-serveur, mais en configuration site-à-site : pour que les postes de la maison, qui sont derrière le serveur VPN, communiquent avec ceux qui sont derrière le client VPN (et inversement, de manière finalement à ce que tous participent au même grand LAN), j'utilise, sur le serveur et sur le client, un pont ethernet (https://openvpn.net/community-resources … -bridging/). En gros, le pont ethernet est une interface virtuelle qui rassemble l'interface physique (réellement branchée au LAN) et l'interface VPN (interface elle-même virtuelle créé par OpenVPN lors de la connexion) : les deux interfaces regroupées en pont perdent leurs paramètres IP individuels (adresses, masques, etc.) et c'est le pont qui dispose d'une unique adresse IP, recevant et relayant ainsi à la fois les communications qui viennent du LAN et celles qui viennent du VPN.
Je souligne relayant, parce que c'est de là que venait mon problème. Le pont fonctionnant au niveau 2 du modèle OSI, je n'imaginais pas que son fonctionnement pût être perturbé par iptables (qui est au niveau 3). Sauf que voilà : https://serverfault.com/questions/16236 … 384#162384 ! À l'intérieur du pont, il faut bien que les communications du niveau 3 passent du LAN au VPN, et donc les règles d'iptables leur sont appliquées.
Or on a vu que Docker passe sur DROP la politique par défaut de la chaîne FORWARD, qui traite les paquets passant d'une interface à une autre : donc les paquets, même à l'intérieur du pont, n'ont plus le droit de passer de l'interface LAN à l'interface VPN, et vice-versa. Ça se voit très bien en enregistrant dans le journal système les paquets bloqués dans la chaîne FORWARD (https://tecadmin.net/enable-logging-in- … -on-linux/) :
IN=br0 OUT=br0 PHYSIN=enp6s0 PHYSOUT=tap0 MAC=XX:XX:XX:XX:XX:XX SRC=192.168.10.17 DST=224.0.0.252 LEN=52 TOS=0x00 PREC=0x00 TTL=1 ID=23331 PROTO=UDP SPT=59543 DPT=5355 LEN=32
Le pont br0 est à la fois l'interface d'entrée et l'interface de sortie mais, à l'intérieur, on voit bien que le paquet vient de l'interface LAN et va vers l'interface VPN ; en comme je n'ai pas de règle dans la chaîne FORWARD pour permettre cela, la politique DROP mise en place par Docker rejette le paquet. J'ai donc dû créer une règle dans la chaîne FORWARD pour permettre, à l'intérieur du pont, toutes les communications entre les interfaces regroupées.
Pour être certain que cette règle soit traitée avant celles de Docker, il faut l'ajouter dans la chaîne utilisateur DOCKER-USER, qui n'est pas effacée quand Docker redémarre (https://blog.donnex.net/docker-and-iptables-filtering/). Donc, dans le script qui crée le pont (rassemble les interfaces) lors du démarrage d'OpenVPN, j'ai ajouté :
iptables -I DOCKER-USER 1 -i br0 -o br0 -j ACCEPT
Ce qui donne, après démarrage d'OpenVPN :
$ sudo iptables -L -v -n
Chain INPUT (policy ACCEPT 252K packets, 208M bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.61 tcp dpt:58051
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.10.61 tcp dpt:58050
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1342K 1151M DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
893 189K DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 261K packets, 162M bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:9980
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:443
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
0 0 DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
893 189K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
362K 308M ACCEPT all -- br0 br0 0.0.0.0/0 0.0.0.0/0
893 189K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Attention à l'option -I (i majuscule) dans la commande iptables : si on utilise -A, la règle est ajoutée à la fin de la chaîne DOCKER-USER, après la règle RETURN, et n'est donc jamais traitée.
Toujours par acquit de conscience, et aussi pour éviter que la règle soit insérée une deuxième fois en cas de redémarrage d'OpenVPN, j'ai ajouté dans le script qui supprime le pont à l'arrêt du service :
iptables -D DOCKER-USER 1
Mais si j'ai bien compris, ça fonctionne parce que cela supprime la ligne 1 de la chaîne DOCKER-USER : je ne sais pas traiter le cas où, entre-temps, on aurait inséré une nouvelle règle en ligne 1...
Blue Duck
Dernière modification par blueduck (Le 25/03/2020, à 18:26)
Poste de travail : Kubuntu « Impish Indri » 22.10 64 bits - AMD Ryzen 3900X @ 3.8 GHz - Palit GeForce RTX 2070 Super
Serveur domestique : Ubuntu Server « Jammy Jellyfish » 22.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz
Hors ligne
Pages : 1