Contenu | Rechercher | Menus

Annonce

Ubuntu-fr vend de superbes t-shirts et de belles clés USB 32Go
Rendez-vous sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 31/12/2018, à 01: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, à 19:29)


Poste de travail : Kubuntu (KDE Plasma 5.14.4, Frameworks 5.52.0) « Cosmic Cuttlefish » 18.10 64 bits - Intel Core i7 860 @ 2.8 GHz - SLI 2 x Asus GTX660-DC2T-2GD5
Serveur domestique : Ubuntu Server « Bionic Beaver » 18.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz

Hors ligne

#2 Le 13/01/2019, à 01: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 tongue

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 ?

Hors ligne

#3 Le 24/01/2019, à 22: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, à 09:57)


Poste de travail : Kubuntu (KDE Plasma 5.14.4, Frameworks 5.52.0) « Cosmic Cuttlefish » 18.10 64 bits - Intel Core i7 860 @ 2.8 GHz - SLI 2 x Asus GTX660-DC2T-2GD5
Serveur domestique : Ubuntu Server « Bionic Beaver » 18.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz

Hors ligne

#4 Le 25/03/2020, à 19: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, à 19:26)


Poste de travail : Kubuntu (KDE Plasma 5.14.4, Frameworks 5.52.0) « Cosmic Cuttlefish » 18.10 64 bits - Intel Core i7 860 @ 2.8 GHz - SLI 2 x Asus GTX660-DC2T-2GD5
Serveur domestique : Ubuntu Server « Bionic Beaver » 18.04.1 LTS 64 bits - Intel Core i5 2400S @ 2.5 GHz

Hors ligne