Espace de noms réseau
Les espaces de noms réseaux (network namespace) sous Linux permettent de cloisonner un ensemble applicatif relatif aux réseaux. Toute interface, service, paquet, trame... appartenant au même espace de noms sont isolés des éléments appartenant à un autre, au même titre que si ces éléments avaient été sur des machines différente. C'est le concept utilisé pour faire des conteneurs sous Linux afin de garantir une isolation plus poussé qu'un simple chroot.
Toutefois, un espace de noms réseau peut communiquer avec d'autres espaces si ils sont liés par une interface veth.
Les bases
L'ensemble des étapes de cette section sont a effectués sur la même machine. Utilisez un PC avec 2 interfaces réseau (un adaptateur USB/Ethernet fera l'affaire). Vous pouvez y connecter des clients pour bien comprendre les interactions entre les espaces de noms.
J'utilise une Debian 9 pour la documentation. Le paquet iproute2
est nécessaire pour pouvoir suivre ce qui suit.
Je me réfère à ce schéma pour cette section.
Création d'un espace de noms réseau
Création
ip netns add privé
Listage
ip netns list
est équivalent à
ls /var/run/netns
ASTUCE
Par défaut sous Linux, tout est exécuté dans un espace de noms nommé 1 et qui n'apparais pas dans le listage. Cette information sera utile pour la suite.Suppression
ip netns del privé
Si nous en avons créés plusieurs, nous pouvons tous les supprimer avec les commandes suivantes:
- Avec une version d'iproute2 récente:
ip -all netns delete
- Avec une ancienne version:
ip netns | xargs -I {} ip netns delete {}
Pour le moment, notre espace de noms ne contient rien, il ne sert donc à rien. Nous allons voir comment l'approvisionner pour cloisonner des interfaces.
Utilisation
Provisionnement d'une interface
ip link set netns privé dev eth0
Vous constatez avec un ip l
que votre interface eth0
a disparue. Elle se trouve désormais dans l'espace de noms.
INFORMATION
Le fait de déplacer une interface réseau d'un espace de nom à un autre a pour effet de purger sa configuration au même titre qu'unip a f eth0
. Il faudra donc penser à reconfigurer l'adressage et l'allumage de cette interface.Exécution d'une commande
Pour interagir avec notre espace de noms privé, il faut entrer des commandes dans celui-ci comme s'il s’agissait d'un shell à par-entière. Nous allons lister la configuration des interfaces de notre espace de noms avec ceci:
ip netns exec privé ip a
Paramètres:
- exec: exécute une commande dans l'espace de noms
- privé: espace de nom concerné par l'exécution (noté PID dans les pages de man)
- ip a: Commande que l'on aurai tapé normalement pour lister la configuration des interfaces réseaux
Comme expliqué plus haut, la configuration de l'interface déplacé a été purgé. Il convient donc donc d'exécuter les commandes suivantes pour y remettre une adresse IP et l'allumer (pensez également que l'ensemble des routes y faisant référence ont été supprimées):
ip netns exec privé ip a a 192.168.1.254/24 dev eth0 ip netns exec privé ip l set eth0 up
À ce stade vous pouvez tenter un ping entre vos deux interfaces (configurez correctement le niveau 3 OSI bien sûr, c'est pas magique). Vous constaterez que les deux réseaux ne parviennent pas à se joindre bien qu'ils soit sur la même machine physique (il n'y a d'ailleurs pas de routes directement connectés pour joindre ces réseaux). Il en va de même pour les clients connectés aux deux extrémités (un sur l'interface dans privé et l'autre dans 1).
Dé-provisionnement d'une interface
ip netns exec privé ip link set eth0 netns 1
Note: c'est ici que le nom de l'espace de noms par défaut de Linux nous est utile.
Intercommunication avec les veth
Une interface veth est une interface fonctionnant par paire qui va nous servir à communiquer d'un espace de noms à un autre.
Création
ip link add vers_privé type veth peer name vers_1
Nous avons 2 interfaces supplémentaires nommées vers_privé et vers_1. Ces deux interfaces sont liées. Tout paquets envoyé vers l'une sortira par l'autre. Il va donc falloir envoyer une de ces interfaces dans notre espace de noms privé et laisser l'autre dans 1.
Provisionnement
ip link set vers_1 netns privé
Désormais, notre interface vers_1 trône aux coté d'eth0 dans privé. On peux entrer cette série de commande pour réaliser une communication inter-espace de noms:
# Configuration des interfaces dans "privé"
ip netns exec privé ip a a 192.168.1.254/24 dev eth0
ip netns exec privé ip l set eth0 up
ip netns exec privé ip a a 1.1.1.0/31 dev vers_1
ip netns exec privé ip l set vers_1 up
ip netns exec privé ip r a default via 1.1.1.1
# Configuration des interfaces dans "1"
ip a a 1.1.1.1/31 dev vers_privé
ip r a 192.168.1.0/24 via 1.1.1.0
ip a a 192.168.2.254/24 dev eth1
ip l set eth1 up
La communication entre VPC-1 et VPC-2 peut être vérifié par la commande suivante sur VPC-1
ping 192.168.2.1
Suppression
ip link del vers_privé type veth peer name vers_1
Note: Ceci a pour effet de supprimer les deux interfaces et ceux, dans tout les espaces de noms où elles sont présentes.
Utilité
En l'état, la chose parait bien peut utile mais le concept peut être étendu à l'élaboration d'un LAB (pourquoi ne pas créer notre propre GNS3 ?), la production où certains éléments doivent être isolé du reste sans utiliser de virtualisation ou bien à des fins de tests...
À titre d'exemple, les espaces de noms réseaux m'ont permit de tester 2 cartes réseaux 10gbps sur la même machine en m'assurant que les paquets passaient bien par le câble et non par le bus PCIe (quand on a qu'une seule carte mère à disposition, ça dépanne).
Sources de la section
- http://man7.org/linux/man-pages/man8/ip-netns.8.html
- http://ask.xmodulo.com/remove-network-namespaces-linux.html
- https://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/
Implémentations concrètes
Passerelle IPSec
Une implémentation concrète du cloisonnement apporté par les espaces de noms est le cas d'une passerelle IPSec.
Imaginons que nous souhaitons faire communiquer deux réseaux à travers un tunnel IPSec comme dans la documentation déjà parue sur le sujet mais que l'usage des VLAN ne soit pas désiré. Nous souhaitons tout de même que les clients du LAN privé ne puissent pas faire autrement que de passer par le VPN pour accéder aux autres réseaux (d'on Internet si voulu). Avec les espaces de noms réseaux et les virtual tunnel interfaces (VTI), cette isolation pourras être effectuée et le couple encapsulation/décapsulation sera exécuté dans un espace de noms différent, ce qui assure un cloisonnement étanche en plus de ne pas avoir à ce faire chier avec les politiques de sécurité IPSec (qui dés que l'on sort du cadre pair à pair deviennent un enfer à gérer). Et cerise sur le gâteau, plus besoin de se faire chier à baisser le MTU des clients pour transférer des fichiers ! Le PMTUD fait son travail dans cette configuration.
Présentation
Pour ce LAB, j'utilise l'architecture suivante.
Les éléments nécessaires à sa mise en place ont été:
- GNS3
- Un disque qcow2 avec une Debian Stretch (9)
- Les utilitaires
iproute2
etstrongswan
- 2 MV exploitant une copie du disque qcow2 ainsi que 2 interfaces réseaux par machines
- Un routeur IOU ou non (j'ai utilisé un commutateur IOU avec des
no switchport
sur les interfaces - 2 VPCS servant de clients pour effectuer les PING
Interfaces vti
Ce concept vient de l'entreprise Cisco et reprend notre façon de faire avec le tunnel de ce document. Partant du postulat que IPSec est un protocole ultra casse couille lorsqu'il s'agit de chiffrer des paquets routés, nous sommes plusieurs à penser qu'il est beaucoup plus simple d'utiliser des interfaces tunnels (qui elles sont autorisés par IPSec) et de faire transiter notre trafic réseau comme bon nous semble à l’intérieur en s’émancipant de la lourdeur d'IPSec.
Ainsi, les interface vti sont de bêtes tunnels GRE que l'on peut étiqueter (pour les gérer avec IPSec) et déplacer dans des espaces de noms différents.
Mise en place
Je ne vais pas détailler les étapes car en dehors de la partie sur les vti (d'on la commande idoine est limpide de clarté), tout a été expliqué et rien n'est fondamentalement incompréhensible à la lecture.
R1
ip netns add ipsec_rouge
ip tunnel add vti_rouge mode vti local 1.1.1.1 remote 1.1.1.10 key 6
ip link set netns ipsec_rouge dev vti_rouge
ip netns exec ipsec_rouge ip addr add 10.20.30.0/31 dev vti_rouge
ip netns exec ipsec_rouge ip link set vti_rouge mtu 1500
ip netns exec ipsec_rouge ip link set vti_rouge up
ip link set netns ipsec_rouge dev eth0
ip netns exec ipsec_rouge ip addr add 192.168.1.254/24 dev eth0
ip netns exec ipsec_rouge ip link set eth0 up
ip netns exec ipsec_rouge sysctl -w net.ipv4.ip_forward=1
ip netns exec ipsec_rouge ip r a default via 10.20.30.1
vim /etc/ipsec.conf
conn R1-vers-R2
left = 1.1.1.1
leftsubnet = 0.0.0.0/0
right = 1.1.1.10
rightsubnet = 0.0.0.0/0
authby = psk
mark = 6
auto = route
keyexchange = ikev2
keyingtries = %forever
ike = aes256gcm16-prfsha384-ecp384!
esp = aes256gcm16-prfsha384-ecp384!
mobike = no
vim /etc/ipsec.secrets
%any %any : PSK "MOT_DE_PASSE_TRES_SECRET"
ipsec restart ipsec up R1-vers-R2
R2
ip netns add ipsec_rouge
ip tunnel add vti_rouge mode vti local 1.1.1.10 remote 1.1.1.1 key 6
ip link set netns ipsec_rouge dev vti_rouge
ip netns exec ipsec_rouge ip addr add 10.20.30.1/31 dev vti_rouge
ip netns exec ipsec_rouge ip link set vti_rouge mtu 1500
ip netns exec ipsec_rouge ip link set vti_rouge up
ip link set netns ipsec_rouge dev eth0
ip netns exec ipsec_rouge ip addr add 192.168.2.254/24 dev eth0
ip netns exec ipsec_rouge ip link set eth0 up
ip netns exec ipsec_rouge sysctl -w net.ipv4.ip_forward=1
ip netns exec ipsec_rouge ip r a default via 10.20.30.0
vim /etc/ipsec.conf
conn R2-vers-R1
left = 1.1.1.10
leftsubnet = 0.0.0.0/0
right = 1.1.1.1
rightsubnet = 0.0.0.0/0
authby = psk
mark = 6
auto = route
keyexchange = ikev2
keyingtries = %forever
ike = aes256gcm16-prfsha384-ecp384!
esp = aes256gcm16-prfsha384-ecp384!
mobike = no
vim /etc/ipsec.secrets
%any %any : PSK "MOT_DE_PASSE_TRES_SECRET"
ipsec restart ipsec up R2-vers-R1 ipsec status
Phase de test
À ce stade, la communication chiffrée est possible. Voici une procédure de test servant à vérifier le fonctionnement du tout.
Sur un des serveur IPSec
ip netns exec ipsec_rouge tcpdump -n -i any
Ici R1.
Ping du client rattaché à l'espace de noms vers le client d'en face
ping 192.168.2.1
Ici "VPC-1" vers "VPC-2".
Les paquets apparaissent en clair sur le tcpdump du serveur dans cet espace de noms.
Maintenant, exécutez la même commande dans l'espace de noms par défaut (le réseau noir) et refaites le ping, vous ne voyez plus que des paquets esp (donc chiffrés).
Sur un des serveur IPSec
tcpdump -n -i any
Ici R1.
Ping du client rattaché à l'espace de noms vers le client d'en face
ping 192.168.2.1
Ici "VPC-1" vers "VPC-2".
Évolution
On peut imaginer pour la suite mettre d'un coté un couple de veth avec le routage qui va bien pour permettre à un des deux réseaux d'accéder à Internet ou à n'importe quel réseaux via le tunnel chiffré. L'utilisation de VXLAN peut également être imaginé en remplacement des VLAN.