Date created: 01/28/20 08:47:42. Last modified: 03/30/20 16:10:34

IPv6 Addressing on Linux

References:

https://en.wikipedia.org/wiki/Unique_local_address

 

Contents:
IPv6 LLAs and ULAs
Ubuntu IPv6 Address Assignment / IPv6 Privacy Extensions
Linux IPv6 Address Flags and Types
Disabling SLAAC on Linux
Neighbor Discovery Protocol on Linux

IPv6 LLAs and ULAs

Originally in RFC3513 "Internet Protocol Version 6 (IPv6) Addressing Architecture" which was later superseded by RFC4291 "IP Version 6 Addressing Architecture", the prefix fe80::/10 (from fe80:: to febf::) was assigned for link local addresses.

 

RFC4193 "Unique Local IPv6 Unicast Addresses" reserves the prefix fc00::/7 for ULAs (Unique Local Addresses).

Originally fec0::/10 was allocated by IANA but later deprecated in RFC3897 "Deprecating Site Local Addresses".

fc00::/7 (from fc00:: to fdff::) is divided into two parts, fc00::/8 (from fc00:: to fcff::) and fd00::/8 (fd00:: to fdff::) with fc00::/8 being undefined.

fd00::/8 is defined for /48 prefixes, formed by setting the forty bits of the prefix following "fd" to a randomly generated bit string. This results in the format fdxx:xxxx:xxxx::/48.

 

Ubuntu IPv6 Address Assignment

By default Ubuntu 18 uses RFC4941 "Privacy Extensions for Stateless Address Autoconfiguration in IPv6" for ULA  auto assignment.

This can be configured using the following options:

# Check the specific interface "wlp3s0":
$ cat /proc/sys/net/ipv6/conf/wlp3s0/use_tempaddr
2
# Check for all interfaces:
$ cat /proc/sys/net/ipv6/conf/all/use_tempaddr
2
$ cat /proc/sys/net/ipv6/conf/default/use_tempaddr
2

# Preference for Privacy Extensions (RFC3041):
# <= 0 : disable Privacy Extensions
# == 1 : enable Privacy Extensions, but prefer public addresses over temporary addresses.
# > 1 : enable Privacy Extensions and prefer temporary addresses over public addresses.

# Disable on all interfaces
sudo sysctl -w net.ipv6.conf.all.use_tempaddr=0
sudo sysctl -w net.ipv6.conf.default.use_tempaddr=0
# or disable on a specific interface:
sudo sysctl -w net.ipv6.conf.wlp3s0.use_tempaddr=0


# If privacy extensions are desired the preferred and valid lifetimes can be set with the following options:

# Preferred lifetime (in seconds) for temporary addresses. Default: 86400 (1 day)
$ cat /proc/sys/net/ipv6/conf/wlp3s0/temp_prefered_lft
86400

# Valid lifetime (in seconds) for temporary addresses. Default: 604800 (7 days)
$ cat /proc/sys/net/ipv6/conf/wlp3s0/temp_valid_lft
604800

When using NetworkManager, in order to disable IPv6 privacy extensions the NetworkManager config file for the specific SSID (if using wireless) or wired network profile needs to be edited:

$ sudo cat /etc/NetworkManager/system-connections/Wired\ connection\ 1
$ sudo cat /etc/NetworkManager/system-connections/WiFi-SSID-Name-Here

# This enables IPv6 privacy extensions
[ipv6]
addr-gen-mode=stable-privacy

# This disabled IPv6 privacy extensions
[ipv6]
addr-gen-mode=eui65

By default Ubuntu hosts using IPv6 privacy extensions will periodically assign a new ULA when the currently assigned address expires, as can be seen below:

$ ifconfig wlp3s0
wlp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.123 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fd3f:3c12:7f10:0:f1d3:cad1:76e1:465 prefixlen 64 scopeid 0x0<global>
inet6 aaaa:bbbb:cccc:dddd:d3d6:3f2c:2f50:11f1 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:67a2:17d3:418c:22c4 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:d71:4b62:3f16:3ed8 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:982f:1ac8:a91f:47e4 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:10f0:ff95:6719:26e9 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:2157:fd0d:af56:aa60 prefixlen 64 scopeid 0x0<global>
inet6 fd3f:3c12:7f10:0:8527:60c3:de21:57d4 prefixlen 64 scopeid 0x0<global>
inet6 fe80::b63c:f6bc:112d:ed9d prefixlen 64 scopeid 0x20<link>
inet6 fd3f:3c12:7f10:0:8953:910:12f2:e6a4 prefixlen 64 scopeid 0x0<global>
ether 24:0a:64:50:5a:5f txqueuelen 1000 (Ethernet)
RX packets 33939971 bytes 44941430309 (44.9 GB)
RX errors 0 dropped 1 overruns 0 frame 0
TX packets 14808401 bytes 9011369958 (9.0 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

iproute2 shows the valid_lft and preferred_ldt seconds remaining (below output recorded much later after a reboot):

$ ip addr show wlp3s0
5: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 24:0a:64:50:5a:5f brd ff:ff:ff:ff:ff:ff
inet 192.168.0.123/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp3s0
valid_lft 75374sec preferred_lft 75374sec
inet6 fd3f:3c12:7f10:0:8f6:9f6d:fef6:e3aa/64 scope global temporary dynamic
valid_lft 602717sec preferred_lft 83774sec
inet6 aaaa:bbbb:cccc:dddd:d3d6:3f2c:2f50:11f1/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 1801sec preferred_lft 1801sec
inet6 fd3f:3c12:7f10:0:8594:54da:3c09:d38c/64 scope global temporary deprecated dynamic
valid_lft 516860sec preferred_lft 0sec
inet6 fd3f:3c12:7f10:0:67a2:17d3:418c:22c4/64 scope global mngtmpaddr noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::b63c:f6bc:112d:ed9d/64 scope link noprefixroute
valid_lft forever preferred_lft forever

After disabling privacy extensions, all addresses are EUI64 based addresses:

$ ip -6 a show scope link dev wlp3s0
5: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fe80::b63c:f6bc:112d:ed9d/64 scope link noprefixroute
valid_lft forever preferred_lft forever

$ sudo ip -6 addr flush scope link dev wlp3s0

$ ip -6 a show scope link dev wlp3s0
5: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fe80::260a:64ff:fe50:5a5f/64 scope link noprefixroute
valid_lft forever preferred_lft forever

 

Linux IPv6 Address Flags and Types

"ip -6 addr show scope" has the following options:

  • global - the address is globally valid
  • site - (IPv6 only) the address is site local, i.e. it is valid inside this site/LAN
  • link - the address is link local, i.e. it is valid only on this device and it's neighbour (e.g. FE80::/10)
  • host - the address is valid only inside this host (e.g. loopback)

The flags show against the various address has the following meanings:

  • dynamic - only list addresses installed due to stateless address configuration (IPv6 only) or DHCP (IPv4)
  • permanent - only list permanent (not dynamic) addresses
  • deprecated - (IPv6 only) only list deprecated addresses
  • dadfailed - (IPv6 only) only list addresses which have failed duplicate address detection
  • temporary - (IPv6 only) only list temporary addresses
  • primary and secondary - only list primary (or secondary) addresses
  • home - (IPv6 only) designates this address is the "home address" as defined in RFC 6275
  • mngtmpaddr - (IPv6 only) make the kernel manage temporary addresses created from this one as a template on behalf of Privacy Extensions (RFC3041). For this to become active, the use_tempaddr sysctl setting has to be set to a value greater than zero. The given address needs to have a prefix length of 64. This flag allows to use privacy extensions in a manually configured network, just like if stateless auto-configuration was active.
  • nodad - (IPv6 only) do not perform Duplicate Address Detection (RFC 4862) when adding this address
  • noprefixroute - Do not automatically create a route for the network prefix of the added address, and don't search for one to delete when removing the address. Changing an address to add this flag will remove the automatically added prefix route, changing it to remove this flag will create the prefix route automatically.

In the following scenario the LAN default gateway has had it's ULA range changed to fd:0:0:1::/64, the Ubuntu host has addressed it's self in the new ULA range but still has addresses in the old range too. These can be cleared as follows:

$ ip -6 addr show scope global dev wlp3s0
5: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fd::1:39a4:4d67:61c0:fdcd/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 2591917sec preferred_lft 604717sec
inet6 fd3f:3c12:7f10:1:44d5:af0:201:dfe9/64 scope global temporary deprecated dynamic
valid_lft 489656sec preferred_lft 0sec
inet6 fd3f:3c12:7f10:1:94d8:8da6:2f79:dc58/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 2589932sec preferred_lft 602732sec
inet6 fd3f:3c12:7f10:0:44d5:af0:201:dfe9/64 scope global temporary deprecated dynamic
valid_lft 489493sec preferred_lft 0sec
inet6 fd3f:3c12:7f10:0:67a2:17d3:418c:22c4/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 2476692sec preferred_lft 489492sec

$ sudo ip -6 addr flush scope global dev wlp3s0

$ ip -6 addr show scope global dev wlp3s0
5: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fd::1:39a4:4d67:61c0:fdcd/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 2591946sec preferred_lft 604746sec

 

Disabling SLAAC on Linux

SLAAC can be disabled by disabling the acceptance of NDP Router Advertisement messages, for all interfaces or per interface, and can be read from the accept_ra file:

$ cat /proc/sys/net/ipv6/conf/all/accept_ra
1
$ cat /proc/sys/net/ipv6/default/all/accept_ra
1
$ cat /proc/sys/net/ipv6/conf/wlp3s0/accept_ra
1

# Disable on all interfaces
sudo sysctl -w net.ipv6.conf.all.accept_ra=0
sudo sysctl -w net.ipv6.conf.default.accept_ra=0
# or disable on a specific interface:
sudo sysctl -w net.ipv6.conf.wlp3s0.accept_ra=0

 

Neighbor Discovery Protocol on Linux

A host will send a multicast Neighbor Solicitation message with the all-zeros source IPv6 address "::" to the IPv6 all nodes IPv6 multicast destination address, ff02::1. The frame will have a destination MAC address in the IPv6 multicast MAC range (33:33:00:00:00:00 through to 33:33:FF:FF:FF:FF), with the lowest 32-bits set to the lowest 32-bits of the destination IPv6 address. The source MAC address is the unicast MAC of the sending host.

The destination IPv6 address used is ff02::1:ff37:77b9. The destination MAC address becomes 33:33:ff:37:77:b9.

A Router Solicitation message is sent from the host to the all routers IPv6 multicast destination address, ff02::2. The source IPv6 address in the Router Solicitation message is the host's self assigned link local IPv6 address. The destination IPv6 multicast MAC address contains the lowest 32-bits of the destination IPv6 address and become 33:33:00:00:00:02. The source MAC address is the unicast MAC of the sending host.