IPv6-Ready Linux checklist

Welcome to the IPv6-Ready Linux checklist! This page aims to provide guidelines for distribution developers on how to deal with IPv6. Ultimately, we hope that by following these guidelines, a Linux (or BSD...) distribution could provide seamless support for all of these scenarios:

It is explicitly required that each scenario should work fine without the need for any manual configuration from the user. This page currently focuses on client/workstation type of system. I might expand it to router and/or server support later.

You can find detailed explanations and rationale below, or jump to the summary checklist.


Detailled analysis

Kernel

This may be obvious, but your kernel needs to include both the IPv4 and the IPv6 network stacks. On Linux, IPv6 is usually compiled as a loadable kernel plugin, but some distributions do not compile it at all. Some other distributions blacklist the IPv6 plugin, which is pretty much the same.

Kernel version

Also, make sure the kernel version is at least 2.6.17.2. It includes updated source address selection, which improves handling of private IPv6 networks (Unique Local Addresses).

In any case, avoid versions 2.6.8 and earlier; these versions assumed that IPv6 connectivity was available whenever the IPv6 stack was loaded (the default on-link assumption).

Finally, do not use version 2.6.19.2 which has broken IPv6 autoconfiguration.

Loading the IPv6 plugin

Autoloading support cannot be relied upon, as it would only load IPv6 support when an application tries to use it (which may be a chicken-and-egg problem). To operate properly, the ipv6 plugin must be loaded:

The obvious place to put to trigger the loading is from /etc/modules, which is parsed by udev/module-init-tools.

C library: DNS resolver

Distribution developers tend to put all the responsibility for IPv4/IPv6 coexistence problems on the kernel. In practice, most problems come from userland. The most critical part is most likely the DNS resolver.

If you write network-related source code, remember not to assume that IPv6 resp IPv4 is available when the DNS resolver returns an IPv6 resp IPv4 address! This is probably the most common source of dual-stack bugs in software.

In particular, keep in mind that getaddrinfo() returns a linked-list of results, rather than a single result:

GNU/libc version

For proper ordering of IPv4 and IPv6 entries from the DNS resolver, you need source address selection support in glibc. This comes with glibc version 2.5. With older versions, IPv6 will always be prioritized regardless of the connectivity status of the host.

/etc/gai.conf

/etc/gai.conf is the configuration file for source address selection. As of April 2007, considering the state of IPv6 address space, you should ship this as the default gai.conf:

# Labels
label  ::1/128       0
label  ::/0          1
label  2002::/16     2
label ::/96          3
label ::ffff:0:0/96  4
label  fec0::/10     5
label  fc00::/7      6
label  2001:0::/32   7

# Precedence
precedence  ::1/128       50
precedence  ::/0          40
precedence  2002::/16     30
precedence ::/96          20
precedence ::ffff:0:0/96  10
precedence 2001:0::/32    5

# To always favor IPv4, replace the previous line with:
#precedence ::ffff:0:0/96  100

Note: this file is only relevant with glibc 2.5 and up.

Other C libraries

At the time of writing, the alternate C libraries for Linux do not support source address selection and should hence be avoided.

Support for broken recursive DNS servers

In the real world, some unfortunate Internet users depend on broken recursive DNS servers. Some of these returns no answer whatsoever when asked for an AAAA record (i.e. hostname to IPv6 address query). When that is the case, IPv6-capable software will typically exhibit a 30 timeout/freeze whenever they attempt to resolve a hostname.

There are no perfect solution to this issue, but to fix the DNS servers. However, MacOS X includes a fairly good work-around for this: it only tries to query AAAA records if the local system has IPv6 connectivity. To test whether IPv6 connectivity is available, one should check each network interfaces for one or more addresses that:

  1. is an IPv6 address,
  2. is not the loopback address: ::1,
  3. is not an IPv4 address embedded in an IPv6 address: ::0:0/96 or ::ffff:0:0/96
  4. is not a link-local address: fe80::/10

If any matching address is found, it is very likely that IPv6 connectivity is present, and hence AAAA DNS queries should be attempted. Otherwise, it is unlikely that AAAA queries will be of any use, though they could theoretically be.

glibc introduced the AI_ADDRCONFIG flag to avoid query records for address types that the system does not support. However, it will still attempt AAAA queries whenever there is an IPv6 address (regardless of the extra requirements in the above list), so it fails to address this particular issue.

Static network configuration

Network configuration software has to support manual configuration of IPv4 and/or IPv6 addresses, routes, recursive DNS servers, etc...

This also applies to the installer if it has network support!

DHCP

DHCPv4 is pretty much always supported by default. However, DHCPv6 is not. It is required on some IPv6-enabled networks (Windows Vista has it), where stateless IPv6 autoconfiguration is not provided. It is also required to obtain IPv6 recursive DNS servers addresses (which can neither be provided through DHCPv4, neither with stateless IPv6 autoconfiguration).

PPP

The PPP daemon usually comes with IPv6 support. However, it only attempts IPv4 configuration by default. To enable the IPv6 configuration protocol, the following line must be added to each PPP peer configuration file:

# ipv6 <space> <comma> - the comma matters!
ipv6 ,

If IPV6CP succeeds, it will only provide a link-local address on the ppp network interface. A DHCPv6 client must handle the rest of the work - in IPv6 world, PPP is configured pretty much the same as a normal network interface.

Transition mechanisms

Transition mechanisms are nice for developers to play and test their software. They are also nice as a fallback service for IPv6 connectivity. However, when including a transition mechanism, one must keep in mind that it might not always work.

6to4

6to4 is an automatic pseudo-tunneling mechanism for IPv6-capable host and networks with at least one public IPv4 address. In theory, it can be enabled automatically whenever a host has an public IPv4 address, since all the parameters required can be inferred from that IPv4 address.

Unfortunately, there are some networks where hosts get a public IPv4 address, but IP protocol 41 (IPv6 over IP) is somehow firewalled (e.g. some captive portal-based wireless accesses). As a consequence, unless it seems that 6to4 should, by default, not be enabled automatically, unless some automated connectivity test is run first.

Kernel support

6to4 is supported in the standard kernel IPv6 stack, and can be configured with /sbin/ip from iproute2. Please resist the temptation to use the legacy sit0 tunnel interface:

Teredo

Teredo is the other IETF standard track automated pseudo-tunneling protocol for IPv6. That one provides IPv6 through NATs over UDP/IPv4, and includes connectivity checks, so that it can safely be enabled.

One may include support for it, so long as you have a stable Teredo server to provide (one being the Microsoft multi-homed servers at teredo.ipv6.microsoft.com).

Kernel support

Teredo is not supported by the kernel alone. Separate tunnelling software (such as Miredo) is required.

Tunnel brokers

Advanced users like to use tunnel brokers because they usually provide a fixed IPv6 prefix. However, they require manual registration, so they are out-of-scope from this document.


Summary

Conclusion

As of april 2007, there is still a long way to go before any Linux distribution (that I know) can claim to be IPv6-ready.