I needed to setup a VM that could only have connectivity through a specific wireguard endpoint. Previoiusly, the VM was using user mode networking (SLiRP) which required no setup. I asked around on IRC and was told that libvirt takes care of that stuff for you so most folks don’t care - but I already have a few VM’s and am not ready for black magic or XML. I will eventually have to move them, I suppose. Windows VMs don’t take kindly to even the slightest of parameter changes, so if there’s a tool that takes the commandline flags and generates the XML, that’d be awesome.
If you really need SLiRP networking (user mode) to work and want to route through wireguard, you could consider using network namespaces to achieve the same result. I like the flexibility offered by the TAP setup that lets my host and LAN devices interfact with the VM in a much more normal way (subjective).
vm1 are TUN devices.
Caveat: Not all traffic in the host is routed through the wireguard interface so
we need some
ip -4 rule usage to route.
This is the most straightforward so let’s get it out of the way. You need the kernel module loaded.
# modprobe wireguard
And on the “server” do the same, but with some modifications
wg set wg0 peer PUBLIC_KEY_HERE allowed-ips 10.0.0.2/32, 10.0.3.0/24
You’d also need to enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
Notice how we’ve allowed the bridge’s ip range in allowed-ips. Bridge setup time:
If you need to run qemu without requiring root user, setup a group
add yourself to it. Logout and login to take effect.
id must report that your
user is in
netdev before you proceed. Also create a new udev rule
KERNEL=="tun", GROUP="netdev", MODE="0660", OPTIONS+="static_node=net/tun"
to configure your TUN devices to use the group. I put mine in
/etc/udev/rules.d/10-qemu.rules along with some other stuff for passthrough.
Your kernel needs “Universal TUN/TAP devices” enabled.
For the bridge:
ip link add br0 type bridge
ip addr add 10.0.3.0/24 dev br0
ip link set up dev br0
For a DHCP server we can use
sudo dnsmasq --interface=br0 --bind-interfaces --dhcp-range=10.0.3.0,10.0.3.255
For the VM’s adapters
ip tuntap add vm0 mode tap group netdev
-device virtio-net-pci,netdev=vm0 \
- instead of
virtio-net-pciyou can use anything else like
e1000which has inbuilt drivers in windows. I installed it manually from the driver disk provided by Red Hat.
script=nois important, else QEMU tries to init a new adapter itself and that required superuser
ifname=vm0is not provided
script=doesn’t work because qemu doesn’t know which adapter to configure and it’ll try to run anyway.
You’ll get an error saying qemu can’t configure the device which looks suspiciously like you didn’t setup your permissions correctly, but it’s not.
At this point your VM should boot and the network adapter should recieve an IP address from dnsmasq.
Like I mentioned before, the host does not have a default route through the wireguard endpoint. We only want traffic from the bridge, or even, specific VMs to go through the endpoint.
ip route add default via 10.0.0.1 dev wg0 priority 1 table 1
This should be sufficient to do policy based routing from the VM to the internet and to the host. You should verify this by pinging from within the VM and from the host.
Documentation found on the kvm website and IRC users grawity, tds and others.