OpenVPN Wireguard routing

hello,
I have a quick question. My router runs an OpenVPN (all lan via this client) client. It also runs a wireguard server to connect to the router remotely. The connecting phone then uses the routers openvpn client to surf the net and at the same time resolves dns through an adguard server running on the lan. The Issue: when the OpenVPN restarts (server change or whatever) the routing for my wireguard server breaks as the internal ip of the OpenVPN server changes. The only way to get the wg server working again is a router reboot to flush the routes. Any way of fixing this? thx :smiley:

Does your phone connect to the wgserver via the wan or via the vpnclient?

Does your phone connect to the wgserver via the wan or via the vpnclient?

it connects via wan (PBR in place for the handshake and then handover to the vpnclient)

For the handshake you indeed need an sport rule which the PBR app should make automatically but that is it. You do not need anything else because you appear to have the default route via the vpn client.
It can help if you show us your config, Please connect to your OpenWRT device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button

Remember to redact keys, passwords, MAC addresses and any public IP addresses you may have but do not redact private RFC 1918 IP addresses as that is not needed:

ubus call system board
cat /etc/config/network
cat /etc/config/firewall
ip route show
ip -6 route show
ip route show table all
ip rule show
cat /etc/config/pbr
service pbr restart
service pbr status

here you go

{
	"kernel": "6.6.119",
	"hostname": "<REDACTED_HOSTNAME>",
	"system": "ARMv8 Processor rev 4",
	"model": "GL.iNet GL-MT6000",
	"board_name": "glinet,gl-mt6000",
	"rootfs_type": "squashfs",
	"release": {
		"distribution": "OpenWrt",
		"version": "24.10.5",
		"revision": "r29087-d9c5716d1d",
		"target": "mediatek/filogic",
		"description": "OpenWrt 24.10.5 r29087-d9c5716d1d",
		"builddate": "1766005702"
	}
}

config interface 'loopback'
	option device 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix '<REDACTED_ULA_PREFIX>'
	option packet_steering '1'

config device
	option name '<BRIDGE_1>'
	option type 'bridge'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'
	list ports 'lan5'

config device
	option name '<DEVICE_1>'
	option macaddr '<REDACTED_MAC>'
	option ipv6 '0'

config device
	option name '<BRIDGE_2>'
	option type 'bridge'
	option bridge_empty '1'
	option ipv6 '0'

config device
	option name '<BRIDGE_3>'
	option type 'bridge'
	list ports '@openvpn'

config device
	option name '<BRIDGE_4>'
	option type 'bridge'
	option bridge_empty '1'
	option ipv6 '0'

config interface 'lan'
	option device '<BRIDGE_1>'
	option proto 'static'
	option ipaddr '<REDACTED_LAN_IP>'
	option netmask '255.255.255.0'
	option delegate '0'
	option dns_metric '5'
	list dns '<REDACTED_DNS_IP>'
	option peerdns '0'

config interface 'wan'
	option device 'eth1.10'
	option proto 'pppoe'
	option ipv6 '0'
	option keepalive '20 6'
	option metric '40'
	option peerdns '0'
	list dns '<REDACTED_DNS_IP>'

config device
	option type '8021q'
	option ifname 'eth1'
	option vid '10'
	option name 'eth1.10'
	option ipv6 '0'

config interface 'openvpn'
	option proto 'none'
	option device 'tun1'
	option metric '5'
	option dns_metric '5'
	list dns '<REDACTED_DNS_IP>'

config interface 'wgserver'
	option proto 'wireguard'
	list dns '<REDACTED_DNS_IP>'
	option delegate '0'
	option nohostroute '1'
	list addresses '10.0.8.1/24'

config wireguard_wgserver
	option description 'wghome'
	option persistent_keepalive '25'
	list allowed_ips '10.0.8.2/32'
	option route_allowed_ips '1'

config interface 'guest'
	option proto 'static'
	option device '<BRIDGE_2>'
	option ipaddr '<REDACTED_GUEST_IP>'
	option netmask '255.255.255.0'
	list dns '<REDACTED_DNS_IP>'

config interface 'IOT'
	option proto 'static'
	option device '<BRIDGE_4>'
	option ipaddr '<REDACTED_IOT_IP>'
	option netmask '255.255.255.0'
	list dns '<REDACTED_DNS_IP>'

config defaults
	option input 'DROP'
	option output 'ACCEPT'
	option forward 'REJECT'
	option synflood_protect '1'
	option drop_invalid '1'

config zone 'lan'
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list device 'tun+'
	list network 'lan'

config zone 'wan'
	option name 'wan'
	option input 'DROP'
	option output 'ACCEPT'
	option forward 'REJECT'
	option mtu_fix '1'
	list network 'wan'

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config zone
	option name 'openvpn'
	option input 'DROP'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	list network 'openvpn'

config forwarding
	option src 'lan'
	option dest 'openvpn'

config zone
	option name 'wghome'
	option input 'DROP'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option mtu_fix '1'
	list network 'wgserver'

config forwarding
	option src 'lan'
	option dest 'wghome'

config rule
	option src 'wan'
	option name 'wghome'
	list proto 'udp'
	option dest_port '<REDACTED_WG_PORT>'
	option target 'ACCEPT'

config forwarding
	option src 'wghome'
	option dest 'lan'

config forwarding
	option src 'openvpn'
	option dest 'wan'

config forwarding
	option src 'wghome'
	option dest 'openvpn'

config rule
	option src '*'
	option dest 'wghome'
	option name 'wghome drop all other'
	option target 'DROP'
	list proto 'all'

config zone
	option name 'IOT'
	option input 'DROP'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'IOT'

0.0.0.1/1 via <REDACTED_GATEWAY> dev tun1 
default via <REDACTED_PPPOE_IP> dev pppoe-wan proto static metric 40 
10.0.8.0/24 dev wgserver proto kernel scope link src 10.0.8.1 
10.0.8.2 dev wgserver proto static scope link 
10.96.0.0/16 dev tun1 proto kernel scope link src 10.96.0.21 
<REDACTED_PUBLIC_IP> dev pppoe-wan proto kernel scope link src <REDACTED_PUBLIC_IP> 

config pbr 'config'
	option enabled '1'
	option verbosity '2'
	option strict_enforcement '1'
	option resolver_set 'none'
	list resolver_instance '*'
	option ipv6_enabled '0'
	list ignored_interface 'vpnserver'
	option rule_create_option 'add'
	option procd_boot_trigger_delay '5000'
	option procd_reload_delay '1'
	option webui_show_ignore_target '0'
	option nft_rule_counter '0'
	option nft_set_auto_merge '1'
	option nft_set_counter '0'
	option nft_set_flags_interval '1'
	option nft_set_flags_timeout '0'
	option nft_set_policy 'performance'
	list webui_supported_protocol 'all'
	list webui_supported_protocol 'tcp'
	list webui_supported_protocol 'udp'
	list webui_supported_protocol 'tcp udp'
	list webui_supported_protocol 'icmp'

config include
	option path '/usr/share/pbr/pbr.user.dnsprefetch'
	option enabled '0'

config policy
	option name 'after WG handshake '
	option src_addr '10.0.8.0/24	'
	option interface 'openvpn'
	option priority '900'

config policy
	option name 'WireGuard to WAN'
	option src_addr '10.0.8.0/24'
	option interface 'wan'
	option priority '910'

pbr - environment
pbr 1.2.0-r6 installed on OpenWrt 24.10.5.

Dnsmasq version 2.90  Copyright (c) 2000-2024 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP no-DHCPv6 no-Lua TFTP no-conntrack no-ipset no-nftset no-auth no-cryptohash no-DNSSEC no-ID loop-detect inotify dumpfile

pbr fw4 nft file: /usr/share/nftables.d/ruleset-post/30-pbr.nft
add chain inet fw4 pbr_mark_0x010000
add rule inet fw4 pbr_mark_0x010000  mark set mark and 0xff00ffff xor 0x010000
add rule inet fw4 pbr_mark_0x010000 return
add chain inet fw4 pbr_mark_0x020000
add rule inet fw4 pbr_mark_0x020000  mark set mark and 0xff00ffff xor 0x020000
add rule inet fw4 pbr_mark_0x020000 return
add chain inet fw4 pbr_prerouting ip saddr { 10.0.8.0/24 }  goto pbr_mark_0x020000 comment "after WG handshake "
add chain inet fw4 pbr_prerouting ip saddr { 10.0.8.0/24 }  goto pbr_mark_0x010000 comment "WireGuard to WAN"

IPv4 table 256 pbr_wan route:
default via <REDACTED_PPPOE_IP> dev pppoe-wan 
IPv4 table 256 pbr_wan rule(s):
29991:	from all sport 51820 lookup pbr_wan
30000:	from all fwmark 0x10000/0xff0000 lookup pbr_wan

IPv4 table 257 pbr_openvpn route:
default via <REDACTED_TUN_IP> dev tun1 
IPv4 table 257 pbr_openvpn rule(s):
29998:	from all fwmark 0x20000/0xff0000 lookup pbr_openvpntype or paste code here

Hmm you over redacted way to much.
RFC1918 address should not be redacted as they are private so do not reveal anything but make giving support more difficult.

That said there are some unnecessary or even wrong settings.

I am short on time so can only cover some.

Before you proceed make a backup and after you are done reboot :slight_smile:

Assuming your OpenVPN client is to a commercial third party you cannot fully trust, you should keep the OpenVPN interface in the wan zone or in its own zone with comparable settings.
You did that but then you should remove the following:

The use of things like option dns_metric '5' is useless the same for setting DNS servers on all interfaces as they end up in the same basket.

In your routing you either did not copy all routes but if you did an important route is missing i.e. :
128.0.0.0/1 via <REDACTED_GATEWAY> dev tun1

If that route is not present you have a problem with your OpenVPN config.

About PBR you can delete these rules:

The sport rules should take care of routing traffic via the wan and the default route via the VPN (assuming the 128.0.0.0/1 rule is present) will take care of routing everything via the VPN including the wgserver traffic.

Not sure why you have the following rule, it does not hurt but is unusual

I hope I covered the most important ones :slight_smile:

that is indeed in there and was deleted by accident in the paste. Thank you(!!) for all your advice, I have removed the tun+ hickup in the lan zone. I cannot remove the PBR rules, if I do, its good bye wireguard handshake as the router sends the connection attempt on wan back through openvpn so no handshake. It took me 2 weeks of trial and error to figure out that I needed that rule for the handshake haha. Maybe I don't? In any case the handhake works with that rule but does not work without it. But did you spot a fix for my initial question? when Openvpn disconnects and reconnects, the wgserver loses its route to the internet and only a router reboot (basically flushing of routes) can fix it.

that rule is for future possible compromise with a device attaching to the wgserver zone and thus getting into an 'accept all' group (on all ports, due to traffic rules).

That should not be the necessary as that is what the sport rule is for.

I think that it are actually these rules which are causing your problem provided that the problem is only with the wgserver clients connected form outside via your wg server and not your lan clients.

Unfortunately it is difficult to pinpoint the problem as you over redacted a lot of your settings.

It would help if you would provide the following data without overredacting:

cat /etc/config/network
cat /etc/config/firewall
ip route show
ip -6 route show
ip route show table all
ip rule show
wg show

One more thing make sure that your WireGuard clients e.g. your phone do not have a listen port set it should be a random listenport

For the record this is how I setup WireGuard:

That rule works the other way around you cannot connect from your LAN client to the wg server clients.
If you do not fully trust all your WG server clients you have to set this up differently e.g. with REJECT on the input rule of the WG server firewall zone and a traffic rule to not allow traffic from the WG servers subnet to your LAN subnet and of course you can make an exception for the clients you trust

1 Like

hmmmm I don't think the sport rule is enough, the router, when its default route is via openvpn will send the handshake response back through its default route even if the device request originates on its wan side, unless you (PBR) specifically tell the router to handle this one request differently. Only if the router itself initiates a wan out itself will it listen for a wan in response. And if I remove the PBR rules the handshake simply do not happen so that kind of confirms it. Wg needs a routing change after the handshake happens. Meanwhile,I think that I have identified the problem but not the solution some days ago already and I don't think (think! I don't know!!) the problem is to be found in the traffic or firewall rules. If the router reboots, openvpn gets an internal ip eg 10.09.1.1 and wg routes through that. If openvpn then restarts and changes ip, eg 10.09.1.2 all lan devices channel through that new ip ('flush' works) but the wgserver keeps routing to 10.09.1.1 until manual intervention (and yes, only wg has that problem). It does not seem plausible that the reason for that would be to be found in the traffic/firewall rules(?). Of course i could make a small script, on openvpn restart flush all, but thats a bazooka which will effect all clients there must be another (simple, obvious) solution to maintain routing integrity. The traffic rules come after the routing rules (I think, logically) Maybe a way of making the openvpn ip static? I think the ip is assigned by the tunnel not the router.

That is what the sport rule is for it will route all traffic originating form the WG server back via the wan.

I am running such a setup as we speak my WG client connected from the internet is connected via the WG server and routed out via an OpenVPN client.
I have installed the PBR app and have no policies whatsoever, the sport rule which routes the listenport of the WG server back via the wan is made automatically.

The WG server does not keep any routes the "problem" is PBR that will keep the routes and as already told you should not need the PBR for routes.

Only thing I cannot guarantee is if your old version of PBR is working as intended, I have version 1.2.1-99 :slight_smile:

But as you do not need PBR for anything else then routing return traffic for your WG server you can do it manually just routing the listen port (sport) of the WG server via a routing table with default route via the wan:
OpenWRT Policy Based Routing (PBR)
or via a script:

Have you checked that your WG clients connecting to the WG server do NOT have a listen port set, if they use the same listenport as the WG server that might interfere!

Have you checked that your WG clients connecting to the WG server do NOT have a listen port set, if they use the same listenport as the WG server that might interfere!

yes thats all ok. does your wgserver interface have this setting option 'nohostroute '1'' on 1 or 0? I'm at a loss on how to get rid of the PBR rules and still having a successful handshake. Maybe that is indeed the problem but then I'm not sure what’s wrong with my wgserver config. If you have the exact same setup as me, then clearly something (simple) must be miss-configurerd on my side. And with your explanation my new mission is clear: somehow get rid of these PBR rules while still getting a handshake.

Yes exactly

A host route is for a WG client to route the endpoint address via the wan.

So it should not matter for a WG swerver but when in doubt do not deviate from the default setting and the default setting is with No Host routes unchecked meaning option nohostroute '0' but usually that is absent in your config as that is the default.

You can just stop and disable PBR and do it manually with making a routing table and a routing rule see my earlier post with my notes about manual PBR
In etc/config/network:

config route
    option interface 'wan'
    option target '0.0.0.0/0'
    option gateway '<REDACTED_PPPOE_IP>'
    option table '100'

Your gateway is probably what you redacted but in my notes is described how to find your gateway

then a routing rule to route the listenport of the wg server via this table 100, i assume the listen port is 51820:
/etc/config/network:

config rule
    # for source port
    option sport '51820'
    #table number to use for lookup
   option lookup '100'
   option priority '2000'

You probably do not need local routes but if yo do then also add:

config rule 'policy_localroute'
    option lookup 'main'
    option suppress_prefixlength '1' # See note
    option priority '1000' # lower priority then other rules so that it is hit first

But the PBR app should actually do the same but as said not sure about your old version, for me the PBR app 1.2.1-99 works.

I seem to have fixed it. Following your advice, I just removed the PBR's. And then I started to trial and error. What finally seemed to have done the trick: I turned on masquerade on lan wan openvnp and wgserver. I will still do some testing but all initial testing looks positive! the PBR rules where indeed the problem! Oh and I also changed the INPUT for wghome to accept.

I totally missed that you did not have Masquerading enabled on the WAN, I did not check because you could not have internet access at all without it unless you have IPv6

Masquerading on the lan is not necessary, it can be useful because your local lan clients can have a firewall of their own which is not allowing traffic from your WG server clients (10.0.8.0/24), but better is to tweak the firewall of the local lan clients because by masquerading you cannot make a distinction between your WireGuard server clients, so if you want to make access policies allowing some WG server clients access and others not that cannot be done if you are masquerading on the lan zone .

Masquerading on the WG server is not necessary unless your WireGuard clients are not setup correctly e.g. do not have 0.0.0.0/0 as allowed IPs

Thank you i turned it off for lan and the wg server and it still works. Btw I have an old version of PBR because I don’t update packages (unless security related) between stable firmware updates but I guess I can get rid of PBR all together now because I only have it for the wg which...does not require it. Thank you very(!!) much for your help you helped me get rid of a major headache and liberated me to now deal with my mosquitto/mqtt issues :smiley:

Glad I could be of assistance :slight_smile:

just a quick follow up fyi after full testing. Tt works and openvpn restarts are no longer a problem, but I need to keep PBR installed even if no rules are active. if i stop&disable PBR the handshake does not happen anymore. I dont mind, i will just keep it installed and activated even if I don't really see why its necessary

Yes you need it installed as that is what makes the sport rule which routes return traffic of the wg server back via the wan :slight_smile:

PBR app does that automatically for all wg servers by default

1 Like

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