Docker réseau

De wiki jackbot
Aller à la navigation Aller à la recherche


Le passage nécessaire à l'ipV6 nous impose de comprendre des nouvelles règles et notamment pour Docker, qui même s'il est compatible, n'a pas été conçu avec l'ipV6 en tête. Un exemple flagrant pour le prouver est que lors de la création d'un réseau à partir de docker-compose l'option :

enable_ipv6: true

N'est pas reconnu avec toutes les versions de fichiers. D'après les infos que j'ai pu trouvé sur le net, jusqu'à la version 2.1, cette option est reconnue, mais plus après.

Il existe plusieurs façon d'activer l'ipV6 sur Docker, soit en modifiant le fichier /etc/docker/daemon.json comme l'indique la documentation. Ce qui aura pour effet d'activer l'ipV6 sur le réseau "bridge" de docker. Soit créer soit même un réseau en ipV6 avec la commande :

docker network create

Création du réseau

C'est cette dernière option que j'ai choisi, car elle va me permettre de facilement connecter les conteneurs dessus avec docker-compose. La commande complète est la suivante :

docker network create --driver bridge --ipv6 --subnet=2a0a:da80:580:4:7aac::/80 --gateway=2a0a:da80:580:4:7aac:c0ff:feae:d344/64 -o "com.docker.network.bridge.enable_ip_masquerade=true" nom_du_reseau

Les options importantes ici sont subnet et gateway.

Subnet ou sous-réseau

Le sous réseau est en fait toutes les adresses qui seront disponibles pour ce réseau. Si on donne la valeur du préfixe ipv6, alors ce réseau aura le droit d'utiliser toutes les adresses qui sont à notre disposition. Ce qui n'est pas forcément une bonne idée, car cela signifie que docker pourra attribuer toutes les adresse ipV6 qu'il veut, y compris celle qui sont déjà prise. Je vous l'accorde, 2^64 adresse disponible ça fait beaucoup et la probabilité que 2 soient identiques est très faible. Cependant pour éviter les risques et s'assurer que docker n'attribuera pas une adresse déjà prise, il ne faut pas se contenter des 4 blocs du préfixe, on peut en ajouter un ou plusieurs pour restreindre le nombre d'adresse disponible. Il faut cependant penser à changer le masque de sous-réseau.

La gestion du masque de sous-réseau est légèrement différente en ipV6, car là on va simplement indiquer le nombre de bits constant sur l'adresse. Dans mon exemple : 2a0a:da80:580:4:7aac::/80, cela signifie que les 80 premiers bits seront constant et donc nécessairement toutes les adresses commenceront par : 2a0a:da80:580:4:7aac:. Chaque bloc contient 16bits, donc à chaque fois qu'on ajoute un bloc il faut ajouter 16 au masque de sous réseau.

Par exemple si j'avais ajouté un bloc j'aurai pu obtenir le sous réseau : 2a0a:da80:580:4:7aac:c0ff::/96

Gateway

En ce qui concerne la gateway, ou passerelle en bon français. Il faut qu'elle soit accessible depuis le sous réseau, en d'autres termes il faut qu'elle soient contenu dans le sous réseau. Ici j'ai pris l'adresse ipV6 de ma carte réseau.

Tests

Si vous connectez un conteneur à ce réseau, vous pourrez le joindre en utilisant l'adresse ipV6 de la carte réseau du serveur (2a0a:da80:580:4:7aac:c0ff:feae:d344). Cependant en y regardant de plus près vous verrez aussi que votre conteneur à l'impression que les paquets proviennent de cette même adresse. Ce qui est problématique quand on veut surveiller un minimum ce qu'il se passe sur le réseau ... C'est donc fonctionnel, mais pas top ... Après de longues recherches j'ai cru comprendre que Docker n'est pas encore tout à fait mature pour l'ipV6. Car si vous vous amusez à regarder les règles iptables que Docker ajoute, vous verrez qu'il y en a plein, mais les règles ip6tables il n'y en a aucune. On va donc en ajouter quelques unes à la main pour faire le travail.

ip6tables

iptables est une commande capable d'envoyer des règles de filtrages à netfilter. ip6tables fait la même chose mais pour des adresses ipV6. Ici ce qui va nous intéresser est que les paquets entrant sur l'interface réseaux, ne soient pas traité par le serveur, mais directement renvoyé au bon conteneur. Il faut donc agir sur les règles de PREROUTING. Avec la commande :

ip6tables -t nat -A PREROUTING -d 2a0a:da80:580:4:7aac:c0ff:feae:d344 -p tcp --dport 8080 -j DNAT --to-dest [2a0a:da80:580:4:7aac::2]:8080

On va rediriger les paquets entrants sur le port 8080 vers l'adresse ipV6 du conteneur qui écoute ce port.

Ça c'est pour les paquets entrant, mais pour les paquets sortant ? Pour ça il faut jouer sur POSTROUTING avec la commande :

ip6tables -t nat -A POSTROUTING -o enp63s0 -j MASQUERADE

Qui va marquer les paquets sortant afin qu'il puissent revenir sans encombre.