IPv6 sur EdgeRouter (Red by SFR / SFR)

Petit achievement aujourd’hui, j’ai réussi à avoir l’IPv6 de mon fournisseur d’accès directement depuis mon routeur EdgeRouter-4. Pour remettre en contexte, ma box SFR est dans son carton. Le seul équipement de SFR que j’utilise est l’ONT, qui converti un signal fibre en cuivre entre-autre.

Jusqu’à présent, j’utilisais un tunnel IPv6-in-IPv4 fourni par Hurricane. C’est gratuit, la bande passante est plutôt grosse, mais n’arrange sûrement pas à réduire la latence par rapport à une connectivité IPv6 directement fournie par l’opérateur (du moins, je pense).

Pourquoi ?

Avant de détailler comment j’ai fait, j’aimerais expliquer pourquoi je n’utilise pas la box de l’opérateur, après tout elle est gratuite et propose plein de fonctionalités, non ? C’est vrai mais… non, pour plein de raisons :

  • en matière de sécurité, je trouve totalement malsain d’avoir une box opérateur, propriété de l’opérateur, contrôlée par l’opérateur au sein de mon réseau local. L’utilisation d’un routeur sous mon contrôle évite une fuite des données vers l’opérateur. Distinction franche entre mon réseau local et le réseau opérateur.
  • si je change d’opérateur, je n’ai pas à reconfigurer mon réseau interne. Seul la patte WAN sera modifiée. J’ai zéro adhérence avec mes opérateurs Internet ou de téléphonie.
  • je n’ai plus de téléphone fixe et la merdasse télévisuelle ne m’encourage pas à utiliser le décodeur fournit. Au pire, il s’agit juste de VLAN à faire passer, donc là aussi la box n’est pas indispensable
  • j’ai vraiment plus de fonctionnalités avec mon routeur que toutes les box opérateurs réunies. Je peux monter un tunnel GRE, IPSec v2, avoir des routes conditionnelles etc… Il s’agit de fonctionnalités que j’utilise.
  • Ca marche (avez-vous déjà utilisé l’interface d’administration de la box Orange) ?
  • Ca marche vraiment. Impossible de faire fonctionner un tunnel IPSec le plus bidon possible en utilisant la box Orange.
  • Ca marche même sous stress, là où la box opérateur plante avec un simple DoS (désolé Nunzz ^^ »)

Il est clair que remplacer sa box n’est pas à la portée de tout le monde, mais rien que pour la fiabilité, ça donne envi.

Mimer la box opérateur

Le plus simple pour trouver comment faire est encore d’analyser la communication entre la box opérateur et le réseau opérateur. Cela tombe bien, j’avais justement un switch manageable ce qui m’a permis de mettre en place un port mirroring et ainsi pouvoir sniffer le traffic depuis mon pc portable en live.

Contrairement à ce que j’avais lu ici ou , j’ai été ravi de lire que l’obtention d’un bloc IPv6 se fait de manière non seulement simple mais suivant les standards (enfin presque) ! En effet, le bloc IPv6 s’obtient via le protocole DHCPv6 en 4 messages :

  • SOLICIT: le client hurle (broadcast) à la recherche d’un serveur DHCP
  • ADVERTISE: un serveur DHCP répond à l’aide
  • REQUEST: le client souhaite obtenir une délégation sur un bloc IPv6
  • REPLY: le serveur, tout aimable qu’il est, répond positivement à la requête
Capture de la requête DHCPv6
Capture de la requête DHCPv6

Bloc IPv6 vs IPv4

De prime abord, le processus pour obtenir une IPv6 semble plus compliquée. Cette apparente complexitée s’explique par le fait qu’il n’y a pas de NAT en IPv6 (enfin si mais on va supposer que non). Cela signifie que tout équipement souhaitant aller sur Internet ne peut pas utiliser l’IP du routeur, comme cela se fait en IPv4 mais doit avoir sa propre IPv6 routable. Routable par opposition à une IPv6 privée (commençant par fe80:) qui pourrait être l’équivalent du 192.168.x.y en IPv4.

Pour répondre à cette problématique d’IP routable, on a deux choix de réseaux :

  • il n’y a plus de réseau local, uniquement le réseau de l’opérateur dont vous et tout vos équipements font parti. Cette solution n’est absolument pas raisonnable tant pour l’usager que pour l’opérateur d’un point de vue de la sécurité.
  • le réseau local de chaque utilisateur et le réseau opérateur, séparés par un routeur

La solution retenue est bien entendue la seconde. Sans IP routable, la communication d’un périphérique est limitée à son réseau local. L’obtention d’une IPv6 se fait donc par un appareil se trouvant lui aussi dans le réseau local, c’est à dire la box opérateur.

Cette box va donc demander à l’opérateur quels sont les IPs qu’il peut distribuer en local, c’est le prefix delegation (PD). L’opérateur fournit à chaque box, qui en fait la demande, une délégation sur un préfixe IPv6 (ou bloc IPv6), ce qui va permettre deux choses :

  • la box va pouvoir distribuer une IP dans ce pool aux objects connectés
  • ce bloc sera routé depuis Internet vers la box (pinger une IP de ce pool va arriver sur le routeur, qui forwardera (ou pas) le paquet)

Patcher Wide-DHCPv6

L’OS EdgeMax est tout à fait en mesure de gérer intégralement la stack IPv6, au moins en CLI vu que la GUI tarde à le gérer proprement. En tant que client DHCPv6, il utilise wide-dhcpv6 pour obtenir une prefix delegation. Là où ça coince, est que le serveur attend deux informations qu’il n’est pas possible de setter dans la configuration de wide-dhcpv6 :

  • le client identifier (option 1) avec un DUID de type 3 (link-layer adress) et non 1 (link-layer adress plus time). Ce pré-requis est obligatoire. Actuellement la valeur est l’adresse mac de la box côté LAN mais pour plus de sûreté, prenez la valeur indiquée dans la capture
  • le vendor class (option 16) qui est l’id du modèle de la box. Il s’agit d’un paramètre optionnelle pour le moment.
Requête DHCPv6 avec les deux options à reproduire
Détail de la requête DHCPv6

Vu que Ubiquiti est respectueux de la licence GPL, j’ai pu récupérer le code source patché de wide-dhcpv6 et commencer à travailler me casser les dents dessus.

Fixer les bugs n’étaient pas une mince affaire. Le EdgeRouter fonctionne sous une architecture MIPS. J’ai donc du monter une vm avec qemu, elle-même dans une VM linux puisque je suis sous Windows, afin de pouvoir compiler la chose. Le débuggage avait comme un arrière goût des années 80 : une compilation qui prend 15 minutes à chaque fois et des outils franchement pas pratique, genre gdb. Et une doc complètement inexistante bien entendu, avec des noms de variables incompréhensible. Au-secours !

Mais j’ai fini par me sortir de ce sable mouvant, voici donc les patches ubnt-wide-dhcpv6-201.tar

Comme c’est ultra chiant à compiler, voici également le binaire à glisser à la place de /usr/sbin/dhcp6c sur le routeur.

Au passage, Ubuntu sous Hyper-v Gen 2, ça marche 🙂

Configurer le Edgerouter

Il va falloir au préalable récupérer quelques informations contenues dans la capture faite précédemment. Elles sont indispensables pour pouvoir configurer proprement le EdgeRouter :

  • le DUID dans le message SOLICIT
  • le vendor class value dans le message SOLICIT
  • le prefix

Il y a 3 sections à configurer :

  • le dhcpv6 pour obtenir un préfixe côté WAN
  • le radvd (router-advert) pour distribuer les préfixes côté LAN
  • l’override de l’adresse mac de l’interface WAN

Ci-dessous ma configuration EdgeRouteur :

interfaces {
    ethernet eth0 {
        address 192.168.x.254/24
        address 2a02:8428:xx:xx00::ff/64
        description lan0
        ...
        ipv6 {
            dup-addr-detect-transmits 1
            router-advert {
                cur-hop-limit 64
                link-mtu 0
                managed-flag true
                max-interval 600
                name-server 2a02:8428:xx:xx::ff
                other-config-flag false
                prefix 2a02:8428:xx:xx::/64 {
                    autonomous-flag true
                    on-link-flag true
                    preferred-lifetime 14400
                    valid-lifetime 28800
                }
                reachable-time 0
                retrans-timer 0
                send-advert true
            }
        }
    }
    ethernet eth2 {
        address dhcp
        description wan0
        ...
        dhcpv6-pd {
            duid 00030001e45d41dexxxx
            no-dns
            pd 1 {
                interface eth0 {
                    prefix-id 1
                }
                prefix-length 56
            }
            prefix-only
            rapid-commit disable
        }
        mac e4:5d:41:de:xx:xx
    }
}

SFR distribue un préfix /56. Un réseau local avec radvd utilise un préfix en /64. Cela signifie que vous pouvez avoir 256 réseaux locaux. Récupérez le préfixe distribué par SFR (depuis la box par exemple) et choisissez un sous-préfixe en /64 pour votre LAN. C’est ce qu’il faudra renseigner dans interfaces -> ethernet ethx -> ipv6 -> router-advert -> prefix.

Fixez également l’IPv6 de l’interface LAN du routeur, afin de pouvoir spécifier un serveur DNS qui écoute sur la stack IPv6, c’est le paramètre interfaces -> ethernet ethx -> ipv6 -> router-advert -> name-server.

Enfin remplacer l’adresse mac de l’interface WAN par celle de l’opérateur. Ce n’est pas obligatoire mais devrait mieux supporter les évolutions du réseau de l’opérateur.

Afin de mieux mimer les requêtes DHCPv6 (et parce que de toute façon il n’est pas possible de générer le bon fichier de conf en cli), on va écraser complètement le fichier généré par la section dhcpv6-pd par notre propre version.

# interface wan
interface eth2 {
        request domain-name-servers, domain-name;
        duid 00:03:00:01:e4:5d:41:de:xx:xx;
        send ia-pd 1;
        # récupéré par le sniff, il s'agit de mettre la valeur brute du vendor class
        send raw-option 16 00:00:a0:0c:00:40:6e:65:75:66:62:6f:78:5f:4e:42;
        script "/opt/vyatta/sbin/ubnt-dhcp6c-script";
};

id-assoc pd 1 {
        prefix ::/0 0 0;
        # interface lan
        prefix-interface eth0 {
                sla-id 1;
                sla-len 8;
        };

        # interface lab
        prefix-interface eth0.213 {
                sla-id 213;
                sla-len 8;
        };
};

Je donne ici un exemple où je récupère un préfix en /56 de SFR et j’assigne deux /64 pour mes deux réseaux locaux :

  • eth0, qui est le réseau principal
  • eth0.213 qui est mon réseau lab

Cela permet de mettre en évidence le rôle des paramètres sla-id et sla-len. sla-len est la différence entre le /56 donné par l’opérateur et le /64 que j’assigne à un réseau, soit 64-56=8.

sla-id est de longeur sla-len, il peut donc avoir une valeur entre 0 et 255 inclus. C’est le nombre qui sera suffixé au préfix. Par exemple mon préfixe donné est 2a02:8428:1234:3300::/56. Alors :

  • avec un sla-id de 1, le subnet de eth0 sera 2a02:8428:1234:3301::/64
  • avec un sla-id de 213, le subnet de eth0.213 sera 2a02:8428:1234:33d5::/64

Il ne reste plus qu’à rendre la configuration et le binaire persistent, à l’aide de /config/user-data et d’un petit script de restauration. Jetez un oeil à mon article de présentation de l’ER-4 pour se faire.

Plus

Ca marche aussi avec Sosh / Orange. Il faudra sniffer le traffic entre la box et l’ONT afin de récupérer les bonnes options et valeurs.

Source

Désactiver les Router Advertisement sur les modem Thomson

Toute personne ayant un abonnement ADSL chez OVH est un geek et sait donc que l’interface web des modems Thomson est… disons très perfectible pour rester gentil.

Je vais donc détailler ci-dessous la méthode permettant de désactiver réellement les Router Advertisement envoyés par le modem, ce qui permettra d’avoir son propre routeur IPv6 (et sans la nécessité d’utiliser le modem en bridge).

Disclaimer

Comme d’habitude, la procédure risque de vous déconnecter d’Internet et tant pis pour vous si vous cassez tout. Vous devez avoir une bonne connaissance du protocole IPv6, notamment au niveau des échanges effectués en ICMPv6, du routage et du protocole de découverte des voisins (NDP aka Neigbour Discovery Protocol).

Pensez à sauvegarder la configuration de votre modem afin de toujours pouvoir revenir en arrière dans une configuration fonctionnelle.
J’ai galéré pendant 2 jours avant d’avoir un truc fonctionnel, il y a donc de forte chance pour que ça ne fonctionne pas du premier coup.

Juste pour rire, la méthode qui ne fonctionne pas.

  • Allez sur la page d’administration du modem
  • Cliquez sur Home Network > Interfaces > Configure
  • Décochez la case « Use Stateless DHCPv6 Server » et valider en appuyant sur Apply
  • Et voilà, ça marche pas (même après un redémarrage du modem) !

technicolor_radvd

Par « ça marche pas », j’entends par là que le modem continue toujours à balancer ses RA et ses DNS, comme on peut le vérifier en écoutant le réseau ou via les logs de mon propre démon radvd :

Aug 15 14:18:53 tefnout radvd[5802]: our AdvOtherConfigFlag on enp2s0 doesn't agree with fe80::xxxx:xxxx:xxxx:xxxx
Aug 15 14:18:53 tefnout radvd[5802]: RDNSS address 2001:41d0:1:e2b8::1 received on enp2s0 from fe80::xxxx:xxxx:xxxx:xxxx is not advertised by us
Aug 15 14:18:53 tefnout radvd[5802]: RDNSS address 2001:41d0:3:163::1 received on enp2s0 from fe80::xxxx:xxxx:xxxx:xxxx is not advertised by us
Aug 15 14:18:53 tefnout radvd[5802]: our AdvValidLifetime on enp2s0 for 2001:41d0:fe1c:1300:: doesn't agree with fe80::xxxx:xxxx:xxxx:xxxx
Aug 15 14:18:53 tefnout radvd[5802]: our AdvPreferredLifetime on enp2s0 for 2001:41d0:fe1c:1300:: doesn't agree with fe80::xxxx:xxxx:xxxx:xxxx

Et maintenant la méthode qui fonctionne

  • Ouvrez putty et connectez-vous en précisant l’ip du modem ainsi que le protocol Telnet
  • Connectez-vous. Les identifiants par défaut sont Administrator pour le nom d’utilisateur et il n’y a pas de mot de passe.
  • Tapez ce qui suit, en adaptant bien sur avec votre prefix/subnet :
# ajout d'une délégation
:ip rt6advd pdadd intf=LocalNetwork subnet-id=2001:41d0:fe1c:xxxx::/64 interface-id=slaac origin=Internet types=+dhcp+6rd+6to4+ula aflag=enabled lflag=enabled
# suppression des router advertisements
:ip rt6advd pfxdelete subnet-id=2001:41d0:fe1c:xxxx::/64

# ajout d'une route, pour que le modem balance les paquets en retour à votre router (nécessaire en mode router)
:ip rtadd dst=2001:41d0:fe1c:xxxx::/64 gateway=fe80::20c:29ff:xxxx:fbf intf=LocalNetwork status=up metric=0 static=enabled
# suppression de l'ancienne route
:ip rtdelete dst=2001:41d0:fe1c:xxxx::/64 intf=LocalNetwork
  • Et on termine bien sur par un saveall  pour que la configuration soit persistante (survive à un reboot)

Les commandes qui commencent par :ip rt6advd  ne servent pas qu’à envoyer des Router Advertisements, elles servent également à autoriser la délégation du préfixe dans le réseau local (= avoir un autre routeur IPv6 en plus du thomson). Il n’est donc pas possible de simplement détacher l’interface avec la commande :ip rt6advd ifdetach intf=LocalNetwork , cela aura pour effet de couper toute connectivité IPv6.

Divers

Pour aligner le modem avec les valeurs par défaut de radvd :

:ip rt6advd pfxadd intf=LocalNetwork subnet-id={VOTRE-PREFIX-IPV6}::/64 interface-id=slaac vltime=86400 pltime=14400 aflag=disabled lflag=enabled

On peut lister les interfaces sur lesquels il balance du RA avec la commande suivante : :ip rt6advd iflist

De manière générale, la commande help  aide dans la plupart des cas à découvrir toutes les fonctionnalités du modem. Le modem est en paille (c’est dommage), mais il est fonctionnellement très bien fournit sur le contrôle de toute la pile réseau.

IPv6 sous Linux

Autant sous Windows l’IPv6 se configure tout seul, autant sous Linux, c’est une autre histoire, en particulier si ce dernier fait office de routeur IPv6 et qu’on a configuré proprement le pare-feu (ou alors je n’ai rien capté, c’est aussi possible).

Il y a deux aspects à voir, tout d’abord lorsque l’OS sert de routeur IPv6 (qu’il soit ou pas routeur IPv4 n’importe pas), c’est à dire lorsque net.ipv6.conf.default.forwarding = 1 , ce dernier n’écoute plus les Router Advertisement, même si net.ipv6.conf.default.accept_ra = 1  et par conséquent, l’IPv6, le masque de sous-réseau ainsi que les routes sont à configurer manuellement. Cela peut surprendre de prime abord.

Le second aspect se situe au niveau de la découverte de ses voisins. En IPv4, cela se fait avec des paquets ARP, alors qu’en IPv6, cela se fait avec des paquets ICMPv6.
Pour rappel, ARP est un protocole de lien, ce n’est pas encapsulé dans un paquet IP.
D’un point de vue du pare-feu, c’est pratique car alors que iptables ne peux filtrer des paquets ARP, puisque ces derniers n’ont rien à voir avec la couche IP (c’est le rôle d’ebtables), ip6tables sait parfaitement filtrer des paquets ICMPv6, eux-mêmes étant encapsulés dans un paquet IPv6. Mais il faut y penser lorsqu’on active son pare-feu.
Cela donne par exemple pour Gentoo :

# /etc/conf/net
config_eth0="192.168.3.2/24
2001:41d0:fe1c:1300:20c:29ff:fe99:fbf/56"
routes_eth0="
default via 192.168.3.1
"2000::/3 via fe80::5a98:35ff:fea1:a7ea" # ça ne sert à rien de router autre chose que des adresses internet pour un serveur dédié "normal"

La première chose qu’on fait en général avec le pare-feu, c’est de passer la stratégie par défaut à DROP, en ajoutant le minimum syndical, à savoir un accès SSH notamment si on n’est pas en local sur la machine. Mais faire cette manip coupe également le bon fonctionnement de l’IPv6.

Après analyse avec tcpdump des trames réseau, on en vient à la configuration d’un pare-feu stateful suivante :

# attention: on flush toute la table, et on change la règle par défaut afin de rester connecté
ip6tables -P INPUT ACCEPT
ip6tables -F INPUT
ip6tables -A INPUT -m ctstate --ctstate INVALID -j DROP
ip6tables -A INPUT -m ctstate --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
ip6tables -P INPUT DROP
# vos règles d'accès commencent ici

 

Les deux premières règles permettent un minimum de protection contre des paquets éventuellement forgés.
La troisième permet d’autoriser toute connexion sur la boucle locale.

Les règles 4 et 5 sont celles qui font marcher le schmilblick et permet au système de découvrir ses voisins, en particulier l’adresse MAC de sa passerelle vers internet. Il n’est pas possible de filtrer par adresse source, car les requêtes peuvent être légitimement émises par des adresses locales (fe80::/10 ), multicast (ff00:/8 ) ou unicast routables (2000::/3 ), en conséquences on filtre sur le nombre de sauts, qui doit être de 1 avec le filtre hl (hop limit), sachant que dans le cas d’un serveur dédié, seul les réponses et requêtes de la passerelle sont désirées et légitimes.

Youtube à plein tube

C’est pas une nouveauté, Youtube + Free = caca lorsqu’on a l’IPv6 d’activé. Voici une démarche permettant de contourner ce problème aisément.
Le tutoriel ne fonctionnera que sous Windows Vista ou Windows 7, mais l’idée peut être adaptée partout. Elle consiste simplement à filtrer les IPv6 utilisées par Youtube.

Voici donc la procédure :

  1. Accédez au pare-feu, via par exemple le bouton Démarrer > wf.msc (il faut évidemment être administrateur de sa machine)
  2. Ajoutez une règle de trafic sortant avec les paramètres suivants (voir plus bas pour la version en images) :
    • Type de règle: personnalisé
    • Appliqué à tous les programmes
    • Le protocole TCP sur le port distant 80
    • Lorsque les IP distantes sont dans la rangée : 2a00:1450::/32 ou 2607:f8b0::/32
    • Bloquer la connexion
    • sur tous les emplacements (Domaine, Privé et Public)
    • avec le nom suivant : Youtube IPv6
    • C’est tout. Il n’y a plus qu’à rafraîchir la page du navigateur

Les IPs s’obtiennent avec n’importe quel analyseur réseau comme Wireshark, Firebug ou les Outils de développements intégrés à Chrome. Ensuite, l’utilisation du bon RIR (Ripe pour les IPs européennes, ARIN pour le continent américain, APNIC pour l’Asie et le Pacifique) permet d’obtenir le bloc contenant l’IP cherchées qui a été affecté. On vérifiera que le propriétaire des 2 blocs est bien Google, propriétaire de Youtube.

En images :

youtube_templateyoutube_programyoutube_portyoutube_hostyoutube_actionyoutube_profilyoutube_name