Quand vous ajoutez un préfixe IPv6 à un tunnel site à site, le paquet ne voyage pas comme le suggère le schéma. La passerelle locale prend le paquet IPv6 entier, le chiffre et place devant lui un en-tête IP externe dont la famille d’adresses est décidée par les adresses des extrémités, pas par ce qui se trouve à l’intérieur. La passerelle distante retire cet en-tête externe et transmet le paquet d’origine sur son LAN, où il redevient un paquet IPv6 ordinaire. Tunnel externe et trafic interne sont deux conversations distinctes qui partagent une clé, une paire d’extrémités et rien d’autre.

Deux en-têtes, deux familles d’adresses

En mode tunnel IPsec, le paquet IPv6 interne devient la charge utile derrière un en-tête ESP. L’en-tête externe qui transporte ce paquet ESP peut être IPv4 ou IPv6, et il suit local_addrs et remote_addrs. WireGuard fait de même avec moins de cérémonie : le paquet interne est la charge utile d’un datagramme UDP vers l’extrémité du pair. Les deux laissent l’en-tête interne intact, ce qui explique pourquoi le côté distant peut l’acheminer après décapsulation.

Le chemin entre les sites ne voit que l’UDP 4500 quand IPsec utilise la traversée NAT, ou l’UDP 51820 pour un écouteur WireGuard par défaut. Chaque routeur sur le trajet peut être IPv4 uniquement et le trafic IPv6 traverse quand même, parce qu’il n’apparaît jamais comme paquet IPv6 sur ce chemin. Cela donne une première séparation nette : tcpdump -ni eth0 udp port 51820 montre le chemin chiffré, tcpdump -ni wg0 ip6 montre le trafic interne. Une capture externe chargée avec une capture interne silencieuse signifie que le noyau ne place pas d’IPv6 dans le tunnel ; c’est du routage ou de la politique, pas un état de lien.

La passerelle décrémente aussi la limite de sauts interne en transmettant, de sorte que les extrémités comptent comme des routeurs sur le chemin IPv6. Le nombre de sauts externe et la limite de sauts interne évoluent indépendamment, et un paquet qui meurt à la passerelle distante est mort en transmission, pas en chiffrement.

Les sélecteurs et AllowedIPs sont la liste des autorisations

IKEv2 négocie quels préfixes internes une SA enfant peut transporter. Sur strongSwan 5.9 et ultérieur, les écrire explicitement dans swanctl.conf ressemble à ceci :

children {
  net6 {
    local_ts  = 2001:db8:aa::/48
    remote_ts = 2001:db8:bb::/48
    mode = tunnel
    esp_proposals = aes256gcm16-prfsha384-ecp384
    start_action = trap
  }
}

Omettre local_ts et remote_ts et strongSwan les dérive des sous-réseaux de l’interface qu’il sélectionne. Sur un hôte double pile, ce raccourci produit souvent une paire IPv4 uniquement : la SA monte et IPv6 est refusé avant d’atteindre le code ESP. Écrire les deux préfixes rend la SA apte à les transporter, et start_action = trap la fait monter sur le premier paquet correspondant.

WireGuard a une seule liste qui remplit deux fonctions. Dans le bloc pair, AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48 est à la fois la route installée à l’envoi et le filtre appliqué à la réception : un paquet déchiffré dont la source interne tombe hors de cette liste est abandonné silencieusement. wg-quick ajoute une route par entrée, donc le bloc pair ci-dessous n’a pas besoin d’une commande ip -6 route séparée.

[Interface]
Address = 2001:db8:aa:ff::1/64, fd00:aa:ff::1/64
ListenPort = 51820

[Peer]
PublicKey = <site-b-public-key>
Endpoint = 203.0.113.20:51820
AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48

Les deux listes doivent être symétriques : le site B accepte le préfixe du site A comme sélecteur distant et l’achemine en retour, et le tunnel ne fonctionne que si les deux directions s’accordent. Une liste asymétrique donne le symptôme qui coûte le plus de temps — une poignée de main saine, des compteurs qui avancent d’un côté, et un ping de A vers B qui réussit alors que rien de B n’atteint A.

Transfert, routes et préfixe de retour

Linux ne transmet pas IPv6 avant que vous ne l’autorisiez, et le réglage est par espace de noms et non par interface :

sysctl -w net.ipv6.conf.all.forwarding=1
ip -6 route add 2001:db8:bb::/48 dev wg0
ip -6 route get 2001:db8:bb::10 from 2001:db8:aa::10

La deuxième ligne est celle que l’on oublie dans les conceptions basées sur les routes. IPsec en mode politique installe une politique XFRM qui correspond aux préfixes, mais une installation basée sur les routes avec vti6 ou WireGuard a besoin d’une véritable route IPv6 pointant vers ce périphérique. Persistez le sysctl sous /etc/sysctl.d/ ; un redémarrage remet sinon silencieusement le transfert à désactivé.

Le transfert a un effet secondaire qu’il vaut la peine de connaître : le noyau ignore alors les annonces de routeur sauf si net.ipv6.conf.<wan>.accept_ra vaut 2, de sorte qu’une passerelle dont l’adresse WAN arrive par SLAAC peut perdre sa route par défaut au moment où vous activez le transfert. Réglez accept_ra = 2 sur cette interface dans le même fichier et la route survit. Le cœur du site B doit aussi apprendre 2001:db8:aa::/48 depuis la passerelle du tunnel, par route statique ou par un protocole de routage sur le tunnel, sinon la réponse meurt à l’intérieur du réseau de B.

Une vérification en quatre étapes qui localise la panne

Travaillez dans cet ordre et arrêtez-vous à la première étape qui échoue, car chaque étape suivante dépend des précédentes.

  1. Sélecteurs : swanctl --list-sas doit montrer la paire de préfixes IPv6 sur la SA enfant, ou wg show wg0 allowed-ips le préfixe distant avec un latest-handshakes récent.
  2. Route du noyau : ip -6 route get 2001:db8:bb::10 doit répondre avec le périphérique du tunnel, pas avec l’interface WAN.
  3. Capture interne : tcpdump -ni wg0 ip6 pendant que vous pinguez entre de vrais hôtes du LAN. Des paquets qui sortent mais aucun qui revient pointent vers la route ou le pare-feu de B ; aucun paquet du tout renvoie aux étapes 1 ou 2.
  4. Destination : sur l’hôte B, ss -6 -ltn confirme que le service écoute en IPv6, et les compteurs locaux du pare-feu montrent si le paquet a été accepté ou supprimé.

La MTU fait partie de la même passe. Les routeurs IPv6 ne fragmentent pas, donc un paquet surdimensionné est supprimé et Packet Too Big revient à l’expéditeur. Si les poignées de main et les petits pings fonctionnent mais qu’un transfert de fichier cale, réduisez la charge utile jusqu’à ce qu’il passe : ping -6 -s 1400 -c 3 2001:db8:bb::10. Les interfaces WireGuard ont par défaut une MTU de 1420 octets et IPsec sur IPv4 en retire davantage, donc régler la MTU interne vaut mieux qu’espérer une découverte de MTU de chemin à travers un pare-feu qui supprime ICMPv6.

Modes de défaillance qui ressemblent à des problèmes de pare-feu

Le plus courant n’est pas un pare-feu du tout : le service se lie à 0.0.0.0 au lieu de ::, l’enregistrement AAAA existe, et le client reçoit un refus rapide en IPv6 qu’un navigateur double pile masque en revenant à IPv4. Si seules certaines applications échouent, vérifiez la famille d’écoute avant de toucher à un jeu de règles.

Le deuxième est le filtrage ICMPv6. Neighbor Discovery et Packet Too Big font partie du fonctionnement normal, pas du diagnostic, et une politique qui supprime tout ICMPv6 produit un tunnel qui se connecte, s’authentifie, puis cale sur tout ce qui dépasse un petit paquet. Autorisez les types dont le chemin dépend et laissez les compteurs actifs pour qu’une suppression soit visible.

Le troisième est un préfixe ajouté au tunnel mais jamais au plan d’adressage du site qui le possède, si bien qu’aucun routeur ne l’annonce et qu’aucun hôte ne peut y répondre. Commencez avec un préfixe et une paire d’hôtes, prouvez les deux directions avec les quatre étapes, puis ajoutez le reste ; un préfixe cassé reste une ligne dans une configuration au lieu d’une refonte. La seule référence officielle qui vaut la peine de rester ouverte est RFC 8200, qui définit l’en-tête que le tunnel transporte.

Articles similaires