Je n'ai pas trouvé jusqu'à présent d'exemple simple comme celui-ci pour comprendre les bases avec référence aux sources. Il s'agit plutôt d'une démonstration du concept, mais cela m'a demandé un certain effort. Je vais donc le partager avec la communauté, étape par étape.
Préparations
J'utilise trois machines virtuelles sur KVM (Kernel-based Virtual Machine), toutes avec Debian 11 (bullseye, pour l'instant version de test) et utilisant la terminologie de RFC 2460 :
Nœud est une interface activée pour IPv6.
Routeur est tout nœud qui transmet des paquets IPv6 qui ne lui sont pas expressément adressés.
Hôte est tout nœud qui n'est pas un routeur.
Nous avons besoin de quelques programmes d'aide qui doivent être installés tant que nous avons un accès Internet sur les nœuds avant de reconfigurer leurs interfaces réseau pour les tests. Sur tous les nœuds, installez radvdump
et sur le routeur, installez radvd
. Veillez à ce que radvd
est désactivé, sinon cela perturbera les tests. Je vais utiliser tcpdump
pour voir ce qui se passe sur le réseau, alors installez-le sur le routeur. Sous Debian, je fais tout cela avec :
~$ sudo apt install radvdump # on hosts and router
router ~$ sudo apt install radvd # only on the router
router ~$ sudo systemctl disable --now radvd.service
router ~$ sudo apt install tcpdump # only on the router
J'utilise le préfixe d'adresse IPv6 2001:DB8::/32 Réservé à la documentation ( RFC 3849 ) qui est utilisable pour des adresses unicast globales valides mais qui n'est pas routé vers l'internet.
Pour avoir les choses à la main, voici quelques spécifications :
Certains types d'adresses sont utilisés ( RFC 4291 )
Unspecified ::/128
Loopback ::1/128
default route ::/0
Multicast FF00::/8
Unique Local unicast FD00::/8
Global Unicast (everything else)
Global Anycast (same as Global Unicast) not used in this example
Portée des adresses Multicast ( RFC 4291 ):
FF00:: reserved
FF01:: Interface-Local scope
FF02:: Link-Local scope
FF03:: reserved
FF04:: Admin-Local scope
FF05:: Site-Local scope
FF06:: to FF07:: (unassigned)
FF08:: Organization-Local scope
FF09:: to FF0D:: (unassigned)
FF0E:: Global scope
FF0F:: reserved
Adresses multicast IPv6 bien connues (extrait - liste complète à l'adresse suivante IANA ):
ff02::1 all nodes
ff02::2 all routers
ff02::5 all OSPF (Open Shortest Path First) routers
ff02::6 all OSPF DRs (OSPF Designated Routers)
ff02::9 all RIP (Routing Information Protocol) routers
ff02::a all EIGRP (Enhanced Interior Gateway Routing Protocol) routers
ff02::c SSDP (Simple Service Discovery Protocol)
ff02::d all PIM (Protocol Independent Multicast) routers
ff02::f UPNP (Universal Plug and Play) devices
ff02::11 all homenet nodes
ff02::12 VRRP (Virtual Router Redundancy Protocol)
ff02::16 all MLDv2-capable routers
ff02::1a all RPL (Routing Protocol for Low-Power and Lossy Networks) routers (used in Internet of Things (IoT) devices)
ff02::fb multicast DNS IPv6
ff02::101 network time (NTP)
ff02::1:2 all DHCP agents
ff02::1:3 LLMNR (Link-Local Multicast Name Resolution)
ff02:0:0:0:0:1:ff00::/104 solicited node address
ff02:0:0:0:0:1-2:ff00::/104 node information query
ff05::1:3 all DHCP server (site)
ff05::101 all NTP server (site)
Activer systemd-networkd en suivant
Section Quick Step à l'adresse Utiliser systemd-networkd pour la mise en réseau générale puis reviens ici.
Je vais tout désactiver pour que nous puissions voir ce qui est nécessaire et l'activer étape par étape. Sur host-a
et host-b
utiliser ce fichier réseau :
host-? ~$ sudo -Es # if not already done
host-? ~# cat > /etc/systemd/network/04-wired.network <<EOF
[Match]
Name=eth0
[Network]
# on host-a uncomment
#Address=2001:db8:0:10::2/64
# on host-b uncomment
#Address=2001:db8:0:20::2/64
IPv6AcceptRA=no
LinkLocalAddressing=no
EOF
Sur le routeur, utilisez ceux-là :
router ~$ sudo -Es # if not already done
router ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Address=2001:db8:0:10::1/64
IPv6AcceptRA=no
LinkLocalAddressing=no
EOF
router ~# cat > /etc/systemd/network/06-eth1.network <<EOF
[Match]
Name=eth1
[Network]
Address=2001:db8:0:20::1/64
IPv6AcceptRA=no
LinkLocalAddressing=no
EOF
Connexion simple de type lien-local
Je vais d'abord examiner la connexion directe entre host-a
et le router
. Le routeur est UP et je démarre host-a
. tcpdump
me montre sur le sous-réseau 2001:db8:0:10/64 :
host-a ~$ sudo tcpdump -n --number --interface=eth0 ip6 2>/dev/null
1 23:25:28.211331 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
2 23:25:28.227326 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 2 group record(s), length 48
3 23:25:28.671386 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
4 23:25:28.735354 IP6 :: > ff02::1:ff00:2: ICMP6, neighbor solicitation, who has 2001:db8:0:10::2, length 32
- Avec le paquet 1-3
host-a
se joint en tant qu'auditeur au groupe multicast ff02::16
- tous les routeurs compatibles avec MLDv2. Le routeur sait maintenant qu'il veut recevoir des messages de routage.
- Avec le paquet 4, il a demandé s'il y avait un autre nœud avec l'adresse IP 2001:db8:0:10::2. Ce n'est pas le cas car il n'y a pas de réponse.
host-a
peut utiliser l'adresse.
Ping vers router
travaux :
host-a ~$ ping6 -n 2001:db8:0:10::1
PING 2001:db8:0:10::1(2001:db8:0:10::1) 56 data bytes
64 bytes from 2001:db8:0:10::1: icmp_seq=1 ttl=64 time=0.829 ms
64 bytes from 2001:db8:0:10::1: icmp_seq=2 ttl=64 time=0.863 ms
64 bytes from 2001:db8:0:10::1: icmp_seq=3 ttl=64 time=0.858 ms
--- snip ---
Adresses unicast Link-local
Dans l'étape suivante, je veux me connecter à la deuxième interface. eth1 sur router
. Pour cela, nous avons besoin d'une route statique :
host-a ~$ sudo ip -6 route add 2001:db8:0:20::/64 via 2001:db8:0:10::1
Mais ping6 -n 2001:db8:0:20::1
ne fonctionne pas de manière stable :
host-a ~$ ping6 -n 2001:db8:0:20::1
PING 2001:db8:0:20::1(2001:db8:0:20::1) 56 data bytes
64 bytes from 2001:db8:0:20::1: icmp_seq=1 ttl=64 time=0.881 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=2 ttl=64 time=0.784 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=3 ttl=64 time=0.898 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=4 ttl=64 time=0.799 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=5 ttl=64 time=0.805 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=6 ttl=64 time=1.13 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=7 ttl=64 time=0.795 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=8 ttl=64 time=0.790 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=9 ttl=64 time=0.793 ms
^^^^^^^^^^
64 bytes from 2001:db8:0:20::1: icmp_seq=55 ttl=64 time=1025 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=56 ttl=64 time=3.26 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=57 ttl=64 time=0.793 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=58 ttl=64 time=0.792 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=59 ttl=64 time=0.789 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=60 ttl=64 time=0.776 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=61 ttl=64 time=0.803 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=62 ttl=64 time=0.801 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=63 ttl=64 time=0.774 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=64 ttl=64 time=0.802 ms
^^^^^^^^^^^
64 bytes from 2001:db8:0:20::1: icmp_seq=110 ttl=64 time=2049 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=111 ttl=64 time=1025 ms
--- snip ---
^C
--- 2001:db8:0:20::1 ping statistics ---
170 packets transmitted, 35 received, 79.4118% packet loss, time 172432ms
rtt min/avg/max/mdev = 0.774/205.826/2048.843/536.218 ms, pipe 3
Si vous suivez le seq
vous verrez qu'avec un délai de ping de 1 sec, il est interrompu après environ 10 sec et répété après environ 45 sec avec une perte de paquets d'environ 80%. Cela ne peut pas être appelé stable. Je ne le comprends pas vraiment mais il est bon de connaître ce comportement lorsqu'on cherche à résoudre un problème. Quoi qu'il en soit, c'est en dehors des spécifications car pour les connexions sur le lien (2001:db8:0:10:2 à 2001:db8:0:10:1), il doit être utilisé adresses locales de liaison comme spécifié dans RFC 4291 - Adresses Link-Local IPv6 Unicast :
Les adresses Link-Local sont conçues pour être utilisées pour l'adressage sur un seul lien à des fins telles que la configuration automatique des adresses, la découverte des voisins ou lorsqu'aucun routeur n'est présent.
Vérifiez l'existence d'une adresse locale de liaison sur l'interface. Il n'y en a pas :
host-a ~$ ip -6 -br addr
lo UNKNOWN ::1/128
eth0 UP 2001:db8:0:10::2/64
Je l'active avec le paramètre LinkLocalAddressing=ipv6
en tout /etc/systemd/network/*.network
sur tous les noeuds, redémarrez, vérifiez et faites un ping :
host-a ~$ ip -6 -br addr
lo UNKNOWN ::1/128
eth0 UP 2001:db8:0:10::2/64 fe80::5054:ff:febc:adbe/64
router ~$ ip -6 -br addr
lo UNKNOWN ::1/128
eth0 UP 2001:db8:0:10::1/64 fe80::5054:ff:fe0f:194e/64
eth1 UP 2001:db8:0:20::1/64 fe80::5054:ff:fe0f:194e/64
host-b ~$ ip -6 -br addr
lo UNKNOWN ::1/128
eth0 UP 2001:db8:0:20::2/64 fe80::5054:ff:fe9b:34b9/64
host-a ~$ sudo ip -6 route add 2001:db8:0:20::/64 via 2001:db8:0:10::1
host-a ~$ ping6 -n 2001:db8:0:20::1
PING 2001:db8:0:20::1(2001:db8:0:20::1) 56 data bytes
64 bytes from 2001:db8:0:20::1: icmp_seq=9 ttl=64 time=2.08 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=10 ttl=64 time=0.780 ms
64 bytes from 2001:db8:0:20::1: icmp_seq=11 ttl=64 time=0.783 ms
--- snip ---
Travaux.
Routage statique
Si j'essaie de me connecter depuis host-a
a host-b
puis ping6 -n 2001:db8:0:20::2
échoue. Cela est dû au fait que le router
ne transmet pas les paquets entre ses interfaces. Nous devons l'activer. Il suffit d'ajouter IPForward=ipv6
à un *.network
dossier. Nous avons également besoin d'une route statique sur host-b
pour qu'il sache où envoyer les réponses host-a
. Nous allons le faire de manière persistante maintenant. Vous obtiendrez donc ce qui suit .network
des fichiers :
hôte-a
host-a ~$ cat /etc/systemd/network/04-wired.network
[Match]
Name=eth0
[Network]
Address=2001:db8:0:10::2/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
[Route]
Destination=2001:db8:0:20::/64
Gateway=2001:db8:0:10::1
routeur
router ~$ cat /etc/systemd/network/04-eth0.network
[Match]
Name=eth0
[Network]
Address=2001:0DB8:0:10::1/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
IPForward=ipv6
router ~$ cat /etc/systemd/network/06-eth1.network
[Match]
Name=eth1
[Network]
Address=2001:0DB8:0:20::1/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
IPForward=ipv6
hôte-b
host-b ~$ cat /etc/systemd/network/04-wired.network
[Match]
Name=eth0
[Network]
Address=2001:db8:0:20::2/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
[Route]
Destination=2001:db8:0:10::/64
Gateway=2001:db8:0:20::1
Annonce de routeur
Le routage statique n'est pas très confortable. Il se fait généralement de manière automatique. Un hôte peut demander à un routeur sa configuration. Pour le supporter, vous devez activer IPv6AcceptRA=yes
dans son /etc/systemd/*.network
fichier. Si vous le faites, vous trouverez avec tcpdump
au démarrage d'un hôte :
host-a ~$ sudo tcpdump -n --number --interface=eth0 ip6 2>/dev/null
1 18:06:20.965014 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
2 18:06:20.976965 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 2 group record(s), length 48
4 18:06:21.701148 IP6 :: > ff02::1:ffbc:adbe: ICMP6, neighbor solicitation, who has fe80::5054:ff:febc:adbe, length 32
5 18:06:21.861153 IP6 :: > ff02::1:ff00:2: ICMP6, neighbor solicitation, who has 2001:db8:0:10::2, length 32
7 18:06:22.725190 IP6 fe80::5054:ff:febc:adbe > ff02::16: HBH ICMP6, multicast listener report v2, 3 group record(s), length 68
9 18:06:24.225649 IP6 fe80::5054:ff:febc:adbe > ff02::2: ICMP6, router solicitation, length 16
10 18:06:27.851217 IP6 fe80::5054:ff:febc:adbe > ff02::2: ICMP6, router solicitation, length 16
11 18:06:35.087287 IP6 fe80::5054:ff:febc:adbe > ff02::2: ICMP6, router solicitation, length 16
--- snip ---
En plus des paquets déjà connus multicast listener report v2
et neighbor solicitation
nous trouvons router solicitation
paquets. Avec ce message, l'hôte demande au routeur la configuration d'une interface. Mais le router
ne répond pas, donc l'hôte continue à demander. Sous Linux, un routeur IPv6 ne répond pas d'emblée aux sollicitations du routeur. Il a besoin d'un service supplémentaire radvd
pour gérer cela. Nous l'avons déjà installé mais désactivé. En utilisant l'exemple simple de Debian /usr/share/doc/radvd/examples/simple-radvd.conf
nous allons maintenant le configurer et l'activer :
router ~$ sudo -Es # if not already done
router ~# cat > /etc/radvd.conf <<EOF
interface eth0
{
AdvSendAdvert on;
prefix 2001:db8:0:10::/64
{
};
};
interface eth1
{
AdvSendAdvert on;
prefix 2001:db8:0:20::/64
{
};
};
EOF
~# systemctl enable radvd.service
Puisque nous nous attendons à ce que les hôtes obtiennent leur configuration du routeur, nous devons supprimer les paramètres manuels de sa configuration. .network
fichiers. Ils devraient ressembler à ce qui suit :
hôte-a et hôte-b :
host-? ~$ cat /etc/systemd/network/04-eth0.network
[Match]
Name=eth0
[Network]
IPv6AcceptRA=yes
LinkLocalAddressing=ipv6
routeur :
router ~$ cat /etc/systemd/network/04-eth0.network
[Match]
Name=eth0
[Network]
Address=2001:db8:0:10::1/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
IPForward=ipv6
router ~$ cat /etc/systemd/network/06-eth1.network
[Match]
Name=eth1
[Network]
Address=2001:db8:0:20::1/64
IPv6AcceptRA=no
LinkLocalAddressing=ipv6
IPForward=ipv6
Redémarrez tous les nœuds et vous devriez avoir un réseau simple autoconfiguré et fonctionnel.
Simplifications
Pour montrer ce qui est nécessaire, j'ai explicitement écrit les options dans les fichiers de configuration du réseau. Mais la plupart d'entre elles sont des paramètres par défaut, donc nous pouvons simplement les omettre.
hôte-a et hôte-b :
host-? ~$ cat /etc/systemd/network/04-eth0.network
[Match]
Name=eth0
routeur :
router ~$ cat /etc/systemd/network/04-eth0.network
[Match]
Name=eth0
[Network]
Address=2001:db8:0:10::1/64
IPForward=ipv6
router ~$ cat /etc/systemd/network/06-eth1.network
[Match]
Name=eth1
[Network]
Address=2001:db8:0:20::1/64
IPForward=ipv6
Déboguer
Vous devrez peut-être vérifier si l'hôte reçoit les paramètres corrects du routeur, ou s'il existe un routeur, par exemple de votre fournisseur d'accès à Internet, dont vous devez connaître les paramètres exacts qu'il envoie. Ensuite, vous pouvez commencer radvdump
pour visualiser l'annonce de routeur reçue. Si vous le démarrez, attendez un peu jusqu'à ce qu'un Router Advertisement soit reçu. C'est ici avec les paramètres par défaut de router
:
host-a ~$ sudo radvdump
#
# radvd configuration generated by radvdump 2.18
# based on Router Advertisement from fe80::5054:ff:fe0f:194e
# received by interface eth0
#
interface eth0
{
AdvSendAdvert on;
# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump
AdvManagedFlag off;
AdvOtherConfigFlag off;
AdvReachableTime 0;
AdvRetransTimer 0;
AdvCurHopLimit 64;
AdvDefaultLifetime 1800;
AdvHomeAgentFlag off;
AdvDefaultPreference medium;
AdvSourceLLAddress on;
prefix 2001:db8:0:10::/64
{
AdvValidLifetime 86400;
AdvPreferredLifetime 14400;
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
}; # End of prefix definition
}; # End of interface definition
Résolution du nom
La résolution de noms sur l'ensemble du réseau n'est possible qu'avec un serveur DNS. Sa mise en place est une nouvelle question qui sort du cadre de cet article. Le fait de ne pas avoir de serveur DNS disponible sur ce réseau simple est également la raison pour laquelle nous utilisons toujours ping6 avec l'option -n
qui supprime l'interrogation d'un serveur DNS pour traduire l'adresse IP. Sans -n
ping6 essaie de se connecter à un serveur DNS pour chaque demande avec un délai d'attente. Cela ralentit considérablement le ping et n'est pas utilisable.
Pour le lien local, il n'y a aucun problème à activer le DNS multicast ( mDNS ) afin de disposer d'une résolution de nom pour les nœuds directement connectés. Il suffit d'ajouter l'option
MulticastDNS=yes
au [Network]
section sur chaque nœud /etc/systemd/network/*.network
fichier. Vous devriez alors être en mesure de
host-a ~$ ping6 -n router.local
PING router.local(fe80::5054:ff:fe0f:194e%eth0) 56 data bytes
64 bytes from fe80::5054:ff:fe0f:194e%eth0: icmp_seq=1 ttl=64 time=2.37 ms
64 bytes from fe80::5054:ff:fe0f:194e%eth0: icmp_seq=2 ttl=64 time=0.799 ms
64 bytes from fe80::5054:ff:fe0f:194e%eth0: icmp_seq=3 ttl=64 time=0.823 ms
--- snip ---
Mais ping6 -n host-b.local
ne fonctionnera pas à partir de host-a
parce que mDNS n'est pas routable.
Références :