Tunnels IPv6 pour la maison

J'ai voulu avoir de l'IPv6 à la maison. Mon opérateur Internet ne fournit que de l'IPv4, il faut donc tunneller d'une façon ou d'une autre. J'ai une Kimsufi à disposition, avec un accès IPv6 natif, j'ai donc voulu l'utiliser comme point de sortie.

Bien sûr, une solution est d'utiliser un fournisseur de tunnel comme HE ou SixXS, mais où est l'intérêt de ne pas faire les choses soi-même ?

1 Creusage de tunnels

Beaucoup de technologies qui permettent de faire des tunnels IPv6 à travers un réseau IPv4 :

Nom Type Usage
6in4 Routeur - Routeur Un lien IPv6 (typiquement entre routeurs) explicitement configuré entre les deux extrémités
GRE Routeur - Routeur Une technique d'encapsulation générique Cisco (depuis normalisée) avec quelques fonctionnalités en plus
6to4 Routeur - Internet Un lien IPv6, les adresses sont dans 2002::⁄32 et on inclut dans l'adresse IPv6 l'adresse IPv4 (publique !) du routeur. Il y a besoin de relais sur l'Internet (pour le sens Internet -> Routeur)
ISATAP Hôte - Hôte Deux hôtes (éventuellement routeurs pour leurs réseaux respectifs) qui peuvent se parler en IPv4, avec quelques options d'autoconfiguration. Prévu pour un réseau local.
6over4 Hôte - Hôte Comme ISATAP, mais les hôtes doivent se parler en IPv4 multicast (typiquement, ils sont sur le même LAN). Pas intéressant par rapport à ISATAP, mais historiquement le premier.
Teredo Hôte - Internet Un hôte (éventuellement derrière un NAT) qui accède à l'Internetv6
IPsec Routeur - Routeur Initialement prévu pour créer un tunnel sécurisé entre deux réseaux

Quand on a un point de sortie, la technique idéale est 6in4, ou éventuellement IPsec en mode authentification (le chiffrement est peu intéressant, puisque couvrant uniquement la partie du trafic de la maison au point de sortie, et uniquement pour l'IPv6…).

2 Plan du réseau

Le serveur / point de sortie utilise lui-même des adresses IPv6. Le réseau côté maison a besoin d'au moins deux préfixes, pour le Wifi et pour le filaire. Or, OVH ne fournit aux kimsufi qu'un seul /64… Il va donc falloir découper en plusieurs morceaux. J'ai choisi /80, attribué comme suit :

tunnel-ip6.png

Figure 1: Schéma réseau

Où :

  • 2001:db8:a:b::/64 est le préfixe attribué au point de sortie ;
  • le premier /80 est attribué aux différents services qui tournent sur la machine ;
  • les /80 suivants pour la maison ;
  • en vert le tunnel entre le routeur Wifi à la maison et le point de sortie ;

J'ai utilisé des adresses ULA pour les extrémités du tunnels, mais en fait il n'y en a pas vraiment besoin : une fois qu'on a commencé à découper notre /64, autant aller jusqu'au bout. Ça permet juste de bien reconnaître les adresses dans les fichiers de configuration et dans les tcpdump.

3 Problèmes

Il y a deux problèmes avec cette façon de faire. Le premier est évident : on utilise des préfixes qui font plus que /64. Cela nous fait essentiellement perdre les mécanismes d'auto-configuration sur les réseaux de la maison.

Le deuxième est un peu plus subtile. Le /64 fournit par OVH n'est pas vraiment routé jusqu'à nous. Si c'était le cas, tous les paquets à destination du /64 seraient livrés à 2001:db8:a:b::1 (par exemple), et notre routage interne avec les /80 lui serait transparent. À la place, le dernier routeur s'attend à être directement connecté à ce /64, et à pouvoir faire directement un NS et recevoir une réponse pour chaque adresse. Il va donc falloir mettre en place sur l'interface externe un proxy NDP, qui fera croire au routeur que toutes les adresses sont directement connectées.

4 Implémentation

4.1 Routage sur le point de sortie

On va configurer les adresses que l'on utilise sur la machine comme des /128 (ou éventuellement comme des /80, enfin bref), créer le tunnel, et ajouter les routes statiques vers la maison.

Quelques lignes dans rc.conf :

                ifconfig_nfe0=
                "inet 203.0.113.197/24"

                defaultrouter=
                "203.0.113.254"

                ifconfig_nfe0_ipv6=
                "inet6 auto_linklocal"

                # 
                entree statique pour le routeur :

                # 
                http://travaux.ovh.net/?do=details&id=6819

                #
                rtsold_enable="YES"

                ipv6_defaultrouter=
                "fe80::5:73ff:fea0:0%nfe0"

                ifconfig_nfe0_alias0=
                "inet6 2001:db8:a:b::1/128"

                ifconfig_nfe0_alias1=
                "inet6 2001:db8:a:b::22/128"

                ifconfig_nfe0_alias2=
                "inet6 2001:db8:a:b::25/128"

                ifconfig_nfe0_alias3=
                "inet6 2001:db8:a:b::80/128"


                # 
                tunnel vers la maison

                gif_interfaces=
                "gif0"

                gifconfig_gif0=
                "203.0.113.197 198.51.100.56"

                ifconfig_gif0=
                "mtu 1480"

                ifconfig_gif0_ipv6=
                "inet6 -auto_linklocal"

                ifconfig_gif0_alias0=
                "fd93:1:2:3::1/127"


                ipv6_gateway_enable=
                "YES"

                ipv6_static_routes=
                "home_wifi home_wired"

                ipv6_route_home_wifi=
                "2001:db8:a:b:1:: -prefixlen 80 fd93:1:2:3::"

                ipv6_route_home_wired=
                "2001:db8:a:b:2:: -prefixlen 80 fd93:1:2:3::"

              

Si pf(4) tourne, on ajoutera :

                table <
                home_nets>  
                const 
                persist {
                 2001:db8:a:b:1::/80 2001:db8:a:b:2::/80 }

                extif = 
                "nfe0"

                tunif = 
                "gif0"

                # Tunnel 6in4 vers maison

                pass 
                on $
                extif 
                proto ipv6

                pass 
                from <
                home_nets> 
                to 
                any

                pass 
                from 
                any 
                to <
                home_nets>


                # Éventuellement des règles plus restrictives pour contrôler ce qui

                # arrive à la maison

              

4.2 Configuration du routeur wifi

Le routeur est un Cisco 877W qui fait tourner 15.1(3)T4. En 12.2, j'ai vu que parfois, le routeur décide de ne pas répondre aux NS, ce qui est un peu gênant. On utilise DHCPv6 pour distribuer les adresses. L'interface Wi-Fi ne peut pas être configurée en IPv6, mais on peut la placer dans un bridge qui, lui, peut être configuré avec IPv6.

ipv6 unicast-routing
ipv6 cef
!
interface Dot11Radio0
 description wireless
 bridge-group 1
 ssid Coloc
!
interface BVI 1
 description bridge pour wireless
 ipv6 mtu 1480
 ipv6 address 2001:DB8:A:B:1::1/80
 ipv6 nd autoconfig default-route
 ipv6 nd managed-config-flag
 ipv6 dhcp server HOME_WLANv6
!
interface Vlan20
 description vlan wired
 ipv6 mtu 1480
 ipv6 address 2001:DB8:A:B:2::1/80
 ipv6 nd managed-config-flag
 ipv6 dhcp server HOME_WIREDv6
!
interface range FastEthernet 0 - 2
 switchport mode access
 switchport access vlan 20
 description wired (vlan 20)
 spanning-tree portfast
!
interface Vlan10
 description vlan internet
 ip address dhcp
!
interface FastEthernet3
 description internet (vlan 10)
 switchport access vlan 10
!
interface Tunnel0
 description tunnel vers serveur
 no ip address
 ipv6 address FD93:1:2:3::/127
 tunnel source Vlan10
 tunnel destination 203.0.113.197
 tunnel mode ipv6ip
!
ipv6 dhcp pool HOME_WIREDv6
 address prefix 2001:DB8:A:B:2::/80
 dns-server 2001:DB8:A:B::53
!
ipv6 dhcp pool HOME_WLANv6
 address prefix 2001:DB8:A:B:1::/80
 dns-server 2001:DB8:A:B::53
!
ipv6 route ::/0 FD93:1:2:3::1/127

Les interfaces Fa 0 - 2, utilisées pour le LAN filaire, sont mises en portfast. Sans le portfast, il faut ≈45 secondes à STP pour accepter que je n'ai pas créé de boucle en branchant mon portable. NetworkManager envoie n RS avec un timeout de t secondes pour la réponse RA. Avec n = 3, t = 1 seconde (RFC2461), NetworkManager a le temps d'abandonner plusieurs fois… Donc on passe en portfast.

4.3 Proxy NDP

Comme mentionné plus haut, l'un des soucis est que le routeur devant la KS s'attend à voir le /64 complètement à plat. Il faut donc un proxy NDP qui réponde à la place des machines qui sont à la maison.

Ça fait environ 300 lignes pour un programme qui écoute avec libpcap les NS sur l'interface externe et qui envoie les NA correspondants. Le code est dans un dépôt git (ou interface gitweb). Avec le réseau montré plus haut, j'appelle ndp6 avec les options :

ndp6 -i nfe0 -p 2001:db8:a:b:1::/80 -p 2001:db8:a:b:2::/80

Les gens qui utilisent Linux sur le point de sortie seront intéressés par ndppd. Parmi les linuxeries, il y a la lecture de /proc/net/ipv6_route pour mettre à jour les réseaux proxifiés, l'utilisation d'une socket AF_PACKET pour écouter les paquets qui ne nous sont pas destinés.

5 Soucis rencontrés

5.1 Clients DHCP

Avec ISC dhclient, lorsqu'une adresse est configurée par DHCPv6, elle est installée avec un préfixe en /64. C'est un bug dans le client DHCP (les annonces DHCP ne contiennent qu'une adresse, pas d'informations sur le lien local). La RFC 5942, section 5 explique le problème, disant que c'est ce qui arrive quand « the IPv6 subnet model is not understood by the implementers of several popular host operating systems ».

Le bug Debian #684009 contient un patch pour ISC dhclient (apparemment remonté upstream). De son côté, Network Manager ne fait ples confiance aux préfixes annoncé par les clients DHCPv6.

Le client WIDE dhcp6c a le bon comportement (à condition de lui dire de demander une adresse…), je n'ai pas testé son intégration avec Network Manager.

Le Windows 7 du boulot semble avoir le bon comportement.

5.2 Bizarrerie sur le DHCP côte WAN

Les serveurs DHCP de chez Virgin Media se comportent bizarrement. En particulier, après une coupure de courant, le routeur ne reçoit pas d'adresse jusqu'à ce que le modem câble se fasse rebooter. Pas quelque chose que je peux corriger de mon côté…

Vus : 2375
Publié par Frédéric Perrin : 9