Le lien local

Nous allons sans tarder effectuer une première manipulation. Pour l'instant, nous ne disposons que de deux hôtes, connectés entre eux par un simple HUB, sans aucune passerelle vers l'internet. L'un des deux hôtes est déjà démarré et configuré en IP v6. Il dispose d'un « sniffeur » (l'incontournable Wireshark).

L'objectif est de contrôler ce qu'il se passe lorsque le second hôte est mis en service. Cet hôte dispose d'une interface dont l'adresse MAC est :

00:0d:88:37:73:e9

Voyons d'abord l'ensemble des trames capturées :

No.     Time        Source                   Destination           Protocol Info
      1 0.000000    ::                       ff02::1:ff37:73e9     ICMPv6   Neighbor solicitation
      2 0.999924    fe80::20d:88ff:fe37:73e9 ff02::2               ICMPv6   Router solicitation
      3 4.999740    fe80::20d:88ff:fe37:73e9 ff02::2               ICMPv6   Router solicitation
      4 8.999580    fe80::20d:88ff:fe37:73e9 ff02::2               ICMPv6   Router solicitation

Il y a plusieurs choses à dire ici.

Neighbor solicitation

L'hôte qui démarre cherche à auto-configurer son lien local, en utilisant le principe vu plus haut. Il va donc préalablement s'assurer que l'adresse IP qu'il compte exploiter n'est pas déjà utilisée.

Pour ce faire, il exploite une nouvelle fonctionnalité d'ICMP qui est appelée « Neighbor discovery » (Découverte du voisinage).

  • L'adresse source est ici non spécifiée (::, à rapprocher en IP v4 de l'adresse 0.0.0.0) ;
  • l'adresse de destination est intéressante : ff02::1:ff37:73e9. Il s'agit d'une adresse de diffusion (multicast) dont nous étudierons le détail plus loin.

Il n'y a pas de réponse à ce message, ce qui veut dire que l'adresse convoitée n'est pas en usage sur le lien local. Notre hôte adopte donc l'adresse :

fe80::20d:88ff:fe37:73e9

construite comme nous l'avons vu plus haut.

Viennent ensuite trois messages de type « Router solicitation » (découverte de routeurs) qui restent sans réponse, ce qui est rassurant, puisqu'il n'y en a pas sur notre réseau embryonnaire.

Voyons plus en détail la première trame :

Frame 1 (78 bytes on wire, 78 bytes captured)
...
Ethernet II, Src: D-Link_37:73:e9 (00:0d:88:37:73:e9), Dst: IPv6-Neighbor-Discovery_ff:37:73:e9 (33:33:ff:37:73:e9)
    Destination: IPv6-Neighbor-Discovery_ff:37:73:e9 (33:33:ff:37:73:e9)
        Address: IPv6-Neighbor-Discovery_ff:37:73:e9 (33:33:ff:37:73:e9)
        .... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
        .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
    Source: D-Link_37:73:e9 (00:0d:88:37:73:e9)
        Address: D-Link_37:73:e9 (00:0d:88:37:73:e9)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
    Type: IPv6 (0x86dd)
Internet Protocol Version 6
    0110 .... = Version: 6
    .... 0000 0000 .... .... .... .... .... = Traffic class: 0x00000000
    .... .... .... 0000 0000 0000 0000 0000 = Flowlabel: 0x00000000
    Payload length: 24
    Next header: ICMPv6 (0x3a)
    Hop limit: 255
    Source: :: (::)
    Destination: ff02::1:ff37:73e9 (ff02::1:ff37:73e9)
Internet Control Message Protocol v6
    Type: 135 (Neighbor solicitation)
    Code: 0
    Checksum: 0x0ad9 [correct]
    Target: fe80::20d:88ff:fe37:73e9 (fe80::20d:88ff:fe37:73e9)

La source (l'hôte qui cherche à s'auto-configurer avec l'IPv6 fe80::20d:88ff:fe37:73e9) dispose de l'adresse MAC 00:0d:88:37:73:e9 et envoie un message ICMP de type: 135 (Neighbor solicitation) sur une adresse de broadcast IPv6 ff02::1:ff37:73e9, ce qui correspond à une adresse MAC multicast de la forme 33:33:ff:37:73:e9.

Si d'aventure, un autre hôte disposait d'une adresse MAC dont les 3 derniers octets seraient 37:73:e9, ce dernier répondrait à la sollicitation en envoyant son adresse IPv6 ainsi que son adresse MAC complète. Dans le cas où l'adresse IPv6 serait identique à celle convoitée par notre poste qui démarre, il y aurait alors conflit et l'auto-configuration ne pourrait se faire.

Neighbor advertisement

Vous aimeriez ben savoir ce qu'il se passerait si, par un hasard extraordinaire, l'adresse construite à partir de l'adresse MAC était déjà en service sur le lien ? Rien de plus simple ! Faisons la manip. Nous allons exploiter la possibilité du multi-adressage d'un nœud pour attribuer à la machine « espion » l'adresse convoitée par le nouvel arrivant.

Sur la machine munie du « Wireshark » (la commande « ip -6 » fonctionne avec IP v6 exactement comme la commande « ip » le fait avec IP v4) :

# ip -6 addr add fe80::20d:88ff:fe37:73e9/64 dev eth0

Vérification :

# ifconfig eth0
eth0      Lien encap:Ethernet  HWaddr 00:10:B5:40:B7:04  
          adr inet6: fe80::210:b5ff:fe40:b704/64 Scope:Lien
          adr inet6: fe80::20d:88ff:fe37:73e9/64 Scope:Lien
...

Voyons maintenant le démarrage de notre cobaye :

No.     Time        Source                   Destination           Protocol Info
      1 0.000000    ::                       ff02::1:ff37:73e9     ICMPv6   Neighbor solicitation
      2 0.000077    fe80::20d:88ff:fe37:73e9 ff02::1               ICMPv6   Neighbor advertisement

Si la première trame est identique au cas précédent, nous observons ici une réponse « Neighbor advertisement » de fe80::20d:88ff:fe37:73e9 (l'adresse que nous avons manuellement ajoutée à notre espion). Le processus s'arrête là, il n'y a pas de découverte de routeurs et pour cause, notre cobaye n'a pu auto-configurer son interface.

Voyons le détail de la trame 2 :

Frame 2 (86 bytes on wire, 86 bytes captured)
...
Ethernet II, Src: AcctonTe_40:b7:04 (00:10:b5:40:b7:04), Dst: IPv6-Neighbor-Discovery_00:00:00:01 (33:33:00:00:00:01)
    Destination: IPv6-Neighbor-Discovery_00:00:00:01 (33:33:00:00:00:01)
        Address: IPv6-Neighbor-Discovery_00:00:00:01 (33:33:00:00:00:01)
        .... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
        .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
    Source: AcctonTe_40:b7:04 (00:10:b5:40:b7:04)
        Address: AcctonTe_40:b7:04 (00:10:b5:40:b7:04)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
    Type: IPv6 (0x86dd)
Internet Protocol Version 6
    0110 .... = Version: 6
    .... 0000 0000 .... .... .... .... .... = Traffic class: 0x00000000
    .... .... .... 0000 0000 0000 0000 0000 = Flowlabel: 0x00000000
    Payload length: 32
    Next header: ICMPv6 (0x3a)
    Hop limit: 255
    Source: fe80::20d:88ff:fe37:73e9 (fe80::20d:88ff:fe37:73e9)
    Destination: ff02::1 (ff02::1)
Internet Control Message Protocol v6
    Type: 136 (Neighbor advertisement)
    Code: 0
    Checksum: 0x72ec [correct]
    Flags: 0xa0000000
        1... .... .... .... .... .... .... .... = Router
        .0.. .... .... .... .... .... .... .... = Not adverted
        ..1. .... .... .... .... .... .... .... = Override
    Target: fe80::20d:88ff:fe37:73e9 (fe80::20d:88ff:fe37:73e9)
    ICMPv6 Option (Target link-layer address)
        Type: Target link-layer address (2)
        Length: 8
        Link-layer address: 00:10:b5:40:b7:04

Notre espion signale par un message ICMP de type 136 que l'adresse IPv6 fe80::20d:88ff:fe37:73e9 est attachée à l'interface dont l'adresse MAC est 00:10:b5:40:b7:04. Ce message est envoyé à tous les hôtes du réseau (ff02::1, ce qui correspond à l'adresse MAC multicast 33:33:00:00:00:01). Notre postulant à l'adresse IPv6 fe80::20d:88ff:fe37:73e9 en est donc informé.

Voyons l'état de la configuration IP v6 du cobaye :

2: eth0:  mtu 1500 qlen 1000
    inet6 fe80::20d:88ff:fe37:73e9/64 scope link tentative
       valid_lft forever preferred_lft forever

Le « scope link » que nous observions tout à l'heure s'est transformé en « scope link tentative ». Autrement dit, cette adresse ne sera pas exploitable, l'hôte n'est pas configuré.

Moralité : En cas de duplication d'adresse, le processus d'auto-configuration montre ses limites. Dans un tel cas, nous devrons résoudre manuellement le conflit.

Notez aussi au passage que tout ceci ressemble furieusement à ce que fait ARP en IPv4. Mais ici, c'est de l'ICMP.

Avec deux interfaces

A priori, il n'y a pas de problèmes, dans la mesure où la construction de l'adresse se fait à partir de l'adresse MAC. Nous devrions trouver deux adresses IPv6 différentes :

eth0      Link encap:Ethernet  HWaddr 00:10:b5:40:b7:04  
          adr inet6: fe80::210:b5ff:fe40:b704/64 Scope:Lien
...

eth1      Link encap:Ethernet  HWaddr 00:0c:6e:63:e6:ed  
          inet adr:192.168.10.30  Bcast:192.168.10.255  Masque:255.255.255.0
          adr inet6: fe80::20c:6eff:fe63:e6ed/64 Scope:Lien
...

C'est bien, c'est comme on avait prévu :-)

Et les routes ?

Il y a plusieurs façons d'afficher les routes IPv6, dont la classique commande « route », avec quelques aménagements :

~# route -A inet6
Table de routage IPv6 du noyau
Destination                    Next Hop                   Flag Met Ref Use If
::1/128                        ::                         Un   0   1     4 lo
fe80::/128                     ::                         Un   0   2     0 lo
fe80::/128                     ::                         Un   0   2     0 lo
fe80::20c:6eff:fe63:e6ed/128   ::                         Un   0   1     0 lo
fe80::210:b5ff:fe40:b704/128   ::                         Un   0   1     0 lo
fe80::/64                      ::                         U    256 0     0 eth1
fe80::/64                      ::                         U    256 0     0 eth0
ff00::/8                       ::                         U    256 0     0 eth1
ff00::/8                       ::                         U    256 0     0 eth0
::/0                           ::                         !n   -1  1     1 lo

Pour l'instant contentons-nous de noter ceci : la route pour fe080::/64 peut passer aussi bien par eth0 que par eth1…

Un petit ping...

Nous avons sur un même lien local deux nœuds auto-configurés en IPv6 :

  • l'un dispose de l'adresse fe80::20c:6eff:fe63:e6ed ;
  • l'autre de l'adresse fe80::21b:11ff:fe52:bfab (sur eth0).

Depuis ce dernier nœud, nous tentons un ping (ipv6) sur fe80::20c:6eff:fe63:e6ed :

~$ ping6 -c4 fe80::20c:6eff:fe63:e6ed
connect: Invalid argument

Pourquoi tant de haine ?

La remarque préalable sur les routes n'a pas été faite par hasard. Avec les adresses de type lien local, il faut préciser sur quelle interface nous désirons travailler. La commande ping6 propose diverses syntaxes. La plus courte est sans doute :

ping 6 <adresse de la cible>%ethx

Voyons ceci :

:~$ ping6 -c4 fe80::20c:6eff:fe63:e6ed%eth0
PING fe80::20c:6eff:fe63:e6ed%eth0(fe80::20c:6eff:fe63:e6ed) 56 data bytes
64 bytes from fe80::20c:6eff:fe63:e6ed: icmp_seq=1 ttl=64 time=3.54 ms
64 bytes from fe80::20c:6eff:fe63:e6ed: icmp_seq=2 ttl=64 time=0.121 ms
64 bytes from fe80::20c:6eff:fe63:e6ed: icmp_seq=3 ttl=64 time=0.123 ms
64 bytes from fe80::20c:6eff:fe63:e6ed: icmp_seq=4 ttl=64 time=0.120 ms

--- fe80::20c:6eff:fe63:e6ed%eth0 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.120/0.976/3.543/1.482 ms

Nettement plus efficace. Nous verrons plus loin que cette limitation n'intervient pas avec des adresses de type global.