Proxy NDP IPv6

^--- billet invité

Niveau : Star Star Star Empty Empty
Résumé : proxy ndp

Aujourd'hui nous allons parler d'IPv6. Pas du troll sur son arrivée imminente (ou pas), mais de situations qui nécessitent l'utilisation d'une fonctionnalité du noyau linux appelée proxy NDP.

Rappels sur IPv6 et NDP (les habitués d'IPv6 peuvent passer)

En IPv4, on dispose du protocole ARP pour trouver, à partir de l'adresse IP, l'adresse MAC à laquelle envoyer le paquet Ethernet sur le même réseau. Si c'est sur un autre réseau, il suffit d'avoir une table de routage et de connaître le routeur (la passerelle) pour cette destination, à qui on envoie le paquet.

En IPv6, on fait fi d'ARP pour utiliser ICMPv6. Vous me direz, on ne fait que reporter le problème, on n'a toujours pas l'adresse MAC : c'est là qu'intervient la notion de lien local. En effet vous avez déjà du remarquer qu'à peine votre interface réseau montée, vous disposez d'une adresse de lien local (obtenue à partir de votre adresse MAC).

# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:19:66:8c:b0:d9
          inet6 addr: fe80::219:66ff:fe8c:b0d9/64 Scope:Link
[...]

De la même manière, vos voisins sur le même lien Ethernet ont leur adresse de lien local, et c'est en utilisant celle-ci combinée au protocole ICMPv6 qu'on voit passer les requêtes NDP (Neighbor Discovery Protocol) de découverte de voisinage. On y retrouve exactement le principe de l'ARP d'IPv4 (who has/target is at), avec un nouveau vocabulaire (neighbor solicitation/neighbor advertisement).

# tcpdump -ni eth0 ip6
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

16:06:29.756895 IP6 2a01:e35:3e93:68c0:4d0a:f82b:3678:aaac > ff02::1:ff8c:b0d9: ICMP6, neighbor solicitation, who has 2a01:e35:3e93:68c0:219:66ff:fe8c:b0d9, length 32

16:06:29.757294 IP6 2a01:e35:3e93:68c0:219:66ff:fe8c:b0d9 > 2a01:e35:3e93:68c0:4d0a:f82b:3678:aaac: ICMP6, neighbor advertisement, tgt is 2a01:e35:3e93:68c0:219:66ff:fe8c:b0d9, length 32

Problème

Ce petit rappel étant fait, voici le problème que l'on peut rencontrer en IPv6 : un fournisseur de connectivité IPv6 vous donne (annonce) depuis son routeur un /N sur lequel vous pouvez utiliser des adresses IPv6. Là où le bât blesse, c'est que son routeur désire voir à plat (sur le même lien local) toutes les IPv6. Impossible donc à première vue de placer votre routeur juste après celui du fournisseur et d'organiser les IPv6 en réseaux comme bon vous semble. A noter qu'on rencontre le même problème en IPv4 avec un fournisseur qui donne un /N et qui veut le voir à plat. Dans ce cas de figure, on peut utiliser le proxy ARP (dans le noyau). La méthode pour l'IPv6 présentée plus bas est ni plus moins son homologue en IPv6.

On rencontre cette situation par exemple chez Free, où la Freebox annonce un /64 (l'abonné dispose même d'un /60), ou encore chez OVH lorsque vous possédez un serveur dédié, où le routeur d'OVH vous annonce un /56 rien que pour vous (même si dans le manager c'est indiqué un /64, vous pouvez utiliser ce /56). Je présume que c'est le cas pour d'autres opérateurs, ou d'autres hébergeurs comme Dedibox.

Que l'on veuille organiser son réseau domestique avec son propre routeur IPv6 derrière sa freebox, ou que l'on veuille répartir en sous-réseaux le /56 de son serveur dédié dans des machines virtuelles ou des containers, le routeur veut voir le réseau à plat (sur le même lien) c'est ce qui pose problème. La solution évidente serait de pouvoir faire du routage : si on pouvait intervenir sur la table de routage de ce routeur (via le manager d'OVH, via la console de gestion de Free, ou via le protocole DHCPv6 s'il est implémenté me dit peck (NDM(note de moi): rechercher prefix delegation)), il suffirait de dire que pour joindre tel sous-réseau il faut contacter le routeur à l'adresse donnée. Malheureusement, on ne peut pas pour l'instant, il faut donc trouver autre chose.

La solution que je vais vous proposer et détailler est un proxy NDP : il s'agit de faire croire au routeur (la freebox ou le routeur OVH) qu'il voit votre réseau à plat (sur le même lien), en transférant les messages NDP d'un côté et de l'autre. Cette solution n'est pas nouvelle : Thierry Fournier propose depuis maintenant 1 an et demi un excellent tutorial rapportant son expérience avec l'IPv6 chez Free et comment il a organisé son réseau domestique. Le Wiki Gentoo dispose lui aussi d'un excellent article à ce sujet.

Une autre solution, plus ancienne, est d'utiliser le brouting ou switch filtrant (on route l'IPv4 et on laisse passer l'IPv6), mais je ne la détaillerai pas.

Solution à base de proxy NDP

Pour résumer, il va s'agir de :

  • posséder un noyau linux supérieur à 2.6.19, à partir duquel le proxy NDP a été implémenté
  • activer le routage IPv6 et le proxy NDP dans le noyau
  • organiser son réseau (côté routeur) en sous-réseaux (côté LAN)
  • router ces sous-réseaux du routeur vers les LANs
  • configurer les hôtes
  • configurer le proxy NDP côté LAN pour que les hôtes aient connaissance du routeur
  • configurer le proxy NDP côté routeur pour que le routeur ait connaissance des hôtes

Pour la suite, comme les explications pour Free ont déjà été données sur Internet, je vous propose d'expliquer le proxy NDP dans le contexte d'un serveur dédié chez OVH avec des machines virtuelles (VM). Notez bien que c'est le même principe, juste le contexte de l'explication qui diffère.

Voyons comment ce réseau IPv6 s'organise :


.----------. 2001:2:3:4500::/56   .---------------.
| routeur  |______________________|    serveur    |
|   IPv6   |                  eth0|     dédié     |
*----------*                      *---------------*
                                veth1 |        | veth2
                                      |        |
                   2001:2:3:4501::/64 |        | 2001:2:3:4502::/64
                                      |        |
                                 eth0 |        | eth0
                                    [VM 1]   [VM 2]

Comme vous le voyez, le routeur fournit à ce serveur le préfixe 2001:2:3:4500::/56 :

2001:0002:0003:45 00::
\_______________/ \_..._/
 partie réseau     partie pour le serveur
    (56)            (72)

Que l'on va diviser en deux /64 pour chaque VM :

  • 2001:2:3:4501::/64 pour la VM1
  • 2001:2:3:4502::/64 pour la VM2

A noter que chez OVH, votre routeur est joignable sur le /56 suivi de 5*FF. Supposons alors que dans notre cas, le routeur soit à l'adresse 2001:2:3:45FF:FF:FF:FF:FF.

Sur le serveur, on route ces sous-réseaux vers les VM :

# ip route add 2001:2:3:4501::/64 dev veth1
# ip route add 2001:2:3:4502::/64 dev veth2
# ip -6 route list
2001:2:3:4501::/64 dev veth1  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
2001:2:3:4502::/64 dev veth2  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
2001:2:3:45FF:FF:FF:FF:FF dev eth0  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
2001:2:3:4500::/56 dev eth0  proto kernel  metric 256  expires 2427074sec mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64 dev eth0  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64 dev veth1  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64 dev veth2  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via 2001:2:3:45ff:ff:ff:ff:ff dev eth0  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295

Avant d'aller plus loin, n'oubliez pas d'activer le routage IPv6 ainsi que le proxy NDP. Par exemple avec les directives suivantes dans /etc/sysctl.conf suivi d'un sysctl -p pour appliquer :

net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.proxy_ndp=1
net.ipv6.conf.all.proxy_ndp=1

Bien entendu, vous pouvez activer cela plus finement uniquement sur les interfaces concernées.

Pour la configuration des hôtes, il s'agit juste de leur indiquer qui est leur routeur, la route par défaut vers ce routeur, et enfin d'ajouter une ou plusieurs adresses dans le préfixe alloué. Par exemple, on configure la VM1 avec l'adresse 2001:2:3:4501::1/64 :

# ip route add 2001:2:3:45ff:ff:ff:ff:ff/128 dev eth0
# ip route add default via 2001:2:3:45ff:ff:ff:ff:ff
# ip address add 2001:2:3:4501::1/64 dev eth0
# ip -6 route list
2001:2:3:4501::/64 dev eth0  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
2001:2:3:45ff:ff:ff:ff:ff dev eth0  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64 dev eth0  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via 2001:2:3:45ff:ff:ff:ff:ff dev eth0  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
# ip -6 address list
1: lo:  mtu 16436
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500
    inet6 2001:2:3:4501::/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::218:51ff:fede:aca9/64 scope link
       valid_lft forever preferred_lft forever

La même chose pour la VM2 avec l'adresse 2001:2:3:4502::1/64.

Il faut maintenant configurer le proxy NDP côté LAN pour que les hôtes (VM) aient connaissance du routeur. Sur le serveur et pour chaque interface où il faut faire apparaître le routeur avec le proxy NDP, procéder comme suit :

# ip neigh add proxy 2001:2:3:45ff:ff:ff:ff:ff dev veth1
# ip neigh add proxy 2001:2:3:45ff:ff:ff:ff:ff dev veth2

La même chose de l'autre côté pour que le routeur ait connaissance des VM. Pour chaque adresse IPv6 utilisée par les hôtes (VM), il faut explicitement la faire apparaître avec le proxy NDP. Par exemple pour les 2 VM où on a configuré l'adresse ::1 :

# ip neigh add proxy 2001:2:3:4501::1 dev eth0
# ip neigh add proxy 2001:2:3:4502::1 dev eth0

Enfin, il faut mettre l'interface côté routeur en mode promiscuous, afin de pouvoir prendre les paquets qui ne lui sont pas destinés mais destinés aux VM :

# ifconfig eth0 promisc

Les interfaces vers les VM n'en ont pas besoin car elles sont virtuelles. Dans le cas de Free avec des hôtes réels connectés à une interface réelle, il sera nécessaire de mettre l'interface côté hôtes en mode promiscuous aussi.

Maintenant, vous devriez avoir l'IPv6 disponible sur vos VM, et organisé comme il vous plaît. Si cela ne fonctionne pas, vous pouvez analyser le réseau en différents points (eth0, veth1, veth2, eth0 des VM) pour voir (ou ne pas voir justement) les paquets IPv6 qui passent :

tcpdump -ni <interface> ip6

Enfin, comme le fait remarquer l'article sur le wiki Gentoo, on peut procéder à la configuration automatique des VM en faisant tourner un démon radvd sur le serveur pour annoncer le préfixe utilisable ainsi que l'adresse du routeur. Cela ne vous affranchira cependant pas d'ajouter manuellement le proxy NDP pour chaque IPv6 utilisée, et c'est l'inconvénient majeur de cette technique. Mais après tout, dans le cas de serveurs les IPv6 utilisées sont choisies à l'avance, et pour les postes clients le plus souvent l'adresse IPv6 est obtenue à partir de l'adresse MAC, alors on s'en sort.

Si vous trouvez un moyen de voir les IPv6 utilisées dans les sous-réseaux et d'automatiquement ajouter le proxy NDP, faites-le savoir ! Ça doit être faisable à coup de tcpdump sur les neighbor solicitation, mais c'est moche...

J'espère avoir été clair et vous souhaite de bien vous amuser avec l'IPv6 ! Si vous avez des questions, n'hésitez pas.

NDM: il y a moyen de faire sans promisc et avec du proxy NDP d'un coté seulement, mais reste a retrouver les bonne conditions pour que ça marche.

Tags:,
Vus : 754
Publié par Peck : 100