What's new

Selective Routing with Asuswrt-Merlin

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Try adding the full path to the 'whob' command in the script....

I seriously thought that was going to be the answer...
Unfortunately, I got the same results...

Nov 27 20:45:50 ovpn_split[1576]: + opkg install whob
Nov 27 20:45:50 ovpn_split[1576]: Package whob (3.76-1) installed in root is up to date.
Nov 27 20:45:50 ovpn_split[1576]: + /opt/bin/whob -h whois.radb.net -- -i origin AS40027
Nov 27 20:45:50 ovpn_split[1576]: + grep -Eo ([0-9.]+){4}/[0-9]+
Nov 27 20:45:51 ovpn_split[1576]: + netsv4=
Nov 27 20:45:51 ovpn_split[1576]: + unset netsv4
Nov 27 20:45:51 ovpn_split[1576]: + /opt/bin/whob -h whois.radb.net -- -i origin AS55095
Nov 27 20:45:51 ovpn_split[1576]: + grep -Eo ([0-9.]+){4}/[0-9]+
Nov 27 20:45:51 ovpn_split[1576]: + netsv4=
Nov 27 20:45:51 ovpn_split[1576]: + unset netsv4
Nov 27 20:45:51 ovpn_split[1576]: + /opt/bin/whob -h whois.radb.net -- -i origin AS2906
Nov 27 20:45:51 ovpn_split[1576]: + grep -Eo ([0-9.]+){4}/[0-9]+
Nov 27 20:45:51 ovpn_split[1576]: + netsv4=
Nov 27 20:45:51 ovpn_split[1576]: + unset netsv4
Nov 27 20:45:51 ovpn_split[1576]: + ipset -L NETFLIXCIDR
Nov 27 20:45:51 ovpn_split[1576]: Name: NETFLIXCIDR
Nov 27 20:45:51 ovpn_split[1576]: Type: hash:net
Nov 27 20:45:51 ovpn_split[1576]: Revision: 0
Nov 27 20:45:51 ovpn_split[1576]: Header: family inet hashsize 1024 maxelem 65536
Nov 27 20:45:51 ovpn_split[1576]: Size in memory: 8500
Nov 27 20:45:51 ovpn_split[1576]: References: 0
Nov 27 20:45:51 ovpn_split[1576]: Members:
 
I seriously thought that was going to be the answer...
Unfortunately, I got the same results...

Well I'm stumped :confused:

However, I suggest you retrieve the subnets the 'old-skool' way using curl direct from ipinfo.io (like I do) and ditch your preferred 'whob/radb.net combo' and try

Code:
ASNUM="AS40027"
netsv4=`curl http://ipinfo.io/$ASNUM  2>/dev/null | grep -E "a href.*$ASNUM\/" | sed 's/^.*\">//; s/<.*//; /^\s*$/d'`;for net in $netsv4;do echo $net;done;unset netsv4

Code:
admin@RT-AC68U:/jffs/scripts# netsv4=`curl http://ipinfo.io/AS40027  2>/dev/null | grep -E "a href.*AS40027\/" | sed 's/^.*\">//; s/<.*//; /^\s*$/d'`;for net in $netsv4;do
 echo $net;done;unset netsv4
45.57.40.0/24
45.57.8.0/23
45.57.8.0/24
45.57.9.0/24
2a00:86c0:2008::/47
2a00:86c0:2008::/48
2a00:86c0:2009::/48
2a00:86c0:2040::/48
admin@RT-AC68U:/jffs/scripts#

NOTE: whob may be quicker, in so far that 'curl ipinfo.io' returns 2279 lines of HTML code, vs. 429 report lines returned by 'whob whois.radb.net'. but seems to only return 42 subnets vs. 144 from ipinfo.io for AS2906?

P.S. I left out the '#!/bin/sh' line! :p
 
Last edited:
Well I'm stumped :confused:

However, I suggest you retrieve the subnets the 'old-skool' way using curl direct from ipinfo.io (like I do) and ditch your preferred 'whob/radb.net combo' and try

My preferred method is a method that works. I got that code from another site and don't have a much better idea of how it works than how yours works. lol.

I just ran your code and it actually produced IPs from script on reboot!

I was losing my freaking mind. Thank you!

I will be out of town until Tuesday night so I won't be able to update my instructions with your suggestions and notes until at least then.

The one thing I noticed is that it is pulling in IPV6 addresses. I assume that is what the non-regular looking IP addresses are anyways. I assume that won't matter since I have IPV6 disabled?

Thanks for all your assistance!
 
The one thing I noticed is that it is pulling in IPV6 addresses. I assume that is what the non-regular looking IP addresses are anyways. I assume that won't matter since I have IPV6 disabled?

Unfortunately, through necessity, the world is moving (chaotically) to formally adopt IPv6..... IoT etc :eek:.

You personally could filter out the IPV6 subnets (my script creates two IPSETS if IPv6 subnets are returned; e.g. AS40027 and AS40027-v6) but your code (as it stands at the moment) lazily leaves it to ipset to reject the add request of IPv6 subnets into the IPv4 only IPSETs.

e.g. for a clean IPv4 only list:

Code:
netsv4=`curl http://ipinfo.io/AS40027  2>/dev/null | grep -E "a href.*AS40027\/" | sed 's/^.*\">//; s/<.*//; /^\s*$/d' | grep -v ":"`;for net in $netsv4;do echo
 $net;done;unset netsv4

but others may want to see/save the IPv6 subnets
 
Unfortunately, through necessity, the world is moving (chaotically) to formally adopt IPv6..... IoT etc :eek:.

You personally could filter out the IPV6 subnets (my script creates two IPSETS if IPv6 subnets are returned; e.g. AS40027 and AS40027-v6) but your code (as it stands at the moment) lazily leaves it to ipset to reject the add request of IPv6 subnets into the IPv4 only IPSETs.

e.g. for a clean IPv4 only list:

Code:
netsv4=`curl http://ipinfo.io/AS40027  2>/dev/null | grep -E "a href.*AS40027\/" | sed 's/^.*\">//; s/<.*//; /^\s*$/d' | grep -v ":"`;for net in $netsv4;do echo
 $net;done;unset netsv4

but others may want to see/save the IPv6 subnets

Thanks. The main reason I left them out is because my understanding is that IPV6 is more susceptible to DNS/WAN IP leaks.

As you can see from reading all of my questions/comments, I am a novice at this, but I am persistent in trying to learn something when I am interested in it. The routing world seems like it has a huge learning curve though. I would be interested in learning more about iptables, ipset, IPV6, NAT, compiling modules for different kernel versions, understanding what functionality is available at different times during the router boot up, when to load something and when to clean it up and load it again, etc... but don't really know where to start. For now, I am just trying to dig in and try to get something to work by cobbling together other working pieces. I like to do a lot of reading and trying stuff before asking questions. I know that you get more help that way when you make an effort.

If you have any suggestions on reading material, I will dive in as time permits. I also am sadly lacking in Linux/Unix experience which I will definitely start to remedy soon. It is the way the world has been going for smart phones, routers, and a lot of other things that I am interested in.
 
Thanks a lot for this info but as someone who is totally new to this and would really like to be able to disable routing Netflix and BBC iPlayer etc over the VPN, I'm finding all the pastes of code pretty hard to follow.

Would you guys (jinx10000 and/or Martineau) be able to write up a step-by-step guide with the latest and greatest instructions that are confirmed working? Perhaps a new thread would be a good idea.

I (and I am sure others!) would very much appreciate it!
 
Thanks a lot for this info but as someone who is totally new to this and would really like to be able to disable routing Netflix and BBC iPlayer etc over the VPN, I'm finding all the pastes of code pretty hard to follow.

Would you guys (jinx10000 and/or Martineau) be able to write up a step-by-step guide with the latest and greatest instructions that are confirmed working? Perhaps a new thread would be a good idea.

I (and I am sure others!) would very much appreciate it!

If you would have asked last week, I may have had more time to do it. I made some slight improvements to the code. Mostly I just have the router reboot when nat-start is called. This happens every 3 or 4 days rather than twice daily. I couldn't really figure out what Martineau was doing with his nat-start script. Either way, mine works all the time now.

I may update the instructions on the next day or two with the new code. Otherwise it's pretty steep by step already. Just broke it into sections...
 
Hi!

This post has been extremely helpful setting up my routes so I wanted to share what I ended up doing in my AC68U running john9527's 374.43_2 fork 22E2

Scenario:
  1. I have an OpenVPN client running (PIA)
  2. I require every outgoing connection to be tunneled, even those by the router itself
  3. I need to be able to access a couple tcp/udp ports from the outside (VPN Server, SSH, blahblah)
What I found was the same as almost everyone ending up here:
  • If I start the ovpn client and redirect internet traffic I can no longer access the router from wan side
  • If I don't redirect traffic but rather mark specific ports everything works besides item 2. Every connection made by the router itself goes outside of the vpn tunnel
I ended up with the following:
Redirect Internet Traffic: ALL
Custom Configuration:
  • route-nopull
  • up /jffs/scripts/openvpn-event
  • down /jffs/scripts/openvpn-event
had to add up and down scripts because the default config only has route-up and route-pre-down (pointing at vpnrouting.sh which will call openvpn-event)

Code:
#!/bin/sh

PARAM=$*
if [ "$PARAM" == "" ]
then
    # Add paramaters equivalent to those passed for up command
    PARAM="$dev $tun_mtu $link_mtu $ifconfig_local $ifconfig_remote"
fi

RestoreInitialState(){
    #Restore Settings to initial state
    ip route flush table 12
    ip route del default table 12
    ip rule del fwmark 1 table 12
    ip route flush cache
    #iptables -t mangle -F PREROUTING
}

CopyRouteTables(){
    ip route show table main | grep -Ev $dev\
    | while read ROUTE ; do
        ip route add table 12 $ROUTE
    done
    ip rule add fwmark 0x0200 table 12 prio 999
}

FirewallEntries(){
    if [ -f /jffs/scripts/openvpnclient$CLNT.postconf.fw-entries ]
    then
       cat /jffs/scripts/openvpnclient1.postconf.fw-entries >> /etc/openvpn/fw/client$CLNT-fw.sh
    fi
}

#BEGIN
TYPE=$(echo $dev | cut -c 4)
CLNT=$(echo $dev | cut -c 5)
if [ $TYPE -eq 1 ]
then
    logger -t "($(basename $0))" $$ "Executing openvpn-event for CLIENT with PARAM=$PARAM script_type=$script_type dev=$dev"
    if [ $script_type == 'up' ]
    then
        RestoreInitialState
        CopyRouteTables
        FirewallEntries
    fi

    if [ $script_type == 'route-up' ]
    then
        service restart_firewall
    fi


    if [ $script_type == 'down' ]
    then
        RestoreInitialState
    fi
fi

Just enter here every iptables entry that needs to be added, it will also be added to /etc/openvpn/fw/client1-fw.sh which will take care not only to repopulate the tables (in case the firewall is restarted) but also to remove every entry upon client disconnection.
You have to put here the code to change rp_filter since it should be executed on every firewall restart
In my case:
Code:
logger -t "($(basename $0))" $$ "Changing RP_Filter"
for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
    echo 0 > $i
done
iptables -t mangle -A OUTPUT -p tcp -m multiport --sport xxx -j MARK --set-mark 0x200/0x200
iptables -t mangle -A OUTPUT -p udp -m multiport --sport xx -j MARK --set-mark 0x200/0x200
iptables -t mangle -A OUTPUT -p udp -m multiport --sport xxx -j MARK --set-mark 0x200/0x200
iptables -t mangle -A OUTPUT -p udp -m multiport --sport xxxx -j MARK --set-mark 0x200/0x200
iptables -t mangle -A OUTPUT -p $(nvram get vpn_server1_proto | cut -c 1-3) -m multiport --sport $(nvram get vpn_server1_port) -j MARK --set-mark 0x200/0x200
Those are services residing within the router, that is why I cound not get them working by adding those entries in the PREROUTING chain. The last one dinamically adds my ovpn server 1 regardless of protocol and port ;)

Feel free to point any leakages I might have with this configuration, brand new to me!

S
--

EDIT Jan 13th: Update with latest version of my config
 
Last edited:
I have a small issue I was hoping to get some help with.

I have the Asus RT AC3100 running firmware 380.64_2 , configured OpenVPN client (goldenfrog) with 3 wired devices that are policy routed through the VPN using the GUI.

All other devices on the network use the WAN, but can not connect to Netflix. I get an error aip-701 on my Vizio TV when I check the connection in the Netflix app it fails the connection to their 4 servers but passes the internet check. I've tried on several devices but Netflix won't load on a SmartTV, Roku, or smartphone. Nor will it load in a browser on PC.

All devices are routing properly, the 3 wired devices go to the VPN but Netflix blocks traffic to the WAN devies. My ISP, Netflix, and VPN are all in the US. If I turn off the VPN client Netflix works perfectly on all devices.
 
.......Netflix won't load on a SmartTV, Roku, or smartphone. Nor will it load in a browser on PC.
Netflix blocks traffic to the WAN devies. My ISP, Netflix, and VPN are all in the US. If I turn off the VPN client Netflix works perfectly on all devices.

Sounds like a possible DNS issue?..Netflix will block known VPN/Smart DNS etc.

I can't remember if the following will work
i.e. temporarily add the Roku/Smart TV/ PC to use the WAN/DNS in the VPN Policy rules
Code:
Roku         xxx.xxx.xxx.xxx   0.0.0.0   WAN
Smart TV     xxx.xxx.xxx.xxx   0.0.0.0   WAN
Netflix PC   xxx.xxx.xxx.xxx   0.0.0.0   WAN


if not, then you may need to:

1. Review 'Strict/Exclusive' VPN DNS setting,
2. Check /etc/dnsmasq.conf for 'server=/Netflix.com/' directives
3. Use DNSFilter to force the Netflix devices to use ISP/Google DNS etc.
 
Last edited:
if not, then you may need to:

1. Review 'Strict/Exclusive' VPN DNS setting,

VPN DNS is "Strict"

2. Check /etc/dnsmasq.conf for 'server=/Netflix.com/' directives

Do I need to add this to dnsmasq.conf? There's nothing mentioning Netflix in the file.

3. Use DNSFilter to force the Netflix devices to use ISP/Google DNS etc.
I have the WAN set to use google's DNS 8.8.8.8, 8.8.4.4 I'll try setting it in DNSfiltering too.


Thanks for the reply I'll let you know if it works.
 
Do I need to add this to dnsmasq.conf? There's nothing mentioning Netflix in the file.

Not unless the other options don't work.

Having a
Code:
server=/netflix.com/xxx.xxx.xxx.xxx
directive in /etc/dnsmasq.conf is a method of forcing a specific (Smart) DNS server to be used to resolve the domain.
 
Dear all,

Did someone successfully applied the method documented here: https://github.com/RMerl/asuswrt-merlin/wiki/Policy-based-routing-(manual-method)?

I tried the manual one, not the asuswrt Merlin policy based routing GUI, because I want to redirect a device traffic through a tunnel keeping access to a website hosted on this device from the ISP gateway, using some port forwarding.
But for the moment I'm stuck on routing all traffic through the ISP gateway except this device.

Here is the exact copy of my "openvpn-event" script:

Code:
#!/bin/sh

sleep 10

for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 0 > $i
done

ip route flush table 100
ip route del default table 100
ip rule del fwmark 1 table 100
ip route flush cache
iptables -t mangle -F PREROUTING

ip route show table main | grep -Ev ^default | grep -Ev tun11 | while read ROUTE ; do
ip route add table 100 $ROUTE
done
ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache

iptables -t mangle -A PREROUTING -i br0 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.77.2 -j MARK --set-mark 0

iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 8080 --match iprange --src-range 192.168.77.2 -j MARK --set-mark 1

So 192.168.77.2 is the static private IP of the device which should use the VPN.

The problem is every devices are using the VPN.
I'm using an RT-AC3200 with the 380.65 firmware. It was the same behaviour with 380.64-2 firmware then I decided to upgrade it.
I tried setting the sleep time to 2 sec then 10 sec. Nothing changed.
My Open VPN client GUI panel is configured as above:
Select client instance: Client1
Service state: ON
Start with WAN: Yes
Create NAT on tunnel: Yes
Redirect Internet traffic: No

The VPN provider is IP Vanish.

Any clue?
Thanks for your help.
 
Dear all,

Did someone successfully applied the method documented here: https://github.com/RMerl/asuswrt-merlin/wiki/Policy-based-routing-(manual-method)?

I tried the manual one, not the asuswrt Merlin policy based routing GUI, because I want to redirect a device traffic through a tunnel keeping access to a website hosted on this device from the ISP gateway, using some port forwarding.
But for the moment I'm stuck on routing all traffic through the ISP gateway except this device.

Here is the exact copy of my "openvpn-event" script:

Code:
#!/bin/sh

sleep 10

for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 0 > $i
done

ip route flush table 100
ip route del default table 100
ip rule del fwmark 1 table 100
ip route flush cache
iptables -t mangle -F PREROUTING

ip route show table main | grep -Ev ^default | grep -Ev tun11 | while read ROUTE ; do
ip route add table 100 $ROUTE
done
ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache

iptables -t mangle -A PREROUTING -i br0 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.77.2 -j MARK --set-mark 0

iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 8080 --match iprange --src-range 192.168.77.2 -j MARK --set-mark 1

So 192.168.77.2 is the static private IP of the device which should use the VPN.

The problem is every devices are using the VPN.
I'm using an RT-AC3200 with the 380.65 firmware. It was the same behaviour with 380.64-2 firmware then I decided to upgrade it.
I tried setting the sleep time to 2 sec then 10 sec. Nothing changed.
My Open VPN client GUI panel is configured as above:
Select client instance: Client1
Service state: ON
Start with WAN: Yes
Create NAT on tunnel: Yes
Redirect Internet traffic: No

The VPN provider is IP Vanish.

Any clue?
Thanks for your help.
Is your VPN's DNS set to strict or exclusive?

Try setting it to exclusive and route everything in the guI by local IP and the respective tun either VPN or WAN. It's time consuming but the only way I found where everything works as intended. You may want to format jffs and get rid of those custom scripts to avoid potential routing conflicts, back them up in case you want to revert to the manual method.
 
Is your VPN's DNS set to strict or exclusive?

Try setting it to exclusive and route everything in the guI by local IP and the respective tun either VPN or WAN. It's time consuming but the only way I found where everything works as intended. You may want to format jffs and get rid of those custom scripts to avoid potential routing conflicts, back them up in case you want to revert to the manual method.

Thanks kudzero. The problem is that doing so you have to think about adding one additional policy rule each time you add a new device... :)
I'm wondering if someone succeeded using the manual method to route traffic through WAN by default.
 
:-(
After having upgraded to the last version, it doesn't work anymore, on 380.65_4 version of asusrt-merlin.
But this version looks more stable, as now the client list interface work pretty weel! :)
 
After having upgraded to the last version, it doesn't work anymore

To be honest, I don't believe there is any valid reason to use the manual scripting method anymore even when Selective Port Routing (which isn't supported via the GUI) is required using the necessary custom fwmarks.

i.e. using the (far more reliable) GUI Selective Routing Policy Rules environment you should be able to configure the Selective routing for a single device via the VPN (using the Policy Rules GUI) whilst everything else (by default) remains routed via the WAN;
Code:
UseVPN 192.168.77.2 0.0.0.0 VPN

and rather than use a (flawed obsolete) script, simply issue just two commands?
Code:
ip rule add from 0/0 fwmark 0x7000 table main prio 9990
iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 8080 -j MARK --set-mark 0x7000/0x7000

NOTE: The subtle difference in the '--set-mark' directive.
 
Last edited:
One potential alternative that might be worth investigating, based on Asus's own VPN Fusion: using iptables for port-based routing.

Code:
if(policy->dst_ip[0] != '\0')   //has destination ip
     eval("iptables", "-D", "PREROUTING", "-t", "mangle", "-i", lan_ifname, "-m", "mac", "--mac-source",
         policy->mac, "-d", policy->dst_ip,"-j", "ROUTE", "--oif", (char*)vpnc_ifname);
else
    eval("iptables", "-D", "PREROUTING", "-t", "mangle", "-i", lan_ifname, "-m", "mac", "--mac-source",
         policy->mac, "-j", "ROUTE", "--oif", (char*)vpnc_ifname);

Not sure how well it works, or if it's compatible with older 2.6 kernels, but it would have the merit of being fairly simple.
 

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top