Docker réseau
Je note ici quelques informations utiles concernant les réseaux de Docker
Création d'un réseau IPV6
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
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 -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.
Dans docker-compose.yml
Il est possible de créer des réseau dans le fichier docker-compose.yml, ce qui est bien pratique. Il est cependant intéressant de connaître certaines astuces
La base
Pour associer un conteneur à un réseau la syntaxe de base est la suivante :
version: '3.7' services: conteneur1: image: ubuntu:latest container_name: test ports: - "80:80" - "443:443" networks: - serveur_web networks: serveur_web: name: serveur_web
Dans ce cas là si le réseau nommé serveur_web n'existe pas il sera crée
Plusieurs réseaux
Quand on souhaite qu'un conteneur puisse communiquer avec d'autres il faut qu'ils aient un réseau en commun, on peut donc choisir de faire la chose suivante :
version: '3.7' services: conteneur1: image: ubuntu:latest container_name: test ports: - "80:80" - "443:443" networks: - serveur_web - base_de_donnees networks: serveur_web: name: serveur_web base_de_donnees: external: true
Dans ce cas là en spécifiant external: true, Docker s'attend à ce que ce réseau là soit déjà créé, il vous fera une erreur si ce n'est pas le cas.
Changer le MTU
Ici c'est dans un cas bien particulier, il se peut que pour certaines raisons (comme l'utilisation de Wireguard#Connexion_SSH), vous deviez configurer le MTU :
version: '3.7' services: conteneur1: image: ubuntu:latest container_name: test ports: - "80:80" - "443:443" networks: - serveur_web networks: serveur_web: name: serveur_web driver: bridge driver_opts: com.docker.network.driver.mtu: 1200
Si le réseau existait déjà, il faudra dans un premier temps le supprimer puis laisser docker-compose le recréer avec le bon MTU