Unable to connect vm to IPv6 internet via virtual tap interface
Here's what I think is wrong and how to address it.
VM side
The first issue is this one on the VM:
default dev eth0 metric 1024 pref medium
This makes believe the VM's routing stack the whole Internet is available directly on the link to eth0. So for any IPv6 destination it will send an NDP request, but nothing (including the host) will answer it.
To fix this, the VM just has to use the host as router, with its link-local address. It can simply be configured manually on the VM:
ip -6 route delete default dev eth0
ip -6 route add default via fe80::d0d5:4eff:fef3:deab dev eth0
For the VM side that's it.
Alternate settings on VM (and host's tp-0gn-0000go-0)
If you don't want to use the link-local address (eg: if it might change on reboot because of a random MAC address on host's tp-0gn-0000go-0), you can instead use the global IP address of the host by duplicating it on tp-0gn-0000go-0.
On the host, also add its IP address on tp-0gn-0000go-0 as /128 (or else with noprefixroute
if that weren't only a single /128 already):
ip -6 address add 2600:1f14:680:6f00:66a3:79d5:6c1d:14b/128 dev tp-0gn-0000go-0
On the VM, instead of above:
ip -6 route delete default dev eth0
ip -6 route add 2600:1f14:680:6f00:66a3:79d5:6c1d:14b/128 dev eth0
ip -6 route add default via 2600:1f14:680:6f00:66a3:79d5:6c1d:14b dev eth0
Host side (on eth0)
The host's own router isn't aware of the VM because the VM has no presence on the host's eth0 side. When a packet from Internet arrives to the host's router, it will do an Neighbour Solicitation, but nothing will answer it, including the host (unless this router could be configured otherwise of course, which would simplify everything). The host has to be configured with ND Proxy to actually answer this solicitation so that in the end the it will send the packet to the host.
To do this, on the host, enable proxy_ndp
on eth0, and add a specific NDP proxy entry (which has effect only if proxy_ndp
is enabled on the interface):
sysctl -w net.ipv6.conf.eth0.proxy_ndp=1
ip -6 neighbour add proxy 2600:1f14:680:6f00:66a3:79d5:6c1d:14c dev eth0
(The neighbour proxy entry can be displayed with ip neighbour show proxy
and deleted for example with ip neighbour flush proxy
. It's not displayed by default with ip neighbour
or deleted with ip neighbour flush all
)
The host will now receive packets for 2600:1f14:680:6f00:66a3:79d5:6c1d:14c
and will route them to the VM as defined in its routing table.
Both directions are now forwarded correctly: it should work.
I didn't attempt something like using a router advertisement daemon (radvd
) to autoconfigure the VM's route, because as it's related to SLAAC which is supposed to be used in something not smaller than /64 I'm not sure it would have worked.
UPDATE: as mentioned by @uMdRupert, whenever forwarding is activated (net.ipv6.conf.all.forwarding=1
) this setting is also needed on the host if configured by Router Advertisements:
sysctl -w net.ipv6.conf.eth0.accept_ra=2
The reason is that by default a Linux IPv6 router ignores Routing Advertisements (I guess the rationale is: because it was already configured as a router, there's no need to change this configuration). So simply activating IPv6 forwarding on an host which received its default route by Router Advertisements (as seen with proto ra [...] expires 1798sec
in such route), might lose this route some time later (or at reboot once configuration was changed) and become unreachable. This must be overruled to still allow accepting such RA on eth0 by setting accept_ra
to 2.
You can create a bridge and connect your eth0
and tp-0gn-0000go-0
to it.
ip link add name br0 type bridge
ip link set dev br0 up
ip link set dev eth0 master br0
ip link set dev tp-0gn-0000go-0 master br0
(be careful, when eth0
joins the bridge it will lose the IP, if you are doing this remotely you have to make sure it will get one)
At this moment the bridge is setup. You can now assign the address to eth0
using whichever method you are using (if SLAAC, then you have nothing to do), if DCHPv4 then dhcp eth0
,...
Start the VM and you should be all set.