When renting a dedicated server usually we get the whole net block of ipv6 addressess in a "package", along with just one or few IPv4 routable address. Having ipv6'es is nice and would be even better to make use of these, especially when IPv6 should not electricize anyone these days. In this post I''ll present a case, how to get workin' ip6 network on a guest virtual machine, which configuration is handled by libvirt(d), using the native v6 address from our rented net block.
So, you have a nice dedicated hardware there with lots of ipv6'es. Lets image we have such 2000:abcd:1:dead::/64 v6 net block. First step is to configure the host properly.
eth0 - external iface on the host side, used for internet access (by both v4&v6 proto),
virbr0 - internal "bridge" iface, used for VMs interconn. Also by this iface the VMs are able to get through the internet by the IPv6 proto,
2000:abcd:1:dead::/64 - the example ipv6 allocated net block,
vtnet0 - the iface on the guest VM, which is bridged to the virbr0 on the host's side.
Define ipv6 network in libvirt. To properly edit libvirt's defined network configuration use virsh command. In this scenario I'll put into edit the default one.
# virsh net-edit default // specify non-default network here if needed!
# libvirt's 'default' network example for ipv6
<forward dev='eth0' mode='route'>
<bridge name='virbr0' stp='on' delay='0'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<ip family='ipv6' address='2000:abcd:1:dead::' prefix='64'>
As you can see, the bridge interface - virbr0 - will have assigned the whole net v6 block. And for the eth0 interface we explicitly specify the work in a route mode, which means:
This is a variant on the default network which routes traffic from the virtual network to the LAN without applying any NAT (...)
After editing libvirt's network do not hesitate to restart it!
# virsh net-destroy default
# virsh net-start default
And check if virbr0 got properly assigned v6.
Now set single (thus /128 mask), probably the first one in your block, v6 address on eth0 iface.
# ifconfig eth0 inet6 2000:abcd:1:dead::/128
which equivalently means 2000:abcd:0001:dead:0000:0000:0000:0000 address.
Hint: edit your OSes network scripts to make it permanent.
Also at this point check, if eth0 device got properly attached /128 ipv6 address from the v6 net block.
What next we will do is to go with guests v6 configuration. Make sure that your qemu VM1's example machine is using the proper libvirt's network. In whatever option login as root and set on it IPv6.
# ifconfig vtnet0 inet6 2000:abcd:1:dead::1/64
What happend here is we have set the second available IPv6 address (2000:abcd:0001:dead:0000:0000:0000:0001) in the /64 block on a first (VM1) virtual machine, using /64 prefix. So far so good. Now lets set a proper default v6 gateway to make it able to communicate with v6 internet hosts. This gateway address will be our eth0 host's address.
# route add -6 default gw 2000:abcd:1:dead::
If you try to ping now any external ipv6 address there won't be the answer. Why? Because of this:
# tcpdump -i eth0 -n ip6
21:44:11.297066 IP6 2000:abcd:1:dead::1 > 2620:0:ccc::2: ICMP6, echo request, seq 7, length 16
21:44:11.532821 IP6 fe80::224:c3ff:fe84:400 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2000:abcd:1:dead::1, length 32
21:44:12.301107 IP6 2000:abcd:1:dead::1 > 2620:0:ccc::2: ICMP6, echo request, seq 8, length 16
21:44:12.544140 IP6 fe80::224:c3ff:fe84:400 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2000:abcd:1:dead::1, length 32
21:44:13.297133 IP6 2000:abcd:1:dead::1 > 2620:0:ccc::2: ICMP6, echo request, seq 9, length 16
21:44:13.535912 IP6 fe80::224:c3ff:fe84:400 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2000:abcd:1:dead::1, length 32
The neighbor discovery solicitation protocol, the IPv4's ARP equivalent, is not being passed to the VM guest interface from host's eth0 iface, and to be more specific: it's not being forwarded to the virbr0 interface on the first place. To deal with that we will use the Proxy NDP's feature by enabling it on host's side.
# echo "net.ipv6.conf.all.proxy_ndp = 1" >> /etc/sysctl.conf
# sysctl -p /etc/sysctl.conf
# ip -6 neigh add proxy 2001:41d0:2:566a::1 dev eth0
In third command you can see the guest's ipv6 assigned address, which is referred to the eth0 host's interface. You should put this command into some local script to restore it after hosts reboot.
And that would be it! If everything went well you should have now properly workin' ipv6 on your guest machine.
In case of issues please check your ip6tables ruleset... ;-)