VPN Policy-Based Routing + Web UI -- Discussion

OK, looks like your OpenVPN settings are filtering the Default Gateway Push.

Sorry, but I'm out of ideas for you.

Just sharing, I found a way to simplify the custom script for Netflix ASN.

# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh


**curl "$TARGET_URL" 2>/dev/null | sed '1d' > "$TARGET_FNAME"**
awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_FNAME" | ipset restore -!

First of all, thanks for developing and helping to troubleshoot this package. Secondly, linux is not my strong suit and I only just started messing with openwrt.

I am having issues with DNS using VLANs and this policy routing package.

I have 5 VLANS: MGMT, LAN, IOT, Telework, Streaming
Desired setup
LAN and IOT=routed through ExpressVPN (with pihole as DNS) -- this is currently working fine
Telework and Streaming=routed through WAN (with Streaming utilizing pihole as DNS) -- this is where the problem is

I have tried implementing a policy in this package (through GUI) to direct Telework and Streaming to WAN and it works (sort of) as long as I don't try and change DNS for streaming (utilizing DHCP options in interface setup). As soon as I change any DNS setting for my Streaming network, EVERY network breaks. I have attached the output of /etc/config/vpn-policy-routing and /etc/init.d/vpn-policy-routing-support in which I have redacted IPs. I will get the reload later as I am currently utilizing the network for work (as is my SO) and I don't want to kick anyone off.

cat /etc/config/vpn-policy-routing

config vpn-policy-routing 'config'
        option verbosity '2'
        option strict_enforcement '1'
        option src_ipset '0'
        option dest_ipset 'dnsmasq.ipset'
        option ipv6_enabled '0'
        list supported_interface ''
        list ignored_interface 'vpnserver wgserver'
        option boot_timeout '30'
        option iptables_rule_option 'append'
        option iprule_enabled '0'
        option webui_protocol_column '0'
        option webui_chain_column '0'
        option webui_sorting '1'
        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 webui_enable_column '1'

config include
        option path '/etc/vpn-policy-routing.netflix.user'
        option enabled '0'

config include
        option path '/etc/vpn-policy-routing.aws.user'
        option enabled '0'

config policy
        option interface 'wan'
        option name 'Telework'
        option src_addr '192.168.Telework.x/x'

config policy
        option interface 'wan'
        option name 'Streaming'
        option src_addr '192.168.Streaming.x/x'

 cat /var/vpn-policy-routing-support
vpn-policy-routing 0.2.1-13 running on OpenWrt 19.07.3. WAN (IPv4): wan/dev/"ISP IP".
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         "VPN IP"       UG    0      0        0 tun0
default         c-"ISP IP".h         UG    0      0        0 eth1.2
IPv4 Table 201: default via "ISP IP" dev eth1.2
"192.168.wifi.x/x" dev br-wifi proto kernel scope link src "192.168.wifi.x"
"192.168.streaming.x/x" dev br-streaming proto kernel scope link src "192.168.streaming.x"
"192.168.IOT.x/x" dev br-IoT proto kernel scope link src "192.168.IOT.x"
"192.168.Telework.x/x" dev br-Telework proto kernel scope link src "192.168.Telework.x"
IPv4 Table 201 Rules:
32761:  from all fwmark 0x10000/0xff0000 lookup 201
IPv4 Table 202: default via "VPN IP" dev tun0
"192.168.wifi.x/x" dev br-wifi proto kernel scope link src "192.168.wifi.x"
"192.168.streaming.x/x" dev br-streaming proto kernel scope link src "192.168.streaming.x"
"192.168.IOT.x/x" dev br-IoT proto kernel scope link src "192.168.IOT.x"
"192.168.Telework.x/x" dev br-Telework proto kernel scope link src "192.168.Telework.x"
IPv4 Table 202 Rules:
32760:  from all fwmark 0x20000/0xff0000 lookup 202
-A VPR_PREROUTING -s "192.168.streaming.x/x" -m comment --comment streaming -c 108190 12336017 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -s "192.168.Telework.x/x" -m comment --comment Telework -c 385885 96998191 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_PREROUTING -m set --match-set ExpressVPN dst -c 0 0 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_PREROUTING -m set --match-set wan dst -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_FORWARD -m set --match-set ExpressVPN 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 ExpressVPN 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
-A VPR_OUTPUT -m set --match-set ExpressVPN 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
Current ipsets
create wan hash:net family inet hashsize 1024 maxelem 65536 comment
create ExpressVPN hash:net family inet hashsize 1024 maxelem 65536 comment

Any help is greatly appreciated. I can definitely try and explain more as well, but I have searched quite a bit to try and figure this out and it just fails every time. Currently my Telework, LAN and IOT networks work fine, but my streaming network cannot resolve DNS even though it is set up to mirror Telework minus the IP scheme. I have been beating my head against a wall for a few days now.

Thanks in advance.

Hi y'all, I had a perfectly functional setup that broke and I'm kind of at a loss for words. The LuCI menu had previously been fully functional, but is now missing any configuration I had already done along with a few of the configuration options. Image attached.

It could be an indication of broken/missing config file. Check if the /etc/config/vpn-policy-routing file is in place and contains valid config.

This has been happening with me for quite some time now and I reported it here. After a few reboots the config file is completely empty. So whenever I make changes to the config I save a copy there as well with .bak extension and then on startup I check whether the config is empty and copy the config from the backup file.

I am having the same problem. After restart everything disappears. Would you like any kind of log file?
Thank you!

I've tried to address the corrupted config file in this build: https://repo.openwrt.melmac.net/vpn-policy-routing_0.2.2-0_all.ipk

PS. major reorganization of my source, package repo and documentation repositories in progress, replace old repo URL (complete URL) with https://repo.openwrt.melmac.net/.

Where do I change the URL in OpenWrt source? I am using custom compiled firmware from source.

I'm not that great with networking
all I know is from YouTube and my own experiences

I have installed OpenWRT on my Linksys WRT 1900 ACS
and It's working greate
I have something I want to setup and I don't know how honestly...

I want my network to be connected to 2 VPNs ( UK & US )
I want group my network in 3

1 - Devices that are connected to the US VPN
2 - Devices that are connected to the UK VPN
3 - Devices that are not connected to either VPN

I have the OpenVPN packages installed
and the VPN Policy-Based Routing + Web UI packages installed
But I don't know how to configure them honestly

My VPN provider is ExpressVPN


I Know that ExpressVPN have their own firmware
I have tried it , it drops a lot and is unstable in my experience. + they don't allow two clients to be connected at the same time (2 locations at the same time)
So I'm trying to do it by myself... but honestly I couldn't figure it out

Is this possible pls?

Hi (from Canada too!)

I've been playing with the module for the past few hours but things are just weird.

One tunnel is an OpenVPN tunnel via tap0. I can't make it route networks through that tunnel.
I think I may have found the issue: I explicitely need to specify a "gateway".

Is this possible somehow?

Example: My OpenWRT box creates a tunnel tap0 with IP (the latter is just statically assigned). I want to route some things via (which is at the other side of the tunnel).

This works with my static routes ... but it seems that the policies are processed first. But there I also want to modify the default gateway. So I think the normal rules are never processed.

Is one of these two possible?

  1. Execute policy routing after the normal routing table?
  2. Supply an explicit gateway
  3. Rule that returns from the policy table (and continues with the normal, static table) on match.

How can I correctly specify the following rule:

config policy
        option name 'NordVPN'
        option src_addr '@wlan0 @wlan1 @eth0.1'
        option dest_addr '! !'
        option interface 'nordvpntun'

What I want to achieve is to route everything to a NordVPN tunnel coming from the given interfaces EXCEPT when the destination is OR (this would alternatively solve my issue above).

While things seem to work if I include only one of them option dest_addr '! OR option dest_addr '!, it doesn't match properly when both are included.

Is there a bug or do I understand this syntax wrong?

Check the instructions at https://docs.openwrt.melmac.net.

I guess it's possible but you will need to do a lot of custom scripting, most likely creating another table, modifying the custom files to use that table and creating a custom iptables rule for affected devices.

Sorry, I don't have any experience with tap tunnels, I don't think I can help you.

There are global append rules, which may work for you, but if not, the syntax is "!a,b,c".

There are global append rules, which may work for you,[/quote]

thank you; I am really sorry if I don't get it but could you elaborate on it? I grep'ped the README for global, append, etc. but nothing showed up that could be related.

Hmm, are you sure that's the right syntax?
I had tried it already and Luci doesn't take it:

Regardless, I tried changing it directly in the config but:

root@MapleGate:~# /etc/init.d/vpn-policy-routing restart
Creating table 'wan/eth1.2/' [✓]
Creating table 'vpn/tap0/' [✓]
Creating table 'nordvpntun/tun0/' [✓]
Routing 'VPN_GW' via wan [✓]
Routing 'NordVPN3' via nordvpntun [✗]
vpn-policy-routing 0.2.1-13 started with gateways:
wan/eth1.2/ [✓]
ERROR: iptables -t mangle -I VPR_PREROUTING -j MARK --set-xmark 0x030000/0xff0000  -m physdev --physdev-in wlan0 ! -d,  -m comment --comment NordVPN3
ERROR: iptables -t mangle -I VPR_PREROUTING -j MARK --set-xmark 0x030000/0xff0000  -m physdev --physdev-in wlan1 ! -d,  -m comment --comment NordVPN3
ERROR: iptables -t mangle -I VPR_PREROUTING -j MARK --set-xmark 0x030000/0xff0000  -m physdev --physdev-in eth0.1 ! -d,  -m comment --comment NordVPN3

vpn-policy-routing 0.2.1-13 monitoring interfaces: wan vpn nordvpntun .

PS: This all could be avoided if we could just process the normal routing table first. In the end this would be a hack anyway in which I'd replicate the local routing table (because always default routes should be executed after specific routes -- that's the whole idea about it...)

Unfortunately the troubles get only more and more. Newest things that breaks: NAT reflection (I can tell details on why if desired but I am almost positive it will break for everyone who uses VPN Policy Based Routing with NAT reflection!).

What we really need is a simple Policy "just get me out of here" if it matches.
Currently the problem is, as I see it, that it's just not possible to exclude anything from this complete Policy Routing Framework.

So in addition to the target interfaces, I'd like to see something like IGNORE, RETURN etc where just nothing is done if things match (except that no policy based routing is performed at all!)

This would literally fix all three issues that I mentioned above.

EDIT: There should be rules created which disable policy routing when the destination is a local IP. For me:

root@MapleGate:~# iptables -t mangle -I PREROUTING 1 -d -j RETURN
root@MapleGate:~# iptables -t mangle -I PREROUTING 1 -d -j RETURN

I don't see any downside on that and it does not break NAT reflection.

Thank you for reply

Ah, maybe multiple addresses in -s/-d are not supported by iptables or not supported in a combination with --physdev, I've only used it for ports and the config syntax is correct. You can run the errored out iptables command to see what it complains about.

You can put these in a custom user file to run at the end of the VPR start.

Hi stangri,

Thanks for your reply. Right now I do have a custom user file but this is expremely hacky.

I hope you see my point which is:

With "VPN Policy-Based Routing" enabled, the normal routing table is always ignored, except there is no match in the Policy List. It is not possible to make exclusions from Policy Routing!

For that reason I propose an IGNORE or RETURN target (which translate into "-j RETURN" rules for iptables).

Do you consider adding this?

Also, let me give a very conrete example where the current system fails:

  • You have an interface to another private subnet (could be a company VPN or whatever, say VPN). The IP address is Other company nets (say, and are reachable via The system contains the proper routing table entries for that: route add netmask gw, route add netmask gw
  • You have a VPN tunnel NORDVPNTUN (e.g., a NordVPN tunnel) over which you want to route all internet traffic from Wifi
  • The default gateway is as usual the wan interface
  • Hence you create the following entries:
  • You realize you can't reach your whole company network any more.
  • Desparately you try to limit how the rule is applied (by adding complicated string into "Remote addresses/domains". But this fails except for the most simplistic scenatio (see above).
  • What would be the only logical setup is this:

Hey, great idea, it would solve a lot of problems. I'm not sure if adding INGORE as an interface/gateway is a good idea for 99% of the users tho, let me sleep on it.