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.
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.
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.
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:
lo
which requires no configuration anyway).
The obvious place to put to trigger the loading is from /etc/modules, which is parsed by udev/module-init-tools.
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:
- Do not assume
socket()
will succeed; if it fails, try the next list entry.- Do not assume
bind()
orconnect()
will succeed; ifsocket()
succeeded, you may still need to try the next list entry asbind()
orconnect()
may fail too. That happens when you have the IPv6 stack loaded, but no IPv6 connectivity, for instance.- If using
listen()
, remember to set theAI_PASSIVE
flag, and be ready to handle multiple listening sockets: you must iterate through the whole linked-list, rather than stop at the first succeeding entry. Otherwise you may have a bad surprise when running on a dual-stack host!
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 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.
At the time of writing, the alternate C libraries for Linux do not support source address selection and should hence be avoided.
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
,::0:0/96
or ::ffff:0:0/96
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.
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!
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).
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 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 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.
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:
any
") - that's why you cannot use sit0.
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).
Teredo is not supported by the kernel alone. Separate tunnelling software (such as Miredo) is required.
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.
CONFIG_IPV6=y
or CONFIG_IPV6=m
ipv6
in /etc/modules
ipv6
module not blacklisted in udev/module-init-tools configuration/etc/gai.conf
shipped with sane defaultsAs of april 2007, there is still a long way to go before any Linux distribution (that I know) can claim to be IPv6-ready.