[Solved] Simple policy-based routing over WireGuard VPN

Hi!

I'm trying to do some simple policy-based routing over a WireGuard VPN. Basically, I want only traffic from a particular IP address to use the VPN. I've been following various instructions and guides, including these:

https://openwrt.org/docs/guide-user/network/routing
https://openwrt.org/docs/guide-user/network/ip_rules
https://openwrt.org/docs/guide-user/network/ucicheatsheet

Anyway, things seem to be working well, except for one oddity that I discovered today. It seems that if I turn off the host that uses the VPN, ICMP "destination unreachable" packets are sent on the eth0 (wan) interface, not on the wg0 (vpn) interface as I would expect.

Here's a snippet from a tcpdump of eth0:

No	Time		    Source		Destination	Protocol	Length	Info
123	12:00:00.000000	10.x.y.z	a.b.c.d		ICMP		102	    Destination unreachable (Host unreachable)

Note the 10.x.y.z source address, which is the address of my wg0 interface:

# ifconfig wg0
wg0       Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.x.y.z  P-t-P:10.x.y.z  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP  MTU:1420  Metric:1
...

It seems odd to me not only that the packet is on the eth0 interface but that no NAT has taken place and translated 10.x.y.z to the address of the eth0 interface.

The routes/rules in my /etc/config/network:

config route
	option interface 'wg0'
	option target '0.0.0.0'
	option netmask '0.0.0.0'
	option gateway '0.0.0.0'
	option table 'vpn'

config route
	option interface 'lan'
	option target '0.0.0.0'
	option netmask '0.0.0.0'
	option gateway '0.0.0.0'
	option table 'vpn'
	option metric '100'
	option type 'unreachable'

config rule
	option src '192.168.1.x/32'
	option lookup 'vpn'

192.168.1.x is the address of the host using the VPN.

The generated routes/rules:

# ip rule
0:	from all lookup local
...
10:	from 192.168.1.x lookup vpn
32766:	from all lookup main
32767:	from all lookup default
# ip route show table vpn
default dev wg0 proto static scope link
unreachable default proto static metric 100

I tried adding another rule, but it seemed to have no effect:

# ip rule
0:	from all lookup local
...
9:	from 10.x.y.z lookup vpn
10:	from 192.168.1.x lookup vpn
32766:	from all lookup main
32767:	from all lookup default

Any idea what's going on? How can I make sure that ICMP "destination unreachable" packets are sent on the right interface?

It's not weird, the ICMP unreachable messages are generated locally on the OpenWrt and there is no rule for that, so it takes the default wan path.

Well, I naively expected things to just work the way I wanted. :wink: Lesson learned. How can I fix this, if adding the rule:

9:	from 10.x.y.z lookup vpn

does not work?

Not exactly. If you want all the locally generated traffic to go through vpn you'll need something like
ip rule add iif <loopback> to 0/0 lookup vpn prio 20
If you want only the icmp-unreachable, you'd have to mark it in iptables accordingly and make a rule to lookup vpn table for marked packets.

I don't think this is what I want, but thank you for the suggestion. :slight_smile:

This sounds more like what I want, but I'm quite unfamiliar with both iptables and openwrt. Can I do what you suggest by simply editing /etc/config/firewall? Any further hints greatly appreciated. :slight_smile:

Perhaps another option... Is it possible to instead disable the generation of icmp-unreachable packets?

Nope, this is way too custom. You need to add raw iptables rules.

Without ruining the networking of the router? I don't think so...
You could block the icmp-unreachables though on the firewall.

echo 1 > /proc/sys/net/ipv4/icmp_errors_use_inbound_ifaddr

2 Likes

Looks promising!

EXCELLENT! :+1:

This setting, when combined with this rule:

appears to have fixed the problem. :slight_smile:

Note what the official docs have to say about it:

If non-zero, the message will be sent with the primary address of
the interface that received the packet that caused the icmp error.
This is the behaviour network many administrators will expect
from a router. And it can make debugging complicated network
layouts much easier.

Maybe this setting should be made the default?

OK, I've marked this topic as solved. Thanks to everyone involved.

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.