IPv6 addressing, dynamic prefix static local part

There are two ways to do this. One is the easy way and one is the hard way.

The easy way is to run a DHCPv6 server on your network and assign host addresses to each device yourself. Or let the server pick the host part; the DHCPv6 servers I have seen will keep the same host part even if the prefix changes.

The hard way is to use ip token to set tokenized interface identifiers. This is described as:

IPv6 tokenized interface identifier support is used for assigning well-known host-part addresses to nodes whilst still obtaining a global network prefix from Router advertisements. The primary target for tokenized identifiers are server platforms where addresses are usually manually configured, rather than using DHCPv6 or SLAAC. By using tokenized identifiers, hosts can still determine their network prefix by use of SLAAC, but more readily be automatically renumbered should their network prefix change. Tokenized IPv6 Identifiers are described in the draft: <draft-chown-6man-tokenised-ipv6-identifiers-02>.

The reason this is the hard way is that while Linux includes this functionality, no Linux distribution I'm aware of includes support for making such a configuration persistent and applying it at boot time, as they do for manual or DHCP configured addresses. So it is probably not going to work very well for you, until some distribution does so. Note that it is now possible to configure IPv6 tokens in NetworkManager and systemd-networkd; more recent answers have specific configuration instructions.

Finally, if your ISP is occasionally changing your prefix, consider using Unique Local Addresses within your network. This way, all of your devices will always have an address that will never change, with which they can talk to each other. Some IPv6-supporting home/SOHO routers (such as OpenWrt) have an option to enable ULA across the entire home network; if there are multiple routers in the home, this should be enabled on the router which connects to the ISP.

Michael did a very good summary and plugwash's recent tip was the best I could find after hunting for several hours for a CentOS 7/RHEL (also systemd and network manager) solution. After getting used to nmcli (I was mainly still using ifcfg and ip) - I could successfully apply it.

But digging deeper according to https://developer.gnome.org/NetworkManager/stable/settings-ipv6.html NetworkManager directly supports IPv6 tokenized interface identifiers as a property (from release 1.4 August 2016 http://news.softpedia.com/news/networkmanager-1-4-adds-support-for-setting-ipv6-tokenized-interface-identifiers-507601.shtml).

So you don't need to set network manager IPv6 settings to ignore but you should set the settings to

nmcli connection modify eth0 ipv6.method "auto" # if not already
nmcli connection modify eth0 ipv6.addr-gen-mode "eui64" # use interface token
nmcli connection modify eth0 ipv6.token "::2"

which will write IPV6_TOKEN=::2 to /etc/sysconfig/network-scripts/ifcfg-eth0 to survive a reboot. To immediate apply this restart the interface by

nmcli connection up id eth0  # restart

Thanks to Michael for confirming that Linux supported the feature and pointing at the the low-level command. This answer covers how to make it work in practice on a Debian stretch desktop (with systemd and network-manager).

First edit the connection in network manager and set the IPv6 settings to ignore.

Now create a file /etc/NetworkManager/dispatcher.d/pre-up.d/iptoken . The file should be owned by root, permissions 755 and with the following contents.

ip token set ::2 dev eth0

Replace eth0 with the device you want and ::2 with the suffix you want.