0

I'm trying to setup a Wireguard tunnel on my host OS and route all network traffic from a specific KVM VM over this Wireguard VPN. My KVM VMs are setup using bridged networking. The interface name on the host OS of the specific VM that I want to route through the VPN is 'viifv1424'. These are the commands I've run to try and achieve this, but it seems the VM is just routing as normal still, and not routing through the VPN:

These are the exact commands I ran. The VM interface name is viifv1424, and the wireguard interface is named wg_viifv1424

#Setup fireguard tunnel
ip link add dev wg_viifv1424 type wireguard
wg setconf wg_viifv1424 /etc/wireguard/wg_viifv1424.conf

#routing table
ip link set dev wg_viifv1424 up
ip route add default dev wg_viifv1424 table 100
ip rule add iif viifv1424 table 100

#iptables rules
iptables -t nat -A POSTROUTING -o wg_viifv1424 -j MASQUERADE
iptables -A FORWARD -i viifv1424 -o wg_viifv1424 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i viifv1424 -o wg_viifv1424 -j ACCEPT

wg_viifv1424.conf contents:

[Interface]
PrivateKey = XXXXXXX
[Peer]
PublicKey = XXXXXXX
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = 1.2.3.4:51820

What am I doing wrong and how can I achieve this?

1 Answer 1

2

At the point your host is making the relevant routing decision, the input interface (iif in your rule) is the bridge device, not viifv1424.

Example setup

On my system, I'm running a typical libvirt setup. I have a network default associated with bridge device virbr0. If I create a virtual machine on that network, the virtual machine gets attached to virtual interface vnet0.

I have a wireguard interface configured as wg0, with address 192.168.64.14.

Rules that don't work

If I set up the equivalent to your rules:

ip route add default dev wg0 table 100
ip rule add prio 100 iif vnet0 table 100
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE

And then attempt to ping 8.8.8.8, I see the echo request go out the host default interface.

Rules that do work

If instead I set up the policy rule with the bridge interface as the input interface:

ip route add default dev wg0 table 100
ip rule add prio 100 iif virbr0 table 100
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE

Then I see the request go out wg0 as desired. Running tcpdump -i wg0 -n I see:

19:05:19.217001 IP 192.168.64.14 > 8.8.8.8: ICMP echo request, id 26, seq 1, length 64
19:05:19.274453 IP 8.8.8.8 > 192.168.64.14: ICMP echo reply, id 26, seq 1, length 64
4
  • This makes sense, but, you don't specify 'venet0' anywhere in your rules. I have multiple VMs on this host, all using the same bridge device. I only one specific VMs to route over the Wireguard tunnel. How can this be achieved? Commented Jan 20, 2023 at 17:54
  • You could route by source ip address instead of by input interface. You could attach your virtual machine to a different bridge interface. You could set up wireguard inside your virtual machine. You might be able to use an iptables rule to set a packet mark on traffic coming in the virtual interface and use that in your policy rule instead.
    – larsks
    Commented Jan 20, 2023 at 23:39
  • Why doesn’t it work when I try to route by the VM virtual interface though? This would be ideal for the setup I want. A VM can have multiple IPs, so I’d rather not use source IP, and I don’t want it on the guest. Commented Jan 21, 2023 at 14:44
  • Because from a networking perspective the bridge device is where packets enter the host; the tap device associated with the vm is like the remote end of an ethernet cable.
    – larsks
    Commented Jan 21, 2023 at 15:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .