IPv6 configuration in Alpine Linux, Debian and GNS3 Docker
The IPv4/IPv6 configuration is documented in
- https://wiki.debian.org/NetworkConfiguration for Debian
- https://wiki.alpinelinux.org/wiki/Configure_Networking for Alpine Linux
GNS3 docker images use the same base component (busybox) as Alpine to configure the interfaces, so use the instructions for Alpine.
The most interesting part of IPv6 is the auto-configuration, it’s completely different from IPv4. I’m going to show its configuration for Debian Linux, it’s also valid for Ubuntu and all its derivatives. Furthermore the configuration for Alpine Linux is shown. I will cover some specifics of GNS3 Docker at the end.
IPv6 Auto-configuration Basics
IPv6 can configure its IPv6 address/netmask and its default gateway by stateless address auto-configuration (SLAAC). The router in an IPv6 network sends periodical router advertisements (RA), which contains the necessary information. A host can use a router solicitation message to request an immediate RA. SLAAC can’t configure further parameters, especially DNS servers and domain name are not configured by SLAAC.
Additionally the DHCPv6 protocol can be used. It exists in two variants, stateless and stateful DHCPv6. The stateless version is meant to complement SLAAC, it mainly supports options for defining DNS parameters. The stateful variant supports all the stateless options, additionally it manages an IPv6 address pool and gives host addresses (with /128 netmask) to the clients. Neither variant is able to give netmasks, default gateway or other routing information to the clients. That has to be done via SLAAC or by static configuration.
Linux handles SLAAC completely in the kernel, no user mode process is involved.
The kernel parameter
net.ipv6.conf.<interface>.accept_ra controls it:
0 - Do not accept Router Advertisements.
1 - Accept Router Advertisements unless forwarding is enabled.
2 - Always accept Router Advertisements, even if forwarding is enabled.
Additional kernel parameters can fine-tune this,
for example the parameter
defines if a default route is added (1, the default) or not (0).
DHCPv6 is not handled by the kernel, it needs a user mode process, for example the isc-dhcp-client (dhclient).
IPv6 test setup
I’m using a simple GNS3 project to test IPv6 configuration in a controlled environment.
The cisco router configuration supports IPv6, SLAAC (enabled by default) and stateful DHCPv6. Stateless DHCPv6 requests are also answered by the stateful DHCPv6 server. Additionally a very basic DNS server allows the test of IPv6 DNS requests.
ipv6 unicast-routing ! ipv6 dhcp pool test address prefix 1:2:3:4:4711::/80 dns-server 1:1:1:1::1 domain-name test ! interface Loopback1 ipv6 address 1:1:1:1::1/128 ! interface GigabitEthernet0/0 ipv6 address 1:2:3:4::1/64 ipv6 dhcp server test no shutdown ! ip dns server ip dns primary test soa ns.test admin@test ip domain name test ip host r1.test 1:1:1:1::1
The “ipterm-1” device is a docker container running Debian. It has the additional package “ifupdown” installed, that allows the network configuration within that container. “alpine-1” runs Alpine Linux within Docker, ifup/ifdown are installed by default.
That’s easy, here an example:
iface eth0 inet6 static address 1:2:3:4::100 netmask 64 gateway 1:2:3:4::1 up echo nameserver 1:1:1:1::1 > /etc/resolv.conf pre-up echo 0 > /proc/sys/net/ipv6/conf/eth0/accept_ra
This will work both for Alpine and Debian.
The ‘pre-up’ command is not necessary for Debian, it will set the accept_ra kernel variable to 0 by default. Alpine doesn’t touch the kernel variables during the interface configuration, so the ‘pre-up’ command is mandatory in Alpine.
The ‘up’ command sets the nameserver by overwriting /etc/resolv.conf. Alternatively you can remove the ‘up’ command and manually edit /etc/resolv.conf.
For Debian, that’s simple, use
iface eth0 inet6 auto.
That sets the accept_ra kernel variable to 2 and activates the interface.
The kernel does the rest.
But SLAAC doesn’t configure DNS, so either configure that manually as shown in the static configuration section, or enable stateless DHCPv6 by using the dhcp option.
iface eth0 inet6 auto dhcp 1
Alpine has no ‘auto’ method, it uses ‘manual’, which only activates the interface. As accept_ra is active by default, you don’t have to touch this. The Alpine documentation sets accept_ra anyway to be on the safe side.
iface eth0 inet6 manual pre-up echo 1 > /proc/sys/net/ipv6/conf/eth0/accept_ra
The DHCPv6 client udhcpc6 in Alpine is very weak. Alpine 3.7 (with busybox 1.27) is the first version with a DHCP6 client that might actually work. But I haven’t tested that, as it is not yet released at the time of writing. Even that DHCPv6 version is not integrated in ifup/ifdown. So DHCPv6 can’t be used in Alpine.
Alpine also contains a package with the debian version of ifup/ifdown. But at least in Alpine v3.6 this package doesn’t help either.
IPv6 initially uses a static interface address during auto-configuration, based on the MAC address. But this static address makes it easy to track a user. Therefore RFC 3041 (obsoleted by RFC 4941) defines a method to use a pseudo-random IPv6 address. This feature is realized by the Linux kernel and is controlled by the kernel variable ‘use_tempaddr’.
This can be enabled permanently by adding this to /etc/sysctl.conf:
It can also enabled in /etc/network/interfaces by adding
pre-up echo 2 > /proc/sys/net/ipv6/conf/<interface>/use_tempaddr
to the interface configuration.
Alternatively, Debian/Ubuntu users can use
privext 2 in the iface section.
No problem for Debian, use
iface eth0 inet6 dhcp.
As the accept_ra kernel variable is also set,
the computer gets two addresses, one from stateful DHCPv6 and one from SLAAC.
It’s not reasonable to turn off SLAAC,
as DHCPv6 alone doesn’t send enough information to get a working IPv6 interface configuration.
As written in the previous section, Alpine doesn’t support DHCPv6 by default.
Normally the Docker software does the IPv4/IPv6 interface configuration. But as GNS3 wants the Docker container to use the virtual links of GNS3, it has to use it’s own setup for the network interfaces. For the interface configuration it injects a busybox binary into the container, which configures them the same way, an Alpine system will do. But that means, it has the same limitations with DHCPv6.
If the Docker container uses Debian or Ubuntu, a workaround could be to configure the interfaces not in the injected busybox, but in the OS of the Docker container.
The idea is to use /etc/network/interfaces in Debian style.
At startup of the container the ifup of busybox will complain
about unknown methods “auto” or “dhcp”.
Simply ignore that and redo the interface configuration in
But that will work only if the “ifupdown” package is installed in the Docker image.
By default that’s not the case, so this will normally not work.
That’s the reason, why I have included the “ifupdown” package
in my own GNS3 Docker images (https://github.com/ehlers/gns3-docker-images).