IPv6 connectivity of security.debian.org

The Problem

Have been hunting this down for quite some time now: several virtual hosts weren’t able to connect to security.debian.org. First I thought it was me, even though I had all the ingredients for IPv6-forwarding to work (this is the host):

*filter 
:FORWARD DROP [0:0]
-A FORWARD -p ipv6-icmp -j ACCEPT
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Of course, net.ipv6.conf.*.forwarding was set on the host. That should be enough to forward all outgoing connections and drop incoming, right? And it does, for pretty much any host, except security.debian.org (AKA as lobos.debian.org and villa.debian.org). There may be more, but that one caught my attention, because apt update hung just there (ftp.de.debian.org worked, btw).

First I thought that it was the MTU, but that was pretty much a red herring. After a while I realized that it was working when the FORWARD policy was ACCEPT, but of course that wasn’t a viable solution. So I dug deeper: Strangely enough, with the policy back to DROP and this rule:

-A FORWARD -d <VM-IPv6> -p tcp -m multiport \
   --sports 80,443 -j ACCEPT

it also worked, but this wasn’t enough:

-A FORWARD -s <VM-IPv6> -j ACCEPT

WTF? Fortunately I had a working virtual machine (also debian 8.6, same kernel), so I ended up comparing the IPv6-sysctl values (sysctl -a | grep ipv6).

The solution

As it turned out, the only difference was that the working virtual machine had net.ipv6.conf.*.forwarding enabled. So I added

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1

to /etc/sysctl.conf of the failing virtual machine, rebooted and then it finally worked ™! I don’t have the slightest clue why this is necessary, though. The VM is the final receiver, the end of the chain, but certainly not a router! Maybe it’s a kernel bug, I don’t know… I’m just glad it works 🙂

Just calling sysctl -w doesn’t do it, btw. You have to take the interface down and up again to take effect, hence the reboot…

OpenVPN and IPv6-Bridging

Nothing is as easy as it seems. Sigh… 🙁

I was getting strange timeouts when accessing sites via tunneled IPv6 (OpenVPN). Turned out that the sender never got the ICMPv6-Redirect from the tunnel endpoint, i.e. OpenVPN-Server. The ICMPv6-Packet is sent from the link-local address of the gateway (fe80::some:thin:g/64), because it gets dropped in the FORWARD-Chain of the gateway if the policy is DROP.

Setting it to ACCEPT magically makes things work, but that’s equal to turning off the firewall. Allowing traffic from and to fe80::/8 doesn’t help, either. Never figured out why.

What now? The physdev-module comes to rescue! Despite its name it can match the (virtual) tap-interface of the OpenVPN-Server. Just add the following rules to the beginning of the FORWARD-Chain:

ip6tables -I FORWARD -m physdev --physdev-out tap0 -j ACCEPT
ip6tables -I FORWARD -m physdev --physdev-in tap0 -j ACCEPT

and things run smoothly again 🙂