I am trying to use Linux routing to route traffic for a SPECIFIC IP ( on a Linux Bridge (named vmbr-dmz) to wireguard tunnel (named wg0). However it is not working.

I have two questions, firstly how to get it working when wireguard AllowedIPs= and when restrcited to just AllowedIPs=

What I have done - on my host (default debian 11 installation) using linux-bridging

9: vmbr-dmz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet brd scope global vmbr-dmz
11: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    inet scope global wg0
       valid_lft forever preferred_lft forever

I created a new Policy Routing Table in /etc/iproute2/rt_tables.d/dmzwg0.conf

100 dmzwg0

I create a rule for that IP address to use the table dmzwg0. The rule is visibile in the list.

ip rule add from lookup dmzwg0

I started with the default wireguard setup from my VPN and started using systemctl start wg-quick@wg0

PrivateKey = k...=
Address =

PublicKey = 8...=
AllowedIPs =
#AllowedIPs =
Endpoint = NNN.NNN.NNN.NNN:51820

I am not sure how to find the next hopw address for wg - but guessing it is How do you determine the next-hop for a wireguard interface? Since it is AllowedIPs= I can ping it, so I can added as next-hop.

ip route add default via dev wg0 table dmzwg0

Looking that the dmzwg0 table I see the route I expect

ip route show table dmzwg0
default via dev wg0

I added the following nf table rules for masquerading.

nft add table nat
nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule nat postrouting oifname "wg0" ip saddr counter packets 0 bytes 0 masquerade

I started from VM I tried to connect to the internet. On the host I ran tcpump -i vmbr-dmz so I could find the traffic from the bridge has the expected I address IP

tcpdump -i vmbr-dmz
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on vmbr-dmz, link-type EN10MB (Ethernet), snapshot length 262144 bytes
14:40:09.803588 IP > dns.google.domain: 59264+ SRV? _http._tcp.security.debian.org. (48)
14:40:09.803620 IP > dns.google.domain: 60873+ SRV? _http._tcp.deb.debian.org. (43)
14:40:14.808719 IP > 60873+ SRV? _http._tcp.deb.debian.org. (43)
14:40:14.808721 IP > 59264+ SRV? _http._tcp.security.debian.org. (48)

I tried tcpdump on both wg0 and my physical NIC eno1 and I could not see the traffic.

My nft nat rules are not counting any packets?

Q1) - So what have I missed? What steps could I take to work out where my traffic is going?

Also if I change my wireguard config to just the IP address I want to allpw I am unable to add the next hop as the host cannot reach/ping the next-hop via wg0.

ip route add default via dev wg0 table dmzwg0
Error: Nexthop has invalid gateway.

Q2) - How do I add the default route to the dmzwg0 table to send all traffic via wg0 for only

  • AllowedIPs= is a single IP address, wireguard uses the first entry to indicate the endpoint, normally you would configure /32 and the /0 in the allowedips entry. You can do source specific routing by adding src to your ip route command
    – sleepyhead
    Sep 6, 2022 at 5:30
  • To clarify ip route command on the host, not on the source itself. Sourced based routing is usually disabled because it's a security problem.
    – sleepyhead
    Sep 6, 2022 at 5:37

1 Answer 1


WireGuard interfaces effectively use their own peers' configuration to determine the next routing hop, so you should not try to specify an explicit "next hop" for a WireGuard interface.

You use the AllowedIPs setting of each peer of a WireGuard interface to let the interface know which packets should be sent to that peer, kind of like the interface's own internal routing table. Packets that you direct out a WireGuard interface will be sent to the peer with an AllowedIPs setting that matches the packet's destination address (in the case of more than one match, the match with the smallest range will be selected; and WireGuard won't let you use the same exact range for more than one peer). If no AllowedIPs match, the packet will be dropped.

Wg-quick will automatically set up routes to match all the AllowedIPs your have configured for an interface. You can use the interface's Table setting to direct wg-quick to set up these routes in a different routing table than your main one:

PrivateKey = ...
Address =
Table = dmzwg0

PublicKey = ...
AllowedIPs =
Endpoint = NNN.NNN.NNN.NNN:51820

The above config will set up your dmzwg0 table like this:

$ ip route show table dmzwg0
default dev wg0 scope link

To send packets that you're forwarding from out through this WireGuard interface, you just need to add the policy routing rule you mentioned in your question:

ip rule add from lookup dmzwg0 priority 123

Note that if you're forwarding packets from to some peer through your WireGuard interface, you do not want to set the AllowedIPs of that peer to Always set AllowedIPs to the destinations that you want to send to the peer (or forward through it) -- if that includes traffic to anywhere on the Internet, it should be

You must log in to answer this question.