« Docker réseau » : différence entre les versions

De wiki jackbot
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Aucun résumé des modifications
 
Ligne 34 : Ligne 34 :
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.
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.


<h1>Tests</h1>
<h2>Tests</h2>
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.
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.


<h1>ip6tables</h1>
<h2>ip6tables</h2>
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 :  
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 :  
<pre style="color: silver; background: black;">
<pre style="color: silver; background: black;">
Ligne 49 : Ligne 49 :
</pre>
</pre>
Qui va marquer les paquets sortant afin qu'il puissent revenir sans encombre.
Qui va marquer les paquets sortant afin qu'il puissent revenir sans encombre.
<h1>Dans docker-compose.yml</h1>
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
<h2>La base</h2>
Pour associer un conteneur à un réseau la syntaxe de base est la suivante :
<pre style="color: silver; background: black;">
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
</pre>
Dans ce cas là si le réseau nommé serveur_web n'existe pas il sera crée
<h2>Plusieurs réseaux</h2>
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 :
<pre style="color: silver; background: black;">
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
</pre>
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.
<h2>Changer le MTU</h2>
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 :
<pre style="color: silver; background: black;">
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
</pre>
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

Version actuelle datée du 9 janvier 2022 à 16:34


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