IPv6 à travers un tunnel OpenVPN : le tour du routeur domestique
IPv6 meurt ou fuit quand le tunnel distribue un préfixe que le routeur ne sait pas router. Parcourez le client, le pool, le forwarding, le proxy NDP et le chemin de retour dans l’ordre.
L’ordinateur portable a une adresse IPv6, le tunnel est monté sur IPv4 et, pourtant, tous les tests IPv6 échouent. Pire : le test réussit et le trafic est sorti par la route du fournisseur sans jamais entrer dans le tunnel. Les deux issues renvoient à une décision manquante : personne n’a donné au routeur un préfixe qu’il pouvait router vers les clients. Suivre le chemin depuis le client vers l’extérieur révèle quelle pièce manque.
Commencez là où se trouve le client
Regardez le client avant de toucher au serveur. ip -6 addr devrait afficher une adresse de tunnel issue du pool, et ip -6 route devrait afficher le préfixe poussé qui pointe vers l’appareil de tunnel. Quand l’adresse est là mais pas la route, le push manque ou le client l’a ignoré. Quand ni l’un ni l’autre n’est là, le serveur n’a absolument rien attribué.
Vérifiez ensuite ce que le client croit du monde extérieur. Une route par défaut via le tunnel revendique tout le trafic IPv6, tandis qu’une route pour 2000::/3 ne revendique que l’unicast global. Les deux peuvent être correctes, et elles répondent à des questions différentes sur les fuites.
Un client sans aucune route par défaut IPv6 échoue à tous les tests publics alors que le tunnel lui-même est parfaitement sain. C’est un trou de politique, pas un tunnel cassé.
Vérifiez le pool que le serveur peut réellement router
Un serveur ne peut attribuer que depuis un préfixe qu’il contrôle réellement. Si le fournisseur délègue un /56, réservez un /64 pour le tunnel et laissez le reste au LAN. Là où le fournisseur ne remet qu’un seul /64 sur le WAN sans rien router de plus, laissez le préfixe du LAN tranquille et donnez au tunnel une plage locale unique, en acceptant que les clients n’aient aucune sortie globale.
Le pool et le push vont ensemble. server-ipv6 2001:db8:80:10::/64 attribue des adresses, et push "route-ipv6 2000::/3" dit aux clients quoi envoyer dans le tunnel. Pousser 2000::/3 couvre l’unicast global et laisse les plages link-local et multicast hors du tunnel.
Écrivez le préfixe choisi dans le journal de déploiement. La prochaine personne qui modifiera la délégation du fournisseur doit savoir quel /64 le tunnel occupe déjà.
Activez le forwarding pour la seconde famille
Le forwarding IPv4 n’implique pas le forwarding IPv6. Réglez net.ipv6.conf.all.forwarding=1 et reproduisez tout ce que la politique FORWARD d’IPv4 autorise déjà. Sur un routeur dont la chaîne FORWARD rejette par défaut, un jeu de règles absent ressemble exactement à un tunnel mort.
La poignée de main réussit, le client reçoit une adresse, et rien ne revient. Ajoutez des règles pour les deux sens et pour le tronçon WAN, car un tunnel qui atteint le LAN mais pas Internet échoue au troisième test. Après un essai raté, regardez les compteurs de la chaîne, car une règle qui n’a jamais correspondu est un autre problème qu’une règle qui a correspondu et rejeté.
ip6tables -A FORWARD -i br0 -o tun0 -j ACCEPT
ip6tables -A FORWARD -i tun0 -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -i tun0 -o wan0 -j ACCEPT
Un effet secondaire attrape ceux qui finissent par accuser le tunnel. Activer le forwarding fait sauter au noyau la configuration d’adresse par Router Advertisement sauf indication contraire, et une route par défaut apprise ainsi disparaît avec elle. Soit vous épinglez une route par défaut explicite sur l’interface WAN, soit vous mettez délibérément accept_ra à 2 à cet endroit. Après l’un ou l’autre changement, confirmez que le routeur a encore un chemin IPv6 utilisable vers l’extérieur avant de retester les clients.
Répondez à la découverte de voisins quand l’amont ne route pas
L’équipement amont traite parfois le /64 délégué comme appartenant à son propre lien et refuse de router le moindre sous-préfixe vers la boîte VPN. Quand cela arrive, quelque chose doit répondre aux sollicitations de voisins pour chaque adresse de client, individuellement.
OpenVPN expose l’adresse attribuée à un hook client-connect, si bien que les entrées peuvent suivre le vrai pool au lieu d’une liste tenue à la main. Le hook ajoute ip -6 neigh add proxy $ifconfig_pool_remote_ip6 dev eth0, et un hook client-disconnect correspondant le retire. Sans ce retrait, la table proxy vieillit et un client ultérieur peut hériter d’une entrée pour une adresse qu’il n’a jamais reçue. Confirmez l’état avec ip -6 neigh show proxy.
Traitez le proxying comme un contournement. Une route statique pour le /64 du tunnel pointée vers le routeur survit aux changements de clients et n’exige aucun hook de shell privilégié.
Suivez le chemin vers l’extérieur, saut par saut
Testez vers l’extérieur en trois étapes : d’abord l’adresse de tunnel du routeur, ensuite un hôte du LAN et troisièmement une destination publique via traceroute6. Le pool est prouvé par la première, le forwarding et le pare-feu du LAN par la seconde, et le chemin de retour par l’amont par la troisième. Chaque échec resserre la recherche sur un seul appareil au lieu de rouvrir toute la conception.
Surveillez le MTU du tunnel, car les routeurs IPv6 du chemin ne fragmenteront pas pour vous. Un MTU trop grand se manifeste par une erreur packet-too-big et un TLS bloqué plutôt qu’un échec net. Fixez-le explicitement et testez avec une charge proche de la limite.