Skip to content

IPv6 Link-local

Time: 30 min

Needs: two OL9 PCs on one Ethernet switch

GNS3 project: ipv6-a1-linklocal

Info

Times listed are approximate and provided as timing guidelines only. Take as much time as you need to complete the activity.

Question

Where does a connected host get its IPv6 addresses from?


Do this — Build it

Cable two OL9 PC nodes named H1 and H2 to an Ethernet Switch (SW) and start the nodes.

On H1:

nmcli con add type ethernet ifname eth0 con-name eth0
nmcli con mod eth0 ipv4.method manual ipv4.addresses 192.168.10.11/24
nmcli con up eth0

On H2:

nmcli con add type ethernet ifname eth0 con-name eth0
nmcli con mod eth0 ipv4.method manual ipv4.addresses 192.168.10.12/24
nmcli con up eth0

On both H1 and H2, run this:

ip -6 addr show dev eth0

What just happened

  • Both hosts have IPv6 addresses that you never configured.
  • The addresses are prefixed with fe80::. Every IPv6 interface gets one of these automatically, always, for as long as the link is up. It is called a link-local address, and IPv6 requires one
    • Link means the address is valid only for this segment.
    • Local means packets using the address are not routed.
    • Link-local addresses exist so that hosts sharing a wire can communicate before any "real" address has been configured - which turns out to be a prerequisite for everything else IPv6 does.

Do this — use it

Copy H2's link-local address, then ping in from H1: Read H2's link-local address the same way, then from H1:

ping -c2 fe80::XXXX:XXXX:XXXX:XXXX

This fails. ping needs more information than just the address. Try this:

ping -c2 fe80::XXXX:XXXX:XXXX:XXXX%eth0

What just happened

  • The address alone was not enough information to send a packet. The reason is because the fe80::/64 prefix is used by every interface (on hosts with more than one interface) so you need to tell ping out of which interface the packet should be sent out.
  • %eth0 is called scope identifier and it is used to disambiguate. It is a way to tell the host which interface to use when sending a packet. This matters only for link-local addresses.
  • You could also have run the command like so: ping -I eth0 -c1 fe80::XXXX:XXXX:XXXX:XXXX

Do this

On H1:

nmcli con modify eth0 ipv6.addr-gen-mode eui64
nmcli con up eth0

ip link show eth0 | grep ether
ip -6 addr show dev eth0 | grep fe80

What just happened

  • Notice the similarily between the MAC address the auto-configured IPv6 address
  • EUI64 is one of the method devices can use to configure their own IPv6 addresses. It lets devices derive the last 64 bits directly from the MAC address like so:
    • split the six bytes in half
    • insert the bits ff:fe in the middle
    • flip the 2nd bit (from the right) in the first byte.
  • That was the original scheme, and it has an obvious problem; it is bad for privacy. Since your interface ID is built from your MAC address, it becomes a globally unique serial number that can be traced back to every network you join.
  • So modern systems default to stable-privacy: an interface ID that is stable per network but different on each one, and computed from a stored secret key rather than from hardware.
  • Put it back:
    nmcli con mod eth0 ipv6.addr-gen-mode stable-privacy
    nmcli con up eth0
    

Do this

Start a capture on the H1 link, the ping H2 over both IPv4 and IPv6.

Select one ICMP packet and one ICMP6 packet and examine them closely. Can you describe what's different between them?

What just happened

  • Up to Layer 2, both packets are similar.
  • The frame's EtherType shows that Ethernet can carry both IPv4 and IPv6 with no changes to the frame's structure
  • Above Ethernet, each protocol has their own header structure. Compare them; the differences are instructive.

Record

Prefix of link-local addresses
Where the interface ID comes from under eui64
Why stable-privacy replaced it
EtherType for IPv4 / for IPv6