VPN Policy-Based Routing + Web UI -- Discussion

That would be absolutely amazing.
It would literally solve all the issues I have reported here and I am sure many more.

If you think things get too confusing ... what about adding an advanced option for enabling the display of such an option? (you have already a few of them anyway).

This way, instead of adding a "IGNORE" to "Interface" there could be an additional column with a checkbox "IGNORE". Although I personally like the initial suggestion better.


Hello everyone,
firstly thanks for this great plugin, I couldn't do without it.

I am trying to wrap my head around something, maybe someone here could help me understand:

I've set up a wireguard client on openwrt to route all network traffic. Now I want to set up my gaming desktop to connect directly (without wireguard). This works fine so far (ip based policy). I now want to setup https-dns-proxy (stubby plugin) as well, but only for machines not using wireguard.

  1. Is this possible and how? and
  2. I am afraid this might break other addons like addblocker and ban-ip?
  3. Will this be more trouble to set up than it's worth?

someone has mentioned to be that it is a bad idea to use this package with wireguard because its UDP, why would that be?

Hi, I'm trying to route certain domains over vpn and am wondering if there's a more efficient way to do it.

I have several very similar domains. For example:

Is there a way to route all domains that end with "abc.com" regardless of what comes before it over the vpn?
When I simply use "abc.com", I am left with errors.


Thanks again for your brilliant suggestion, the ignore option for the interface is supported in vpn-policy-routing 0.2.2-1 available from my repo. Again, this is a test version, I may rename/reimplement this in the future, so be sure to check this thread again before upgrading.

It's only supported in the principal app as a test, it is not yet supported in WebUI. I may need some time to think thru how to best implement it in WebUI.

Please test it and LMK how it went.

Serving different resolvers for different clients in your LAN is outside of the scope of this project, you may be better off seeking help elsewhere.

You should ask that "someone" and I'd appreciate if you post here their answer as well. It may very well be the case, there are a lot of other devs and people on this forum who have more in-depth knowledge of networking than I do.

I'm pretty confident README has this covered.


I have a hairpin NAT loopback to be able to access my self-hosted server domain (resolving to my WAN IP) from within my home network.

It is implemented in custom firewall rules:

iptables -t nat -A prerouting_rule -d {{public_WAN_ip}} -p tcp --dport 443 -j DNAT --to {{local_ip:port to handle the request}}
iptables -A forwarding_rule -p tcp --dport {{local port}} -d {{local ip}} -j ACCEPT
iptables -t nat -A postrouting_rule -s {{local network}} -p tcp --dport {{local port}} -d {{local ip}} -j MASQUERADE

It works when I restart my firewall but then when I enable vpn policy routing it stops working.

Looking for help on debugging.

relevant parts
server is configured to go through wan

config vpn-policy-routing 'config'
	list supported_interface ''
	option boot_timeout '30'
	option webui_enable_column '0'
	option webui_protocol_column '0'
	list webui_supported_protocol 'tcp'
	list webui_supported_protocol 'udp'
	list webui_supported_protocol 'tcp udp'
	list webui_supported_protocol 'icmp'
	list webui_supported_protocol 'all'
	option enabled '1'
	option ipv6_enabled '1'
	option src_ipset '1'
	option webui_sorting '0'
	option iptables_rule_option 'append'
	option iprule_enabled '0'
	option webui_chain_column '0'
	option strict_enforcement '1'
	option dest_ipset 'dnsmasq.ipset'
	option verbosity '0'

config policy
	option interface 'wan'
	option name 'server'
	option src_addr '{{local ip}}'
# This doesn't do anything to fix the problem but I thought I'd try this.
config policy
	option interface 'wan'
	option name 'loopback'
	option dest_addr '{{external domain that resolves to wan IP}}'

/etc/init.d/vpn-policy-routing support

vpn-policy-routing 0.2.1-8 running on OpenWrt 18.06.5. WAN (IPv4): wan/dev/{{WAN))
Dnsmasq version 2.80  Copyright (c) 2000-2018 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC no-ID loop-detect inotify dumpfile
Routes/IP Rules
default         *              U     0      0        0 wgclient
IPv4 Table 201: default via {{WAN}} dev eth0.0
IPv4 Table 201 Rules:
32705:	from all fwmark 0x10000/0xff0000 lookup 201
IPv4 Table 202: default via {{VPN}} dev wgclient
IPv4 Table 202 Rules:
32704:	from all fwmark 0x20000/0xff0000 lookup 202
IPv6 Table 201: fe80::/64 dev eth0.0 proto kernel metric 256 pref medium
IPv6 Table 202: {{VPN}} dev wgclient proto kernel metric 256 pref medium
IPv6 Table 202: default dev wgclient proto static metric 1024 pref medium
-A VPR_PREROUTING -p udp -m multiport --dports 5060 -m comment --comment SIP_Ports -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -p tcp -m multiport --dports 5060 -m comment --comment SIP_Ports -c 1 52 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -m set --match-set wgclient_mac src -c 5727 419512 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_PREROUTING -m set --match-set wgclient_ip src -c 0 0 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_PREROUTING -m set --match-set wgclient dst -c 23 3076 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_PREROUTING -m set --match-set wan_mac src -c 90433 32787727 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -m set --match-set wan_ip src -c 24569 21052089 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -m set --match-set wan dst -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -p udp -m multiport --dports 5060 -m comment --comment SIP_Ports -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -p tcp -m multiport --dports 5060 -m comment --comment SIP_Ports -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -m set --match-set wgclient_mac src -c 9 696 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_PREROUTING -m set --match-set wan_mac src -c 451 102090 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_FORWARD -m set --match-set wgclient dst -c 0 0 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_FORWARD -m set --match-set wan dst -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_INPUT -m set --match-set wgclient dst -c 0 0 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_INPUT -m set --match-set wan dst -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
IPv6 Tables INPUT
-A VPR_OUTPUT -m set --match-set wgclient dst -c 0 0 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_OUTPUT -m set --match-set wan dst -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
IPv6 Tables OUTPUT
Current ipsets
create wan hash:net family inet hashsize 1024 maxelem 65536 comment
create wan_ip hash:net family inet hashsize 1024 maxelem 65536 comment
add wan_ip {{local server IP}} comment "server: {{local server IP}}"
create wgclient hash:net family inet hashsize 1024 maxelem 65536 comment
add wgclient .............. {redacted}
add wgclient .............. {redacted}
add wgclient .............. {redacted}
add wgclient .............. {redacted}
create wgclient_ip hash:net family inet hashsize 1024 maxelem 65536 comment
create wan_mac hash:mac hashsize 1024 maxelem 65536 comment
.............. {redacted}
DNSMASQ ipsets
ipset=/{{hostname that resolves to my external IP}}/wan # loopback

/etc/init.d/vpn-policy-routing reload

Creating table 'wan/eth0.0/{{redacted network}}' [✓]
Creating table 'wgclient/{{redacted network}}' [✓]
Routing .....redacted...
Routing 'server' via wan [✓]
Routing 'loopback' via wan [✓]
vpn-policy-routing 0.2.1-8 started with gateways:
wan/eth0.0/{{redacted network}}
wgclient/{{redacted network}} [✓]

Getting these errors on a fresh flashed unit for any device I try routing through, thx

Service Status

Service Gateways
US_Nordvpn/tun0/ ✓

Service Errors
Unknown fw_mark for us_nordvpn



Solved by reverting to vpn-policy-routing_0.2.2-0_all.ipk

I had a similiar problem - keep in mind that the interface names are case-sensitive. in my case the interface name was openVPN while PBR seems to use openvpn .


Having the same issues with 0.2.2-1! Where can I download the previous version?

Sorry, should be fixed in 0.2.2-2.

1 Like

Awesome, thx!

I was recently made aware that the (regular, not dnsmasq) ipset only adds the first IP address of the domain on add, making me rethink the whole ipset/ipset.dnsmasq processing.

I'm thinking that in the next version, if the candidate for dnsmasq.ipset is discovered within the policy, but the dnsmasq.ipset is not supported on the system, process it regularly but throw a warning, otherwise all suitable dnsmasq.ipset candidates will be added to dnsmasq ipset automatically, without the need to configure anything.

The dest_ipset will be returned to boolean state and will function similarly to src_ipset.

I would welcome feedback from veteran and new users on this change.


I have never added a third-party repository.
Just wanted to check: If I add your repository, will only vpn-policy-routing & luci-app-vpn-policy-routing be taken from the repository or should I take any precautions to not interfere with other packages?
Would you recommend to just download the two ipkg's for this test and install offline with opkg?

My repo contains only the packages I maintain and I try to maintain compatibility with both snapshots and 19.07/18.06 releases, so it should be safe to add, however you can also grab the IPK for the principal package and install/upgrade just that.

Ok, I added your repo now and tried the new version.


It seems that the order of preference of the policies is from last to first.
What I mean: the last "policy" entry is inserted into the chain first (has highest preference).

I only realized this now and this is really confusing (particularly since the web-interface allows ordering of entries). Is this on purpose? If you don't wanna change it, it may be a good to explicitely add the note (not just docu but also under "Comment, interface and at least one other field are required. [...]" in the web interface.

Other than that it really works nicely. I would suggest to add this somehow to the webinterface. Now an entry with "ignore" is shown as having interface "WAN" in the web interface.


Actually, maybe I misunderstand. Now I flipped the order of previous rules (that have MARK as target) and the rules stopped working. Is the system built in a way such that later entries overwrite markers of previous entries?

If this is the case, then the "ignore" probably requires additional logic to place it into the VPR_-chain in the right order.

I tried looking for this but if it's there, it's buried where I couldn't easily find it.

In the "README.md" file, there is a section "Basic OpenVPN Client Config" with a reference to multiple guides for setting up OpenVPN but incompatible with this package, followed by some sample settings that are guaranteed to work (with a proper OpenVPN configuration, of course). My question is, is there a recommended guide that results in a compatible OpenVPN setup? I'm experiencing issues and before I try asking for help, I want to make sure I am running a proper OpenVPN setup first. After all, if I'm not, I'll have to do it anyways, so better to take care of that up front. Not only that, but would feel better knowing that I'm using a right configuration for better security.

So simply put... A recommended guide for a compatible OpenVPN configuration please. Thank you.

First of all thanks for all the effort on making this package happen.

I have a corner case problem with package but I cloud not resolve it using my knowledge of OpenWrt and linux and send you a PR on github, so I'm seeking help here.

This my situation. I have 3 wireguard(2 to work and to a datacenter) vpns and 3 internet connections(TD-LTE, pppoe over adsl and pppoe over p2p wifi provider). Sometimes phone line is noisy and pppoe over ADSL disconnects and connects 2 or 3 times. Lets assume it is 3 times. This triggers reload operation 3 times. Last two pppoe reconnection happens when 1st reload is running. after 1st reload is complete then 2nd and 3rd reload run. I think one of the 2nd and 3rd reloads can be eliminated because the start time 2nd reload is greater than 3rd reconnection. I Think following diagram can clear what I'm trying to describe

How can I eliminate such thing?
I was thinking about logging event time and reload start time somewhere and then check those to decide. My idea is to implement reload_service and save those things using procd_set_param but documentation around procd is somehow sparse and I'm not sure if it can be done this way or not.

I you can give some clues about how it must be done I would be happy to help

Again Thanks for all your efforts

Please try your rules as they were before I introduced the ignore option and then put ignore policies at the very bottom. Let me know if that works.