Yesterday somebody asked me about provider-independent addresses in IPv6,
because of the old 'renumbering sucks' reason. At that moment I did remember
that there is a sort-of provider-independent option, but it is relatively
new and IPv6 purists frown upon it, so you probably will not get a
provider-independent allocation just because you don't like renumbering.
This does show the 'roots' of IPv6 being
in the time when classless inter-domain routing and aggregation were seen as
the best solution for routing table growth. But in the end: renumbering is
not so nice, and can cause interruptions in internal reachability. With full
NAT and just one external address renumber operations never affect internal
services.
But, later I remembered there is a solution in IPv6 for this, because it is
possible to configure multiple addresses on any interface in IPv6,
and outgoing traffic will prefer to reach a service on the same class
of address, with a preference set for each 'type' of address, as listed
in
/etc/gai.conf in Linux. And there are equivalent tables in
other operating systems.
The solution is: assign all clients both a 'unique local'
and a 'global' IPv6 address. The 'global' IPv6 address is the one
which 'may change'. When announcing both address ranges via the
router announce protocol, clients will configure both types.
More about unique local addresses in
Unique local address - Wikipedia English but the important here is that
they are in the
fc00::/7 IPv6 address range.
Publish the
internal-facing services, such as file-servers,
authentication-servers and time-servers with their unique local
address and the
external-facing services such as web-servers with
their global address. Yes, some services will have both type of address.
Views in DNS will help you hide those internal-only services.
Nice theory, but I had to test this! So I calculated an IPv6 unique local
address range using bits of
RFC 4193
Officially,
fd00::/8 is the part in use for 'prefix generated
from random numbers', but I tested with an address in the range
fc00::/8. Little oops and being eager to test things there on my part.
I configured
radvd accordingly in
/etc/radvd.conf:
interface eth0.3
{
AdvSendAdvert on;
prefix ::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvPreferredLifetime 604800;
AdvValidLifetime 2592000;
};
prefix fc5c:2186:e460:2::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvPreferredLifetime 604800;
AdvValidLifetime 2592000;
};
RDNSS 2001:980:14ca:42::694 {
};
};
The prefix :: line is to automatically copy the assignment which
dhcp6c
in prefix-delegation mode adds to it.
This causes the correct configuration on a client:
# ip -6 addr ls dev wlan0
3: wlan0: mtu 1500 qlen 1000
inet6 fc5c:2186:e460:2:21f:e1ff:fe45:2894/64 scope global dynamic
valid_lft 2591560sec preferred_lft 604360sec
inet6 2001:980:14ca:2:21f:e1ff:fe45:2894/64 scope global dynamic
valid_lft 2591560sec preferred_lft 604360sec
inet6 fe80::21f:e1ff:fe45:2894/64 scope link
valid_lft forever preferred_lft forever
I also had to configure the unique local address range on the
home router/server, both as a 'service' IP and a 'network
interface' IP. IPv6 services live on eth0.42, the interface to the wireless
network is eth0.3.
# ip -6 addr add fc5c:2186:e460::694/128 dev eth0.42
# ip -6 addr add fc5c:2186:e460:2::1/64 dev eth0.3
And now I added a service with both type of addresses to DNS, and it works:
$ host resolver
resolver.idefix.net has IPv6 address 2001:980:14ca:42::694
resolver.idefix.net has IPv6 address fc5c:2186:e460::694
$ host www.google.com resolver
Using domain server:
Name: resolver
Address: fc5c:2186:e460::694#53
Aliases:
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 209.85.147.104
www.l.google.com has address 209.85.147.105
www.l.google.com has address 209.85.147.106
www.l.google.com has address 209.85.147.99
www.l.google.com has address 209.85.147.147
www.l.google.com has address 209.85.147.103
www.l.google.com has IPv6 address 2a00:1450:400c:c01::63
That is.. after I added the home unique local range to the acl in
named.conf.options. Which confirms the source address of the
unique local range is used. For a service which shows no unique
local address, the global address is used:
$ host www.google.com resolver.xs4all.nl
Using domain server:
Name: resolver.xs4all.nl
Address: 2001:888:0:6::66#53
Aliases:
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 209.85.147.103
www.l.google.com has address 209.85.147.104
www.l.google.com has address 209.85.147.105
www.l.google.com has address 209.85.147.147
www.l.google.com has address 209.85.147.99
www.l.google.com has address 209.85.147.106
www.l.google.com has IPv6 address 2a00:1450:400c:c01::63
Now on documenting this I wonder what happens when radvd reconfigures itself
and sees 2 addresses, one of which it is to pick up and one of which is in
its own configuration. For now, this works. This may become unstable when the
global address changes, which means
radvd.conf will have to be
generated in a more robust way from the prefix information found by
dhcp6c.
Learned: yes, this breaks when the global IPv6 address is removed
by dhcp6c.
Update:
This even works with a Linux-based router when the clients only have a
global IPv6 address and the services are reachable on unique local
addresses.
Update:
A few weeks later the Internet connectivity was shortly interrupted, which
means
dhcp6c removes the global IPv6 addresses from the interfaces.
So
radvd started advertising the
fc00::/7 address twice.
To fix that both advertised addresses have to be in
radvd.conf.