IPv6 global address
The global address is used in IPv6 to communicate with the outside world. This is thus the one that is used as source for any communication and thus in a way identify you on Internet.
Below is a dump of an interface configuration:
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:22:15:64:42:bd brd ff:ff:ff:ff:ff:ff inet6 2a01:f123:1234:5bd0:222:15ff:fe64:42bd/64 scope global dynamic valid_lft 86314sec preferred_lft 86314sec inet6 fe80::222:15ff:fe64:42bd/64 scope link valid_lft forever preferred_lft forever
The global address is here 2a01:f123:1234:5bd0:222:15ff:fe64:42bd/64. It is build by using the prefix and adding an identifier build with the hardware address. For example, here the hardware address is 00:22:15:64:42:bd and the global IPv6 address is ending with 22:15ff:fe64:42bd.
It is thus easy to go from the IPv6 global address to the hardware address. To fix this issue and increase the privacy of network user, privacy extensions have been developed.
The RFC 3041 describes how to build and use temporary addresses that will be used as source address for connection to the outside world.
To activate this feature, you simply have to modify an entry in /proc. For example to activate the feature on eth0, you can do
The usage of the option is detailled in the must-read ip-sysctl.txt file:
use_tempaddr - INTEGER 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. Default: 0 (for most devices) -1 (for point-to-point devices and loopback devices)
After network restart (a simple ifdown, ifup of the interface is enough), the output of the ip a command looks like that:
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:22:15:64:42:bd brd ff:ff:ff:ff:ff:ff inet 192.168.1.129/24 brd 192.168.1.255 scope global eth0 inet6 2a01:f123:1234:5bd0:21f1:f624:d2b8:3702/64 scope global temporary dynamic valid_lft 86314sec preferred_lft 2914sec inet6 2a01:f123:1234:5bd0:222:15ff:fe64:42bd/64 scope global dynamic valid_lft 86314sec preferred_lft 86314sec inet6 fe80::222:15ff:fe64:42bd/64 scope link valid_lft forever preferred_lft forever
A new temporary address has been added. After preferred_lft seconds, it becomes deprecated and a new address is added:
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:22:15:64:42:bd brd ff:ff:ff:ff:ff:ff inet 192.168.1.129/24 brd 192.168.1.255 scope global eth0 inet6 2a01:f123:1234:5bd0:55c3:7efd:93d1:5057/64 scope global temporary dynamic valid_lft 85009sec preferred_lft 1672sec inet6 2a01:f123:1234:5bd0:21f1:f624:d2b8:3702/64 scope global temporary deprecated dynamic valid_lft 82077sec preferred_lft 0sec inet6 2a01:f123:1234:5bd0:222:15ff:fe64:42bd/64 scope global dynamic valid_lft 86398sec preferred_lft 86398sec inet6 fe80::222:15ff:fe64:42bd/64 scope link valid_lft forever preferred_lft foreverr
The deprecated address is removed when the valid_lft counter reach zero second.
Some more tuning
The default duration for a prefered adress is of one day. This can be changed by modifying the temp_prefered_lft variable.
For example, you can add to sysctl.conf:
net.ipv6.conf.eth0.temp_prefered_lft = 7200
The default validity length of the addresses can be changed via the temp_valid_lft variable.
The max_desync_factor set the max random time to wait before asking a new address. This is used to avoid that all computers in network ask for an address at the same time.
On side effect is that if you set the prefered or valid time to a low value, the max_desync_factor must also be decreased. If not, there will be long time period without temporary address.
If temp_prefered_lft is multiple time lower than temp_valid_lft, then the deprecated addresses will accumulate. To avoid overloading the kernel, a maximum number of addresses is set.
Equal to 16 by default, it can be changed by setting the max_addresses sysctl variable.
Known issues and problems
As the temporary address is used for connection to the outside and has a limited duration, some long duration connections (tink ssh) will be cut when the temporary address is removed.
I’ve also observed a problem when the maximum number of addresses is reached:
ipv6_create_tempaddr(): retry temporary address regeneration. ipv6_create_tempaddr(): regeneration time exceeded. disabled temporary address support.
The result was that the temporary address support was disabled and the standard global address was used again. When setting temp_prefered_lft to 3600 and keeping temp_valid_ft to default value, the problem is reproduced easily.
The support of IPv6 privacy extensions is correct but the lack of link with existing connection can cause the some services to be disrupted. A easy to use per-software selection of address could be really interesting to avoid these problems.
6 thoughts on “IPv6 privacy extensions on Linux”
Software with long running connections should allow to prefer permanent address
https://bugzilla.redhat.com/show_bug.cgi?id=512032 discusses it for openssh but I would prefer it to be a config option
Very interesting Pascal, I did not known about the socket option:
int value = IPV6_PREFER_SRC_PUBLIC;
setsockopt(socket, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &value, sizeof(value));
It is no longer RFC 3041 but, since 2008, RFC 4941. The biggest change between the two RFC is the new requirment that privacy addresses are off by default.
See also RFC 5014 which describes the API for applications to choose whether they prefer public/temporary addresses. It seems Linux has implemented it for
setsockopt(s, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, ...), but not for the hints in
The pathname /proc/sys/net/ipv6/conff/eth0/use_tempaddr is incorrect (conff instead of conf) (at least on Ubuntu)