Systemd networking: IPv6 networking not available at boot

bootipv6networkingsystemd

I've a Debian machine running multiple static IPv4 and IPv6 addresses managed by systemd itself at /etc/systemd/network/10-static-eth0.network as follows:

[Match]
Name=eth0

[Network]
Address=2a04:----::149/64
Address=2a04:----::242/64
Address=2a04:----::243/64
Gateway=2a04:----:0001

Address=5.----.149/25
Address=5.----.242/25
Address=5.----.243/25
Gateway=5.----.129

DNS=89.----.4
DNS=46.----.104

I've multiple processes that start with the system via systemd units like OpenVPN, Bind9 etc. They're all set to bind to specific IPs of the interface eth0. However they fail to start because they can't bind to the IPv6 addresses after boot.

How do I know this?

I made two test units that use ping and ping6 to test the network right after the targets network.target and network-online.target and this happens:

IPv4 Test Result:

server.example:~# systemctl status abootping.service
● abootping.service - A boot-time ping for network testing
   Loaded: loaded (/lib/systemd/system/abootping.service; enabled)
   Active: inactive (dead) since Thu 2015-11-26 11:01:58 CET; 45s ago
 Main PID: 433 (code=exited, status=0/SUCCESS)

Nov 26 11:01:54 server.example ping[433]: PING test-ping-host.example (89.-----.8) from 5.----.149 : 56(84) bytes of data.
Nov 26 11:01:54 server.example ping[433]: 64 bytes from test-ping-host.example (89.-----.8): icmp_seq=1 ttl=59 time=4.92 ms
Nov 26 11:01:55 server.example ping[433]: 64 bytes from test-ping-host.example (89.-----.8): icmp_seq=2 ttl=59 time=4.92 ms
Nov 26 11:01:56 server.example ping[433]: 64 bytes from test-ping-host.example (89.-----.8): icmp_seq=3 ttl=59 time=4.84 ms
Nov 26 11:01:57 server.example ping[433]: 64 bytes from test-ping-host.example (89.-----.8): icmp_seq=4 ttl=59 time=5.41 ms
Nov 26 11:01:58 server.example ping[433]: 64 bytes from test-ping-host.example (89.-----.8): icmp_seq=5 ttl=59 time=4.95 ms
Nov 26 11:01:58 server.example ping[433]: --- test-ping-host.example ping statistics ---
Nov 26 11:01:58 server.example ping[433]: 5 packets transmitted, 5 received, 0% packet loss, time 4007ms
Nov 26 11:01:58 server.example ping[433]: rtt min/avg/max/mdev = 4.843/5.010/5.414/0.209 ms

IPv6 Test Result:

server.example:~# systemctl status abootping6.service
● abootping6.service - A boot-time ping6 for network testing
   Loaded: loaded (/lib/systemd/system/abootping6.service; enabled)
   Active: failed (Result: exit-code) since Thu 2015-11-26 11:01:54 CET; 56s ago
 Main PID: 436 (code=exited, status=2)

Nov 26 11:01:54 server.example ping6[436]: ping: bind icmp socket: Cannot assign requested address
Nov 26 11:01:54 server.example systemd[1]: abootping6.service: main process exited, code=exited, status=2/INVALIDARGUMENT
Nov 26 11:01:54 server.example systemd[1]: Failed to start A boot-time ping6 for network testing.
Nov 26 11:01:54 server.example systemd[1]: Unit abootping6.service entered failed state.

As you can see the IPv4 is working perfectly after boot, however IPv6 isn't and all boot processes that need IPv6 fail do bind.


About my network-online.target

In order to really make sure my boot units only start after the network is really working I added After=network.target network-online.target to all of them.

network-online.target itself has this wants:

enter image description here

That includes:

[Unit]
Description=Wait for Network to be Configured
Documentation=man:systemd-networkd-wait-online.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
Requisite=systemd-networkd.service
After=systemd-networkd.service
Before=network-online.target

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online
RemainAfterExit=yes

[Install]
WantedBy=network-online.target

According to documentation:

systemd-networkd-wait-online is a one-shot system service that waits
for the network to be configured. By default, it will wait for all
links it is aware of and which are managed by
systemd-networkd.service(8) to be fully configured or failed, and for
at least one link to gain a carrier.

The real effect of this service wait is noticeable on boot, and my test ping services respect it:

enter image description here


The ping after SSH Login

Before everyone thinks my IPv6 network isn't properly configured here are a few proofs otherwise:

  1. If I SSH to the machine right after the boot and try to use ping6 it works:

    server.example:~# ping6 -I 2a04:-----::242 test-ping-host.example -c 5
    PING test-ping-host.example(test-ping-host.example) from 2a04:-----::242 : 56 data bytes
    64 bytes from test-ping-host.example: icmp_seq=1 ttl=59 time=7.41 ms
    64 bytes from test-ping-host.example: icmp_seq=2 ttl=59 time=7.41 ms
    64 bytes from test-ping-host.example: icmp_seq=3 ttl=59 time=7.31 ms
    ^C
    --- test-ping-host.example ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2003ms
    rtt min/avg/max/mdev = 7.314/7.381/7.415/0.047 ms
    
  2. If I restart, for instance, lighttpd it binds correctly to the IPv6 it supposed to and I can open hosted websites using a IPv6 client or ping6 from another machine.


Here is my question: Is this normal? Shouldn't the IPv6 also work because systemd-networkd-wait-online made sure it was available? Or… does at least one link to gain a carrier. really mean that after I get an working IPv4 it will stop waiting and the IPv6 addresses are still not routable? How can I fix this?

Best Answer

Apparently I'm actually right, it's not waiting for IPv6. I posted this issue on the project's Github and someone marked it as an RFE: https://github.com/systemd/systemd/issues/2037

Check this for a solution (disabling IPv6 DAD) that temporally fixes the issue: http://serverfault.com/questions/766253/ensure-systemd-wait-for-ipv6-before-start-service-unit