Dépôts de configurations et scripts pour le logiciel de conteneurisation Systemd-nspawn.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ycharbi 513a5d1efc
Ajout du support des ponts isolés en espace de noms réseau + ajout de la configuration de la MTU pour simplifier sa personnalisation par modification manuelle du script
3 weeks ago
README.md Ajout du support des ponts isolés en espace de noms réseau + ajout de la configuration de la MTU pour simplifier sa personnalisation par modification manuelle du script 3 weeks ago
ifdown.sh Même modification que le commit précédent pour ifdown.sh 7 months ago
ifup.sh Ajout du support des ponts isolés en espace de noms réseau + ajout de la configuration de la MTU pour simplifier sa personnalisation par modification manuelle du script 3 weeks ago

README.md

Usage

Les fichiers ifup.sh et ifdown.sh sont des scripts de gestion d'interfaces réseaux pour les conteneurs Systemd-nspawn écrit par mes soins. Supportant les VLAN et les ponts isolés en espace de noms réseau (sans support du 802.1Q pour ces derniers), ils se bases sur la technologie de filtrage des VLAN du noyau Linux pour la gestion du 802.1Q. Les ponts isolés peuvent quant à eux être utilisés pour empêcher la communication des conteneurs au sein d'un même LAN. Cette approche permet une mise en œuvre d'une défense en profondeur dans la communication inter-conteneur.

  • ifup.sh permet l'attribution d'une interface physique à un conteneur ainsi que la création et le placement d'une interface réseau virtuelle dans un VLAN ou dans un tronc 802.1Q. Il se charge également de l'intégrer à un pont spécifique. Pour les ponts isolés en espace de noms réseau, les VLAN ne sont pas supportés. L'existence préalable des ponts et des espaces de noms réseau (si pont isolé) est requise
  • ifdown se charge de supprimer les interfaces créées par Systemd-nspawn après l'extinction du conteneur

Afin qu'ils s'exécutent au démarrage et à l'arrêt d'un conteneur, il faut modifier le service systemd-nspawn@.service pour y ajouter les directives adéquates. Notez l'emplacement des scripts dans l'exemple et assurez-vous de leur permission d'exécution :

systemctl edit systemd-nspawn@.service

Collez-y le contenu suivant. Ceci aura pour effet de créer le fichier /etc/systemd/system/systemd-nspawn@.service.d/override.conf qui persistera aux mises à jour du paquet systemd-container.

[Service]
ExecStartPre=/etc/systemd/nspawn/ifup.sh %i
ExecStopPost=/etc/systemd/nspawn/ifdown.sh %i

Si vous voulez revenir en arrière, un systemctl revert systemd-nspawn@.service supprimera le fichier de modifications et restaurera l'état initial sans laisser de traces de l'opération précédente.

💡 Le traitement des paramètres d'interfaces des conteneurs des fichiers *.nspawn s'appuit sur des commentaires spécifiques à placer directement au dessus de chaque directives Interface=.

Pour configurer les interfaces réseaux d'un conteneur, il faut :

  • Interface physique : utiliser la directive Interface= de façon normale en veillant à ne pas avoir l'une des deux lignes de commentaire dans les deux lignes au dessus de celle-ci
  • Interface virtuelle : ajouter deux lignes de commentaires au dessus de chaque directive Interface= dans le fichier de configuration de celui-ci

Pour une interface physique :

Interface=nomIfacePhy

Pour une interface non étiqueté (mode access) :

#PONT=votrePont
#VLAN=vid
Interface=nomIfaceVirt_vid

Pour une interface de tronc 802.1Q (mode trunk) :

#PONT=votrePont
#8021Q=vid1,vi2,vid3
Interface=nomIfaceVirt_vid

Pour une interface en pont isolé :

#PONT=votrePont
#ISOLE=votreEspaceDeNomsRéseau
Interface=nomIfaceVirt

Il est possible de mixer les notions au travers de plusieurs interfaces comme dans l'exemple suivant (fichier /etc/systemd/nspawn/web.nspawn) :

[Network]
#PONT=br0
#VLAN=100
Interface=web_100
#PONT=br0
#VLAN=121
Interface=web_121
#PONT=br0
#8021Q=5,210
Interface=web_T1

Interface=eth2
#PONT=br1
#8021Q=181,1109
Interface=web_T2
#PONT=br-netns135
#ISOLE=netns135
Interface=nxtcld

Le script vérifie que ce que vous avez renseigné est valide. S'il rencontre la moindre erreur, il s'interrompt sans modifier le système et vous oriente sur le problème. En utilisation avec un conteneur, les messages de retour du script sont visibles dans le journal du service via systemctl status systemd-nspawn@votreConteneur.service ou journalctl -xe.

⚠️ J'attire votre attention sur le fait que l'ajout, en cours de fonctionnement, de directives Interface= dans le ficher de configuration de votre conteneur a pour effet de neutraliser l'exécution de ifdown.sh. Ceci est intrinsèque à la façon dont il fonctionne. Les interfaces créées par ifup.sh devront alors êtres supprimées manuellement.

Environnement

Toute référence à un pont ou à un espace de noms réseau suppose son existence préalable. Cette section propose un exemple de configuration réseau pour un système GNU/Linux Debian mettant en œuvre un pont avec filtrage de VLAN ainsi qu'un pont isolé en espace de noms réseau. Il conviendra d'en adapter les valeurs pour coller avec votre besoin.

Fichier /etc/network/interfaces :

auto lo
iface lo inet loopback
	up /usr/local/sbin/confint

Fichier /usr/local/sbin/confint :

#!/bin/bash
# Script de configuration des interfaces réseau

nom_pont="br0"
nom_iface1="ens3"

# La MTU peut être passée à 9000 pour l'activation des trames géantes (adapter cette valeur dans le script le cas échéant)
ip link set "${nom_iface1}" mtu 1500
ip link set "${nom_iface1}" up

# Création du pont supportant le 802.1Q
ip link add "${nom_pont}" type bridge vlan_filtering 1
ip link set "${nom_pont}" up

# Ajout de l'interface physique au pont
ip link set "${nom_iface1}" master "${nom_pont}"

# Désactivation du VLAN par défaut sur le pont afin de l'isoler
bridge vlan del dev "${nom_pont}" vid 1 self
bridge vlan del dev "${nom_iface1}" vid 1 master

# VLAN
id_vlan="10"
nom_svi="vlan${id_vlan}"
ip_svi="192.168."${id_vlan}".1/24"
ip link add link "${nom_pont}" name vlan"${id_vlan}" type vlan id "${id_vlan}"
ip link set "${nom_svi}" up
ip address add "${ip_svi}" dev "${nom_svi}"
bridge vlan add dev "${nom_iface1}" vid "${id_vlan}" tagged master
bridge vlan add dev "${nom_pont}" vid "${id_vlan}" tagged self

id_vlan="20"
nom_svi="vlan${id_vlan}"
ip_svi="192.168."${id_vlan}".1/24"
ip link add link "${nom_pont}" name vlan"${id_vlan}" type vlan id "${id_vlan}"
ip link set "${nom_svi}" up
ip address add "${ip_svi}" dev "${nom_svi}"
bridge vlan add dev "${nom_iface1}" vid "${id_vlan}" tagged master
bridge vlan add dev "${nom_pont}" vid "${id_vlan}" tagged self

# Routage
ip route add default via 192.168.10.254 dev vlan10 onlink

# Pont isolé 135
id_rzo="135"
nom_netns="netns${id_rzo}"
nom_pont="br-netns${id_rzo}"
nom_veth="veth${id_rzo}"
ipv4_veth="10.1.${id_rzo}.254/24"
ip netns add "${nom_netns}"
ip netns exec "${nom_netns}" ip link add "${nom_pont}" type bridge stp_state 0
ip link add ${nom_veth} type veth peer name ${nom_veth}_h
ip link set netns "${nom_netns}" dev ${nom_veth}_h
ip netns exec "${nom_netns}" ip link set ${nom_veth}_h master "${nom_pont}"
ip netns exec "${nom_netns}" ip link set dev ${nom_veth}_h type bridge_slave isolated off
ip netns exec "${nom_netns}" sh -c "echo 1 > /proc/sys/net/ipv6/conf/${nom_pont}/disable_ipv6"
ip netns exec "${nom_netns}" sh -c "echo 1 > /proc/sys/net/ipv6/conf/${nom_veth}_h/disable_ipv6"
ip netns exec "${nom_netns}" ip link set ${nom_pont} up
ip netns exec "${nom_netns}" ip link set ${nom_veth}_h up
ip address add "${ipv4_veth}" dev "${nom_veth}"
ip link set "${nom_veth}" up

Ne pas oublier d'ajouter les droits d'exécution au script et d'activer le routage :

chmod +x /usr/local/sbin/confint

# Configuration de routage éphémère
# Utiliser un paramètre sysctl pour le rendre persistent
echo 1 > /proc/sys/net/ipv4/ip_forward

Tests sans altérations

Si vous voulez modifier les scripts, il peut être pratique d'afficher les commandes générées sans les appliquer lors de vos tests. Pour ce faire, il suffit de commenter la ligne suivante (et comme précisé en commentaire dans le script) dans la fonction execCmdIntRzo() (le script exige un nom de conteneur en paramètre) :

# ${commandes_a_executer["${id_commande_rzo}"]}