10. Créer des interfaces de type veth

L'introduction d'un nouvel espace de nom réseau revient à introduire une nouvelle table de routage dans un même système. Dans la vue ci-dessous, le cadre vert illustre les éléments ajoutés au routeur R2 : un lien vers un espace de noms baptisé green avec un serveur web hébergé à l'intérieur.

Les manipulations présentées dans cette section doivent aussi être réalisées sur le routeur R3 en suivant le plan d'adressage présenté à la Section 2, « Topologie réseau étudiée ».

Topologie logique avec un espace de noms réseau

Q26.

Comment créer une paire d'interfaces réseau virtuelles de type veth sur un système GNU/Linux ?

Rechercher dans les pages de manuels la commande ip link la syntaxe qui permet de créer la paire d'interfaces veth0 et veth1.

# ip link add veth1 type veth peer name veth0

# ip link ls dev veth0
4: veth0@veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN \
                                mode DEFAULT group default qlen 1000
    link/ether be:04:25:e8:cc:49 brd ff:ff:ff:ff:ff:ff

# ip link ls dev veth1
5: veth1@veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN \
                                mode DEFAULT group default qlen 1000
    link/ether c2:05:0c:82:35:77 brd ff:ff:ff:ff:ff:ff

Q27.

Comment créer un nouvel espace de noms réseau appelé green et affecter l'interface veth1 à cet espace de noms ?

Rechercher dans les pages de manuels ip-netns la syntaxe qui permet de créer un nouvel espace de noms réseau.

# ip netns add green
# ip netns ls
green

L'affectation d'une interface à l'espace de noms se fait avec la commande suivante.

# ip link set veth1 netns green

Q28.

Comment visualiser et modifier l'état des interfaces de type veth dans les deux espaces de noms réseau ?

Rechercher dans les pages de manuels ip-netns la syntaxe qui permet d'exécuter une commande dans un nouvel espace de noms réseau.

On active les deux interfaces et on affiche les informations d'état.

# ip link set dev veth0 up

# ip link ls dev veth0
4: veth0@if5: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue \
                        state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether d6:63:10:30:b4:da brd ff:ff:ff:ff:ff:ff link-netns green
# ip netns exec green ip link set dev veth1 up

ip netns exec green ip link ls dev veth1
5: veth1@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue \
                        state UP mode DEFAULT group default qlen 1000
    link/ether be:70:c4:17:19:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Q29.

Comment valider les communications entre les deux espaces de noms réseau ?

Utiliser les adresses de lien local IPv6 pour faire un test ICMP avec l'adresse multicast de sollicitation d'hôte.

Le test avec la commande ping doit désigner l'interface du lien à utiliser.

# ping -c2 ff02::1%veth0
PING ff02::1%veth0(ff02::1%veth0) 56 data bytes
64 bytes from fe80::d463:10ff:fe30:b4da%veth0: icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from fe80::bc70:c4ff:fe17:1954%veth0: icmp_seq=1 ttl=64 time=0.149 ms (DUP!)
64 bytes from fe80::d463:10ff:fe30:b4da%veth0: icmp_seq=2 ttl=64 time=0.058 ms

--- ff02::1%veth0 ping statistics ---
2 packets transmitted, 2 received, +1 duplicates, 0% packet loss, time 27ms
rtt min/avg/max/mdev = 0.058/0.089/0.149/0.043 ms

Le voisinage réseau de l'interface veth0 désigne l'adresse MAC de l'interface veth1 dans l'espace de noms réseau green.

# ip nei ls dev veth0
fe80::bc70:c4ff:fe17:1954 lladdr be:70:c4:17:19:54 STALE

Réciproquement, le voisinage réseau de l'interface veth1 désigne l'adresse MAC de l'interface veth0.

$ ip netns exec green ip nei ls dev veth1
fe80::d463:10ff:fe30:b4da lladdr d6:63:10:30:b4:da router STALE

On peut donc conclure que le lien point à point entre les deux espaces de noms réseau est fonctionnel.

Q30.

Comment ajouter deux préfixes réseau IPv4 et IPv6 sur la liaison point à point entre les deux interfaces de type veth ?

Comme lors des étapes précédentes, on reprend les commandes ip avec la désignation de l'espace de noms réseau pour l'interface à l'extrémité du lien point à point.

Dans notre exemple sur le routeur R2, on utilise les préfixes 10.1.2.0/30 et 2001:678:3fc:e::/64.

  • Pour l'interface veth0 :

    # ip addr add 10.1.2.1/30 brd + dev veth0
    # ip -6 addr add 2001:678:3fc:e::1/64 dev veth0
  • Pour l'interface veth1 :

    # ip netns exec green ip addr add 10.1.2.2/30 brd + dev veth1
    # ip netns exec green ip -6 addr add 2001:678:3fc:e::2/64 dev veth1

Comme dans la question précédente, on peut qualifier la communication entre les deux interfaces au niveau réseau à l'aide de la commande ping.

Voici une copie d'écran des tests effectués depuis l'espace de noms green.

# ip netns exec green ping -qc2 10.1.2.1
PING 10.1.2.1 (10.1.2.1) 56(84) bytes of data.

--- 10.1.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 18ms
rtt min/avg/max/mdev = 0.049/0.079/0.110/0.031 ms

# ip netns exec green ping -qc2 2001:678:3fc:e::1
PING 2001:678:3fc:e::1(2001:678:3fc:e::1) 56 data bytes

--- 2001:678:3fc:e::1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 18ms
rtt min/avg/max/mdev = 0.070/0.112/0.155/0.043 ms

Q31.

Comment publier les deux préfixes réseau correspondant à la nouvelle liaison point à point via OSPF ?

Il faut activer l'interface veth dans la configuration des deux démons de routage OSPF : bird et bird6.

Il faut consulter la section OSPF du guide BIRD User's Guide. Les instructions utiles pour cette question sont les suivantes.

interface
stub

La partie OSPFv2 du fichier de configuration sur R2 devient :

R2:~# sed -n '/protocol ospf OSPFv2R2 {/,/^}/p' /etc/bird/bird.conf
protocol ospf OSPFv2R2 {
        rfc1583compat yes;
        ecmp yes;
        area 0 {
                interface "eth0.12", "eth0.23" {
                        authentication none;
                };
                interface "veth0" {
                        stub yes;
                };
        };
}

Les mêmes instrcutions sont placées dans le fichier de configuration du protocole OSPFv3.

R2:~# sed -n '/protocol ospf OSPFv3R2 {/,/^}/p' /etc/bird/bird6.conf
protocol ospf OSPFv3R2 {
        ecmp yes;
        area 0 {
                interface "eth0.12", "eth0.23" {
                        authentication none;
                };
                interface "veth0" {
                        stub yes;
                };
        };
}

On vérifie ensuite que les entrées sont bien intégrées dans les routes OSPF des deux démons.

R2:~# birdc show route 10.1.2.0/30
BIRD 1.6.4 ready.
10.1.2.0/30        dev veth0 [OSPFv2R2 13:49:32] * I (150/10) [0.0.2.4]
R2:~# birdc6 show route 2001:678:3fc:e::/64
BIRD 1.6.4 ready.
2001:678:3fc:e::/64 dev veth0 [OSPFv3R2 13:50:01] * I (150/10) [0.0.2.6]

Q32.

Est-ce que les adresses IPv4 et IPv6 situées dans l'espace de noms green joiganbles depuis les réseaux distants ?

Le fait d'avoir placé l'interface veth1 dans un espace de noms réseau distinct, impose l'utilisation d'une table de routage propre à cet espace. Sur la base des opérations déjà effectuées, on s'interroge sur le fait que ces opérations suffisent pour que les communications soient fonctionnelles.

On fait des tests ICMP et ICMP6 depuis un autre routeur pour constater que si les flux parviennent bien à destination, il n'existe pas de solution retour.

Dans l'exemple ci-dessous, on teste les communications entre le routeur R1 et l'interface veth1 située au delà du routeur R2

On lance une requête ICMP depuis R1.

R1:~# ping -c3 10.1.2.2
PING 10.1.2.2 (10.1.2.2) 56(84) bytes of data.

--- 10.1.2.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 56ms

On lance l'analyse réseau dans l'espace de noms réseau green.

R2:~# ip netns exec green /usr/bin/tshark -i veth1 -f icmp
<snipped/>
Capturing on 'veth1'
    1 0.000000000    10.1.12.1 → 10.1.2.2     ICMP 98 Echo (ping) request  id=0x63c9, seq=1/256, ttl=63
    2 1.026937745    10.1.12.1 → 10.1.2.2     ICMP 98 Echo (ping) request  id=0x63c9, seq=2/512, ttl=63
    3 2.050936173    10.1.12.1 → 10.1.2.2     ICMP 98 Echo (ping) request  id=0x63c9, seq=3/768, ttl=63

On relève bien l'arrivée des requêtes à destination. Il n'y a aucune réponse à ces requêtes.

En reprenant le même test avec ICMP6, on relève le même problème.

R1:~# ping -c3 2001:678:3fc:e::2
PING 2001:678:3fc:e::2(2001:678:3fc:e::2) 56 data bytes

--- 2001:678:3fc:e::2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 47ms

L'analyse réseau ne montre que l'arrivée des requêtes à destination.

R2:~# ip netns exec green /usr/bin/tshark -i veth1 -f icmp6
<snipped/>
Capturing on 'veth1'
    1 0.000000000 2001:678:3fc:c::1 → 2001:678:3fc:e::2 ICMPv6 118 Echo (ping) request id=0x63d0, seq=1, hop limit=63
    2 1.004989685 2001:678:3fc:c::1 → 2001:678:3fc:e::2 ICMPv6 118 Echo (ping) request id=0x63d0, seq=2, hop limit=63
    3 2.032992497 2001:678:3fc:c::1 → 2001:678:3fc:e::2 ICMPv6 118 Echo (ping) request id=0x63d0, seq=3, hop limit=63

Q33.

Comment compléter les tables de routage IPv4 et IPv6 situées dans l'espace de noms green pour que le trafic initié depuis cet espace soit émis correctement ?

On complète les tables de routage avec une route par défaut pour joindre les réseaux distants depuis l'espace de noms green.

La lecture des tables de routage dans l'espace de noms réseau green explique tout. Ces tables ne contiennent que l'entrée relative au lien point à point configuré entre les interfaces veth0 et veth1.

R2:~# ip netns exec green ip route ls
10.1.2.0/30 dev veth1 proto kernel scope link src 10.1.2.2

R2:~# ip netns exec green ip -6 route ls
2001:678:3fc:e::/64 dev veth1 proto kernel metric 256 pref medium
fe80::/64 dev veth1 proto kernel metric 256 pref medium

Il faut donc compléter ces tables de routage avec une route par défaut vers l'espace de noms réseau par défaut dans lequel est située l'interface veth0.

R2:~# ip netns exec green ip route add default via 10.1.2.1

R2:~# ip netns exec green ping -c1 ff02::2%veth1
PING ff02::2%veth1(ff02::2%veth1) 56 data bytes
64 bytes from fe80::d463:10ff:fe30:b4da%veth1: icmp_seq=1 ttl=64 time=0.099 ms

--- ff02::2%veth1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.099/0.099/0.099/0.000 ms

R2:~# ip netns exec green ip -6 route add default via fe80::d463:10ff:fe30:b4da dev veth1

Les nouvelles tables de routage de l'espace de noms green font apparaître les routes par défaut

R2:~# ip netns exec green ip route ls
default via 10.1.2.1 dev veth1
10.1.2.0/30 dev veth1 proto kernel scope link src 10.1.2.2
R2:~# ip netns exec green ip -6 route ls
2001:678:3fc:e::/64 dev veth1 proto kernel metric 256 pref medium
fe80::/64 dev veth1 proto kernel metric 256 pref medium
default via fe80::d463:10ff:fe30:b4da dev veth1 metric 1024 pref medium

Les tests ICMP et ICMP6 de la question précédente montrent maintenant que les communications sont bien fonctionnelles. Les requêtes sont à nouveau émises depuis le routeur R1

R1:~# ping -qc3 10.1.2.2
PING 10.1.2.2 (10.1.2.2) 56(84) bytes of data.

--- 10.1.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 40ms
rtt min/avg/max/mdev = 0.085/0.220/0.490/0.190 ms
R1:~# ping -qc3 2001:678:3fc:e::2
PING 2001:678:3fc:e::2(2001:678:3fc:e::2) 56 data bytes

--- 2001:678:3fc:e::2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 55ms
rtt min/avg/max/mdev = 0.089/0.319/0.778/0.324 ms

Q34.

Comment installer un service Web en écoute exclusivement sur les adresses IPv4 et IPv6 situées dans l'espace de noms réseau green ?

Pour aller au plus court, on installe le paquet lighttpd et on édite la configuration du service de façon à limiter l'accès aux adresses IP voulues.

R2:~# aptitude install lighttpd

On modifie ensuite le fichier de configuration /etc/lighttpd/lighttpd.conf de façon à limiter l'accès aux adresses IPv4 et IPv6 de l'interface veth1.

Voici une copie du correctif correspondant au routeur R2.

--- /etc/lighttpd/lighttpd.conf.orig    2018-11-04 14:29:00.700077032 +0000
+++ /etc/lighttpd/lighttpd.conf 2018-11-04 14:29:38.568699677 +0000
@@ -22,6 +22,9 @@
 compress.filetype           = ( "application/javascript", "text/css", "text/html", "text/plain" )

 # default listening port for IPv6 falls back to the IPv4 port
-include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
+#include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
 include_shell "/usr/share/lighttpd/create-mime.assign.pl"
 include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
+
+server.bind = "10.1.2.2"
+$SERVER["socket"] == "[2001:678:3fc:e::2]:80" { server.use-ipv6 = "enable" }

Relativement à une configuration classique, il faut lancer le serveur Web dans le contexte du nouvel espace de noms réseau. On commence donc par arrêter le démon lancé lors de l'installation du paquet.

R2:~# systemctl stop lighttpd

Là encore, pour aller au plus court on lance directement le démon dans le contexte de l'espace de noms réseau green.

R2:~# ip netns exec green lighttpd -f /etc/lighttpd/lighttpd.conf

R2:~# ip netns exec green ss -nlt '( src :80 )'
State       Recv-Q Send-Q        Local Address:Port    Peer Address:Port
LISTEN      0      128                10.1.2.2:80           0.0.0.0:*
LISTEN      0      128     [2001:678:3fc:e::2]:80              [::]:*

Q35.

Comment valider l'accès au service Web situé dans l'espace de noms réseau green depuis un réseau distant ?

Comme la partie routage a été validée dans les questions précédentes, on passe directement à la couche application avec le chargement de la page Web par défaut du serveur.

Depuis le routeur R1, on obtient le résultat suivant :

R1:~# wget -O /dev/null http://10.1.2.2
--2018-11-04 14:34:37--  http://10.1.2.2/
Connexion à 10.1.2.2:80… connecté.
requête HTTP transmise, en attente de la réponse… 200 OK
Taille : 3378 (3,3K) [text/html]
Sauvegarde en : « /dev/null »

/dev/null  100%[=========================>]   3,30K  --.-KB/s    ds 0s

2018-11-04 14:34:37 (116 MB/s) — « /dev/null » sauvegardé [3378/3378]
R1:~# wget -O /dev/null http://[2001:678:3fc:e::2]
--2018-11-04 14:35:45--  http://[2001:678:3fc:e::2]/
Connexion à [2001:678:3fc:e::2]:80… connecté.
requête HTTP transmise, en attente de la réponse… 200 OK
Taille : 3378 (3,3K) [text/html]
Sauvegarde en : « /dev/null »

/dev/null  100%[==========================>]   3,30K  --.-KB/s    ds 0s

2018-11-04 14:35:45 (16,8 MB/s) — « /dev/null » sauvegardé [3378/3378]