Additional info can be found at
Karl Auer's Blog: Controlling IPv6 source address selection , IPv6 Source Address Selection - what, why, how
Name to IPv4 or IPv6 address resolving is usually done using a libc resolver library. Usually the function getaddrinfo is used for that. In case of more than one IPv6 address is returned, according to RFC 3484 / Default Address Selection for Internet Protocol version 6 a sorting should be applied, which can be optionally configured.
The “magic” is controlled by a file named /etc/gai.conf (it can be that it is empty or missing by default). Default is usually somewhere stored in documentation, see “man gai.conf” or e.g. /usr/share/doc/glibc-common/gai.conf.
For controlling sort order by configuration following are needed for testing:
A host in DNS returning more than one IPv6 address, e.g.
$ dig +short aaaa st1.bieringer.de 2001:4dd0:ff00:834::2 2a01:238:423d:8800:85b3:9e6b:3019:8909 |
Lookup via DNS (/etc/hosts won't work)
/etc/gai.conf with proper config, e.g.
precedence ::1/128 50 # default precedence ::/0 40 # default precedence 2002::/16 30 # default precedence ::/96 20 # default precedence ::ffff:0:0/96 10 # default precedence 2001:4dd0:ff00:834::/64 80 # dst-A precedence 2a01:238:423d:8800::/64 90 # dst-B |
For tests use e.g. telnet client
$ telnet st1.bieringer.de Trying 2a01:238:423d:8800:85b3:9e6b:3019:8909... (dst-B) ... Trying 2001:4dd0:ff00:834::2... (dst-A) ... |
If precedence is changed in configuration
precedence 2001:4dd0:ff00:834::/64 90 # dst-A ex 80 precedence 2a01:238:423d:8800::/64 80 # dst-B ex 90 |
The order is changed accordingly
$ telnet st1.bieringer.de Trying 2001:4dd0:ff00:834::2... (dst-A) ... Trying 2a01:238:423d:8800:85b3:9e6b:3019:8909... (dst-B) ... |
Source address selection in Linux is done automatically by kernel and usually only using information from routing tables and try to match the same scope of address.
With extension of internal “ip addrlabel” a source address can be bound to a destination address (e.g. selected via mechanisms above). Binding means here: “same label” (label is a number).
Default of “ip addrlabel” (here on CentOS 6):
# ip addrlabel prefix ::1/128 label 0 prefix ::/96 label 3 prefix ::ffff:0.0.0.0/96 label 4 prefix 2001::/32 label 6 prefix 2001:10::/28 label 7 prefix 2002::/16 label 2 prefix fc00::/7 label 5 prefix ::/0 label 1 |
System is multihomed (here on one interface), router provides 2 prefixes via radvd:
# ip -6 addr show dev eth1 | grep -w inet6 |grep -w global inet6 2001:6f8:12d8:2:5054:ff:fefb:6582/64 scope global dynamic inet6 2001:6f8:900:8cbc:5054:ff:fefb:6582/64 scope global dynamic |
Connect now to server (shown above)
$ telnet st1.bieringer.de Trying 2001:4dd0:ff00:834::2... (dst-A) ... Trying 2a01:238:423d:8800:85b3:9e6b:3019:8909... (dst-B) ... |
Related tcpdump with filter “tcp and dst port 23” shows only the use of the upper local source IPv6 address
IP6 2001:6f8:12d8:2:5054:ff:fefb:6582.37762 > 2001:4dd0:ff00:834::2.telnet: (src-A -> dst-A) IP6 2001:6f8:12d8:2:5054:ff:fefb:6582.45754 > 2a01:238:423d:8800:85b3:9e6b:3019:8909.telnet: (src-A -> dst-B) |
Binding now source and destination with “ip addrlabel”
# ip addrlabel add prefix 2001:6f8:12d8:2::/64 label 200 # ip addrlabel add prefix 2001:6f8:900:8cbc::/64 label 300 # ip addrlabel add prefix 2001:4dd0:ff00:834::/64 label 200 # ip addrlabel add prefix 2a01:238:423d:8800::/64 label 300 |
Resulting “ip addrlabel”
# ip addrlabel prefix ::1/128 label 0 prefix ::/96 label 3 prefix ::ffff:0.0.0.0/96 label 4 prefix 2a01:238:423d:8800::/64 label 300 # dst-B prefix 2001:4dd0:ff00:834::/64 label 200 # dst-A prefix 2001:6f8:900:8cbc::/64 label 300 # src-B prefix 2001:6f8:12d8:2::/64 label 200 # src-A prefix 2001::/32 label 6 prefix 2001:10::/28 label 7 prefix 2002::/16 label 2 prefix fc00::/7 label 5 prefix ::/0 label 1 |
Connect now to server again
$ telnet st1.bieringer.de Trying 2001:4dd0:ff00:834::2... (dst-A) ... Trying 2a01:238:423d:8800:85b3:9e6b:3019:8909... (dst-B) ... |
Related tcpdump with filter “tcp and dst port 23” shows now the use of both local source IPv6 addresses according to the configured pairs A and B
IP6 2001:6f8:12d8:2:5054:ff:fefb:6582.37765 > 2001:4dd0:ff00:834::2.telnet: (src-A -> dst-A) IP6 2001:6f8:900:8cbc:5054:ff:fefb:6582.39632 > 2a01:238:423d:8800:85b3:9e6b:3019:8909.telnet: (src-B -> dst-B) |
Setup of persistent “ip addrtable” is probably currently not supported by Linux distributions, so extension of network init scripts or rc.local must be used for that. A script which uses information from /etc/gai.conf and configure “ip addrtable” accordingly can be found here: /etc/gai.conf - it ain't what you think it is