Using IPv6 SLAAC with IP forwarding on Debian Stretch (“connect: network is unreachable”, no default gateway)

When configured as a router, for instance for hosting virtual machines with KVM, a Debian machine with a somewhat recent kernel will not listen to router advertisements from others. This makes sense in many cases, but when you have a VM host in your internal network, which only router function is to allow communication to and from the virtual machines it hosts, the default behaviour is less than optimal.

ping6 reports the network as unreachable. Looking at ip -6 route reveals the problem. There’s no “default” line configured.

# ping6
connect: Network is unreachable
# ip -6 route
2001:4fa0:baaa:1::/64 dev eth0 proto kernel metric 256 expires 86394sec pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium

After verifying with tcpdump -i eth0 ip6 that router advertisements were indeed being received, I looked around for a bit and found this post by Andy Smith that explains the problem in detail.

In short, accepting router advertisements is governed by /proc/sys/net/ipv6/conf/$IFACE/accept_ra. These values are documented in ip-sysctl.txt (local archive here).

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

	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.

The solution is thus to set accept_ra to 2 to allow for accepting router advertisements even if forwarding is set to 1.

Since I use Shorewall to enable the forwarding, I ended up with a somewhat different config than Andy, but I still use the pre-up statements in /etc/network/interfaces to resolve the issue.

allow-hotplug eth0
iface eth0 inet static
	pre-up echo 2 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra

The rest of the config is only shown for reference. The important part is the pre-up line. Setting this, and then manually writing to /proc/sys/net/ipv6/conf/eth0/accept_ra to apply the configuration immediately, I had a default route within seconds, and ping to Google worked like a charm.

# ip -6 route
2001:4fa0:baaa:1::/64 dev eth0 proto kernel metric 256 expires 86394sec pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fe80::1:1 dev eth0 proto ra metric 1024  expires 50sec hoplimit 64 pref medium
# ping6 -c4
PING (2a00:1450:400f:807::200e)) 56 data bytes
64 bytes from (2a00:1450:400f:807::200e): icmp_seq=1 ttl=55 time=19.0 ms
64 bytes from (2a00:1450:400f:807::200e): icmp_seq=2 ttl=55 time=18.6 ms
64 bytes from (2a00:1450:400f:807::200e): icmp_seq=3 ttl=55 time=22.3 ms
64 bytes from (2a00:1450:400f:807::200e): icmp_seq=4 ttl=55 time=17.8 ms

--- ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 17.823/19.474/22.359/1.725 ms

1 Comment

  • Eve says:

    Add inet6 part

    iface eth0 inet6 auto
    accept_ra 2

    may help you 🙂

    And also, according to debian stretch manual, if you use auto in inet6, it’s automatically set to 2, so you may even omit accept_ra part.

    accept_ra int
    Accept router advertisements (0=off, 1=on, 2=on+forwarding). Default value: “2”

Leave a Reply

Your email address will not be published. Required fields are marked *