Je vous propose d’expérimenter le routage IP sous Linux (Debian), grâce aux outils de la suite iproute2, afin de mieux comprendre ce mécanisme essentiel du niveau 3 de l’OSI.
Nous allons déployer un environnement avec deux réseaux locaux fermés (LAN1 et LAN2) et trois machines de type debian core : une dans chaque LAN et une avec une "patte" dans chaque réseau local :

Puis nous mettrons en œuvre un routage statique entre ces deux réseaux.
Il est recommandé de connaître le Protocole Internet (IP) et le principe du routage associé. Pour plus de clarté, nous n’utiliserons dans ces travaux que le protocole IPv4 (le principe est le même avec IPv6).
On désigne par iproute2 une collection d’utilitaires pour la gestion des protocoles TCP, UDP, IP et la gestion du réseau sous Linux, supportant l’IPv4 et l’IPv6. La collection iproute2 est destinée à remplacer toute une suite d’outils réseau standard Unix (appelée net-tools) qui étaient anciennement utilisés pour les tâches de configuration d’interfaces réseau, tables de routage, et gestion de table ARP. La suite net-tools est dépréciée, il est recommandé de ne plus l’utiliser.
Voici quelques exemples d’outils net-tools remplacés par iproute2 :
| Usage | Ancien outil net-tools | Commande iproute2 |
|---|---|---|
| Adressage (niv. 2) | ifconfig | ip link |
| Adressage (niv. 3) | ifconfig | ip addr |
| Routage | route | ip route |
| Résolution d’adresses | arp | ip neigh |
| VLAN | vconfig | ip link |
| Tunnels | iptunnel | ip tunnel |
| Multicast | ipmaddr | ip maddr |
| Statistiques | netstat | ss |
Nous allons créer les trois machines GNU/Linux debian-core :
Pour créer ces machines, voir le tutoriel de référence pour l'installation debian-core sous VirtualBox
Il est possible bien entendu de créer une première et de la cloner deux fois. Attention à bien générer de nouvelles adresses MAC pour les interfaces réseau :

Le PC hôte de nos VM doit être connecté à Internet afin que chaque VM accède elle-même à Internet via la connexion NAT (recommandé).
Toutes les commandes à suivre sont réalisées en mode console, connecté avec l’utilisateur sudoer.
On vérifie la connectivité à Internet, en testant la connexion à une adresse IP externe connue (ici le DNS Cloudflare)...
ping 1.1.1.1
... et que la résolution DNS fonctionne :
ping debian.org
On commence par les opérations classiques de mise à jour :
sudo apt update && sudo apt upgrade
Puis on installe sur chaque machine les utilitaires tcpdump et traceroute :
sudo apt install -y tcpdump traceroute
Ces opérations sont à faire pour chaque VM.
Une fois les trois machines préparées, il faut les éteindre :
sudo poweroff
Il faut maintenant recâbler le hardware virtuel afin de créer l’infrastructure suivante (on utilise les réseaux internes de l’hyperviseur) :

Dans cette configuration, les machines ne seront plus connectées à Internet.
Voici la configuration sous VirtualBOX de l’interface réseau de debianA connectée au réseau interne LAN1 :

Puis la configuration pour debianB qui est sur LAN2 :

La machine debianX quant à elle dispose de deux interfaces réseau, une sur chaque LAN :


Nous modifions maintenant le nom de chaque machine (hostname).
On démarre d'abord les machines.
Puis, en partant du principe que le hostname actuel de chaque VM est debian :
echo "debianA" | sudo tee /etc/hostname
Cette commande remplace le contenu du fichier /etc/hostname par la chaîne "debianA".
echo envoie le texte.sudo tee permet d'écrire dans un fichier système protégé par des droits root tout en affichant la sortie dans le terminal.sudo sed -i 's/debian/debianA/g' /etc/hosts
Cette commande modifie le fichier /etc/hosts pour assurer la cohérence du réseau local.
sed -i édite le fichier directement ("in-place").'s/debian/debianA/g' recherche toutes les occurrences de l'ancien nom (debian) et les remplace par le nouveau (debianA) pour que la machine puisse toujours se reconnaître elle-même.Puis on redémarre pour prendre en compte la modification du hostname :
sudo reboot
De la même façon :
echo "debianB" | sudo tee /etc/hostname
sudo sed -i 's/debian/debianB/g' /etc/hosts
sudo reboot
De la même façon :
echo "debianX" | sudo tee /etc/hostname
sudo sed -i 's/debian/debianX/g' /etc/hosts
sudo reboot
Nous utiliserons donc la suite de commandes iproute2, devenue le standard sur les systèmes GNU/Linux.
La commande ip link show (que l’on peut abréger avec ip link et même ip l), permet d’afficher les interfaces disponibles. Par exemple sur la machine X :
ip link show

Nous voyons les deux interfaces Ethernet de debianX. Bien repérer leurs noms ; ici : enp0s3 et enp0s8
Grâce aux adresses MAC, on peut valider quelle interface est en lien avec quel réseau. Ici, enp0s3 (adresse MAC 08:00:27:E4:DF:49) est clairement la carte qui est connectée au LAN1, selon le repérage effectué juste avant.
La carte enp0s8 est DOWN, car elle n'était pas présente au moment de l'installation, elle n’est donc pas encore configurée dans le système.
Revenons sur la machine debianA.
Nous pouvons lui attribuer l’adresse IPv4 192.168.10.1/24 sur son interface enp0s3 (si c’est son nom ; avec vmware workstation par exemple, elle aurait pu s’appeler ens32) :
sudo ip addr add 192.168.10.1/24 dev enp0s3
ip addr show

Voici ce qu'on peut observer :
192.168.10.1 avec un masque de sous-réseau de 24 bits à l'interface réseau enp0s3.ip addr show confirme que l'adresse a bien été ajoutée.169.254.18.209 (APIPA). Cela indique que l'interface est configurée pour obtenir une adresse via DHCP, mais qu'aucun serveur DHCP n'a répondu.C'est le paquet
avahi-autoipd- installé par défaut depuis debian 13 - qui installe ce service APIPA.
Cette configuration ne sera pas persistante au prochain redémarrage du système. Pour ce faire, il faut modifier le fichier de configuration des interfaces réseau :
sudo nano /etc/network/interfaces
Il faut modifier les paramètres de l’interface réseau (lignes 12 et 13) en conservant le nom de l’interface sur votre propre système s'il est différent :
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
allow-hotplug enp0s3
iface enp0s3 inet static
address 192.168.10.1/24
La configuration de l’interface primaire est précédée de celle de la boucle interne loopback (
lo) et de quelques commentaires . Attention aux erreurs de frappe qui décommentent par mégarde certaines lignes dans les fichiers de configuration… et plantent l’initialisation correcte du système (une cause fréquente est l’état de cette satanée touche VERR.NUM…)
Après un redémarrage de la machine, la configuration IPv4 est correcte et persistante (et l'APIPA a disparu) :

Il nous faut paramétrer maintenant les autres machines. D’abord debianB :
sudo nano /etc/network/interfaces
...
allow-hotplug enp0s3
iface enp0s3 inet static
address 192.168.11.1/24
Puis debianX, avec ses deux interfaces enp0s3 et enp0s8 :
sudo nano /etc/network/interfaces
...
allow-hotplug enp0s3
iface enp0s3 inet static
address 192.168.10.254/24
allow-hotplug enp0s8
iface enp0s8 inet static
address 192.168.11.254/24
Pour appliquer les modifications, on peut relancer la machine. On peut également redémarrer le service réseau :
sudo systemctl restart networking
et voilà ! la commande ip a nous retournera :

L'adresse APIPA est restée sur
enp0s3, c'est ce qui arrive quand on redémarre seulement le service réseau. En redémarrant le système entier, elle n'apparaîtra plus.
Une fois tout cela en place, il doit être possible de pinger la debianX depuis debianA :
ping -c3 192.168.10.254
Et de pinger également debianX depuis la debianB :
ping -c3 192.168.11.254
Et enfin de pinger les machines A et B depuis debianX :
ping -c3 192.168.10.1
ping -c3 192.168.11.1
Cependant, il n’est pas possible de pinger la debianB depuis debianA :
ping 192.168.11.1
nous donnera :
pascal@debianA:~$ ping 192.168.11.1
ping: connect: Le réseau n'est pas accessible
En effet, la machine debianA ne connaît pas ce réseau 192.168.11.0/24, et encore moins le moyen de s’y rendre.
Regardons quelques commandes iproute2 qui permettent de gérer le cache ARP de la machine. En effet, chaque machine disposant d’une pile (stack) IP gère une table d’association adresse MAC <> adresse IP. Chaque entrée de cette table a par ailleurs une durée de vie limitée. Essayez ces quelques commandes sur debianA :
ping -c1 192.168.10.254
ip neigh
ip n
sudo ip n flush all
ip n
ping -c1 192.168.10.254 && watch ip n
Avec la dernière commande, vous pourrez normalement voir l’évolution d’une entrée ARP entre ses différentes états :
On peut aussi créer une association ARP permanente avec une commande du type :
sudo ip neigh add 192.168.10.254 lladdr 08:00:27:xx:xx:xx dev enp0s3
L’usage d’entrées ARP permanentes peut avoir deux raisons :
Fin du focus ARP. Revenons à nos moutons
Par défaut, le routage n’est pas activé sur une machine Linux standard, et notamment ici sur la machine debianX. Il faut donc activer le routage IPv4 sur notre machine X :
sudo sysctl -w net.ipv4.ip_forward=1
La commande sysctl permet de configurer certaines fonctions du noyau Linux. La commande que nous venons de lancer fonctionne immédiatement, mais elle n'est pas persistante (le réglage sera perdu au redémarrage).
Pour rendre ce changement permanent sur Debian 13, la méthode recommandée est de créer un fichier de configuration dédié dans le répertoire /etc/sysctl.d/ :
sudo nano /etc/sysctl.d/99-routing-custom.conf
Puis d'y ajouter la ligne suivante :
net.ipv4.ip_forward=1
Appliquez ensuite la modification immédiatement, sans avoir besoin de redémarrer la machine, avec la commande suivante :
sudo sysctl --system
On doit notamment apercevoir l'appplication de notre règle (lignes 4 et 13 ici) :
* Applique /usr/lib/sysctl.d/10-coredump-debian.conf ...
* Applique /usr/lib/sysctl.d/50-default.conf ...
* Applique /usr/lib/sysctl.d/50-pid-max.conf ...
* Applique /etc/sysctl.d/99-routing-custom.conf ...
kernel.core_pattern = core
kernel.sysrq = 0x01b6
kernel.core_uses_pid = 1
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.enp0s3.rp_filter = 2
...
vm.max_map_count = 1048576
kernel.pid_max = 4194304
net.ipv4.ip_forward = 1
Quelle commande permet d’afficher la table de routage actuelle de chaque machine ?
ip route
Ce qui doit nous donner, pour chacune de nos machines :
192.168.10.0/24 dev enp0s3 proto kernel scope link src 192.168.10.1
192.168.11.0/24 dev enp0s3 proto kernel scope link src 192.168.11.1
192.168.10.0/24 dev enp0s3 proto kernel scope link src 192.168.10.254
192.168.11.0/24 dev enp0s8 proto kernel scope link src 192.168.11.254
Lancer l’utilitaire tcpdump sur la machine X afin de visualiser les paquets ICMP qui transitent sur son interface reliée à LAN1 (donc sur l’interface enp0s3) :
sudo tcpdump -i enp0s3 icmp
Quelle est la commande pour déclarer une route IP de la machine A vers la machine B ?
# sur debianA :
sudo ip route add 192.168.11.0/24 via 192.168.10.254 dev enp0s3
Traduction : pour joindre le réseau 192.168.11.0/24, il faut passer par la passerelle (gateway) 192.168.10.254, via l’interface enp0s3 (rappel : une passerelle doit toujours faire partie d’un réseau auquel je suis directement connecté).
Que donne un ping de A vers B désormais ?
ping -c4 192.168.11.1
ça ne fonctionne pas :
PING 192.168.11.1 (192.168.11.1) 56(84) bytes of data.
--- 192.168.11.1 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3062ms
Si on analyse les résultats affichés par tcpdump qui tourne sur X :
listening on enp0s3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23:09:00.044684 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 14, seq 1, length 64
23:09:01.059141 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 14, seq 2, length 64
23:09:02.083211 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 14, seq 3, length 64
23:09:03.107000 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 14, seq 4, length 64
... on devine la cause du problème. Il ne faut pas perdre de vue qu’un ping c’est une demande (request) de A vers B, suivi d’une réponse (reply) de B vers A, pour valider la bonne connexion de niveau 3 (IP). Il manque donc ici le message retour de B vers A, donc la route de B vers A.
Quelles est la commande pour activer un routage IP de la machine B vers la machine A ?
# sur debianB :
ip route add 192.168.10.0/24 via 192.168.11.254 dev enp0s3
Et c’est la joie dans la place ! la route est en place de bout en bout :
pascal@debianA:~$ ping -c4 192.168.11.1
PING 192.168.11.1 (192.168.11.1) 56(84) bytes of data.
64 bytes from 192.168.11.1: icmp_seq=1 ttl=63 time=6.96 ms
64 bytes from 192.168.11.1: icmp_seq=2 ttl=63 time=0.688 ms
64 bytes from 192.168.11.1: icmp_seq=3 ttl=63 time=0.787 ms
64 bytes from 192.168.11.1: icmp_seq=4 ttl=63 time=1.88 ms
--- 192.168.11.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3014ms
rtt min/avg/max/mdev = 0.688/2.579/6.962/2.573 ms
Avec tcpdump sur debianX qui affiche :
23:15:23.911152 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 15, seq 1, length 64
23:15:23.912522 IP 192.168.11.1 > 192.168.10.1: ICMP echo reply, id 15, seq 1, length 64
23:15:24.912231 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 15, seq 2, length 64
23:15:24.912572 IP 192.168.11.1 > 192.168.10.1: ICMP echo reply, id 15, seq 2, length 64
23:15:25.923168 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 15, seq 3, length 64
23:15:25.923550 IP 192.168.11.1 > 192.168.10.1: ICMP echo reply, id 15, seq 3, length 64
23:15:26.924762 IP 192.168.10.1 > 192.168.11.1: ICMP echo request, id 15, seq 4, length 64
23:15:26.925815 IP 192.168.11.1 > 192.168.10.1: ICMP echo reply, id 15, seq 4, length 64
La commande traceroute permet de savoir le chemin emprunté pour joindre la machine distante :
# sur debianA
traceroute 192.168.11.1
On voit clairement que le paquet est d’abord passé par la machine X, avant de joindre la machine B :
pascal@debianA:~$ traceroute 192.168.11.1
traceroute to 192.168.11.1 (192.168.11.1), 30 hops max, 60 byte packets
1 192.168.10.254 (192.168.10.254) 1.851 ms 1.844 ms 1.831 ms
2 192.168.11.1 (192.168.11.1) 1.759 ms 1.709 ms 1.660 ms
Après avoir contemplé la magie du routage IP (ce mécanisme est le fondement de la majorité des échanges sur Internet), nous ne saurions être pleinement satisfait si les routes statiques que nous avons réalisées n’étaient pas persistantes.
Qu’à cela ne tienne.
Nous allons nous rendre dans le répertoire du système prévu justement pour des scripts qui sont exécutés à chaque fois qu’une interface du réseau est « up » :
cd /etc/network/if-up.d
Et ajoutons un script pour chaque machine (ici la debianA) :
sudo nano route_x
A priori, on l’imagine simplement contenant deux lignes :
#!/usr/bin/env bash
ip route add 192.168.11.0/24 via 192.168.10.254 dev enp0s3
Il ne faut pas oublier de le rendre exécutable :
sudo chmod +x route_x
Après redémarrage de la machine, vous pourrez vous rendre compte que ça ne fonctionne pas très bien… Si, si. La route statique existe, sans doute, mais vous aurez aperçu un petit [FAILED] dans la séquence de démarrage, et le service networking est en réalité HS, voyez par vous-même :
systemctl status networking
En fait, ce script, que l’on voit de-ci de-là comme solution pour une route statique, n’est pas satisfaisant.
D’abord, dans un script, il faut prendre la bonne habitude d’écrire les commandes avec un chemin absolu, et non relatif, comme ici (« ip … »), donc déjà :
#!/usr/bin/env bash
/sbin/ip route add 192.168.11.0/24 via 192.168.10.254 dev enp0s3
D’autre part, les scripts présents dans if-up.d sont lancés pour chaque interface qui passe UP, ainsi qu’une fois supplémentaire quand toutes sont UP. A chaque fois, la variable $IFACE contiendra le nom de l’interface en question (et aura la valeur « –all » pour le dernier cas).
Notre script sera donc plus correct ainsi :
#!/usr/bin/env bash
if [ "$IFACE" = "enp0s3" ] ; then
/sbin/ip route add 192.168.11.0/24 via 192.168.10.254 dev eth0
fi
Relancer les machines, et vérifier que cette fois, tout est fonctionnel, sans erreur, paisible et serein.
Est-ce la seule méthode ?
Il existe (au moins) une autre méthode pour créer cette route statique persistante : au lieu de créer un script dans le répertoire if-up.d, on peut insérer la commande de création de la route directement dans le fichier de configuration des interfaces, grâce à la directive post-up :
Par exemple ici pour la machine A (fichier /etc/network/interfaces):
...
allow-hotplug enp0s3
iface enp0s3 inet static
address 192.168.10.1/24
post-up /sbin/ip route add 192.168.11.0/24 via 192.168.10.254 dev enp0s3
Nous avons donc pu au travers d’une maquette simple expérimenter les fondamentaux du routage avec Linux, utiliser quelques outils iproute2 et aborder quelques point importants.
Allons plus loin maintenant, en créant à partir d'ici une première version du miniLAB avec une miniBox. Rendez-vous ici !