Using IPv6 outside of Docker with Docker
I recently activated IPv6 on my Netcup VPS, and in the process of setting it up on all my LXCs I noticed that for “reasons” the IPv6 default route would vanish after starting Docker (switching it all over to Podman is on my TODO list), effectively breaking the IPv6 connectivity on this LXC.
After some digging this seems to be a security thing: docker will enable forwarding on (eg.) eth0
, but setting forwarding=1
will make the kernel ignore router advertisements.
What are Router Advertisements? As per the pfSense documentation:
In IPv6, hosts locate a router through Router Advertisement (RA) messages sent from routers instead of by DHCP; IPv6-enabled routers that support dynamic address assignment are expected to announce themselves on the network to all clients. As such, DHCPv6 does not include any gateway information. So clients can obtain their addresses from DHCPv6 or SLAAC, but unless they are statically configured, they always locate their next hop by using RA packets sent from available gateways.
In the linux kernel this is controlled through the accept_ra
sysctl:
accept_ra - INTEGER
Accept Router Advertisements; autoconfigure using them.
It also determines whether or not to transmit Router Solicitations. If and only if the functional setting is to accept Router Advertisements, Router Solicitations will be transmitted.
Possible values are:
0 - Do not accept Router Advertisements.
1 - Accept Router Advertisements if forwarding is disabled.
2 - Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled.
Functional default:
enabled if local forwarding is disabled.
disabled if local forwarding is enabled.
To get router advertisements working again while forwarding is enabled, we need to set it to 2.
Setting net.ipv6.conf.eth0.accept_ra=2
in /etc/sysctl.d/99-docker.conf
didn’t help much: it seems that Docker will overwrite this setting too. So I opted instead to create a new systemd service file called `/etc/systemd/system/docker-ipv6-route.service to reset this value:
[Unit]
Description=Set accept_ra=2 after Docker starts
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/sysctl -q net.ipv6.conf.eth0.accept_ra=2
[Install]
WantedBy=multi-user.target
It’s a dirty hack, but it works. Let’s see what happens when I move this setup to Podman, later.
Leave a comment