IPv6 Source Address Selection on Ubuntu
Have outgoing IPv6 address on an interface selected deterministically, could be desirable.
Linux will use as default the latest address added to the interface as the source address, this is generally not the optimal solution.
Linux implements RFC 3484, “Default Address Selection for Internet Protocol version 6 (IPv6)”.
Briefly, the algorithm involves building a candidate list of potential source addresses, then following these rules in order:
Prefer same address.
Prefer appropriate scope.
Avoid deprecated addresses.
Prefer home addresses.
Prefer outgoing interface.
Prefer matching label.
Prefer public addresses.
Use longest matching prefix.
“If the eight rules fail to choose a single address, some unspecified tie-breaker should be used.” Linux chooses to use the latest address added.
To influence this algorithm, it is necessary to influence one of previous rules, for example is possible to mark unwanted source addresses as “deprecated”, causing them to fail rule no 3.
The method to implement this under Linux is to set preferred_lft to 0, thus causing the address to be marked as deprecated. (deprecation doesn’t make the address invalid, so you can still receive packets destined for that address, but it just won’t be used as source-adddres).
For an address already added to the interface, use ip addr change (XXXX:XXXX:XXXX::XX/YY is the IPv6 Address in use, eth0 is the interface):
ip -6 addr change XXXX:XXXX:XXXX::XX/PL dev eth0 preferred_lft 0
To add a new address, set preferred_lft contextually:
ip addr add XXXX:XXXX:XXXX::XX/PL dev eth0 preferred_lft 0
Configuration can also be done automatically during networking start-up, for example in newer Ubuntu versions:
iface eth0 inet6 static address XXXX:XXXX:XXXX::XX/PL up ip addr add YYYY:YYYY:YYYY::YY/PL label eth0:01 dev eth0 preferred_lft 0