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!

Ah thanks for that Martineau

Alas the script by DJR747 appears to be very specific for OpenVPN, and adapting it for use with the PPTP client is beyond my scope!

Tried, just for the heck of it, and got some interesting errors:

someone@RT-N66U:/jffs# ip route flush table 10
Nothing to flush.

someone@RT-N66U:/jffs# ip route del default table 10
RTNETLINK answers: No such process

someone@RT-N66U:/jffs# ip route del default table 12
RTNETLINK answers: No such process

Ran it anyway and the result was everything went via the VPN and the one device I wanted routed via VPN had no access at all :)

Oh well.

Regards

That sounds as if you are missing the mandatory first line

Code:
#!/bin/sh
 
No. Honest!

In fact, the example I gave was done via command line.

Anyway, after an afternoon messing about with it, I think I will have to revert to the original script and see what I can d with split tunneling.

Regards

PS. Even running it as a shell this comes up:

someone@RT-N66U:/jffs# ip route del default table 10
RTNETLINK answers: No such process
 
Guys this is an extremely useful thread. Thanks to the script I was able to get this working. I am no longer dependent on my VPN provider for selective routing (I was using the applet for Asus-Merlin routers from Astrill VPN).

Is there is a more elegant way to switch a specific device (my desktop) from using VPN to not using VPN?

At present I'm using a windows powershell script on the desktop itself to change my desktop NIC configuration to a static IP in the VPN routed range on my network and then back to DHCP in the non-VPN-routed range when I'm done (as I'm mainly using VPN to unblock geo-blocked streaming). I did see something in DJRs script about 'marking' an IP on the router for VPN routing -was wondering if this would be the best way to switch between routing rather than changing IP address. I'm a complete noob at shellscripts so would be very grateful for any guidance!
 
Guys this is an extremely useful thread. Thanks to the script I was able to get this working. I am no longer dependent on my VPN provider for selective routing (I was using the applet for Asus-Merlin routers from Astrill VPN).

Is there is a more elegant way to switch a specific device (my desktop) from using VPN to not using VPN?

At present I'm using a windows powershell script on the desktop itself to change my desktop NIC configuration to a static IP in the VPN routed range on my network and then back to DHCP in the non-VPN-routed range when I'm done (as I'm mainly using VPN to unblock geo-blocked streaming). I did see something in DJRs script about 'marking' an IP on the router for VPN routing -was wondering if this would be the best way to switch between routing rather than changing IP address. I'm a complete noob at shellscripts so would be very grateful for any guidance!

The command

Code:
iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark $ON_OFF

performs the actual VPN switch based on the variables $IP_RANGE and $ON_OFF ($ON_OFF=1 routes the target via the VPN)


I wrote the following script - which despite my inelegant code you should be able to follow.

This allows me to issue commands such as

Code:
/jffs/scripts/VPN_Select_ON_OFF.sh PS3-Bedroom ON FORCE
/jffs/scripts/VPN_Select_ON_OFF.sh ALL ON
/jffs/scripts/VPN_Select_ON_OFF.sh ANDROID ON

to easily select which device or logical group of my devices use the VPN


Code:
#!/bin/sh

# Usage:  VPN_select_ON_OFF [host.dnsmasq | ip_address | KEY_tag] [ON | OFF] {FORCE}
#
#
#                           where  Host.dnsmasq will be matched against /etc/hosts.dnsmasq contents
#                                  
#                                  Key_tag      will be matched against /mnt/$MYROUTER/VPN_MASKS.txt     
#                               
#                                  FORCE will ensure designated target will ONLY use the VPN. 

## CUSTOMIZE YOUR SCRIPT VARIABLES
#
## Uncomment and assign/change value(s) as needed to customize your rules
#
# ip_range1="192.168.10.200-192.168.10.203"
# ip_range2="192.168.10.8/29"
# ip_range3=""
#
# If your IP addresses don't fall in a contiguous range, you'll need separate rules instead.

MYROUTER=$(nvram get computer_name)
USEPATH="/tmp/mnt/$MYROUTER"

logger -t "($(basename $0))" $$ VPN Selective routing for [$@]

# Perform a lookup if a hostname (or I/P address) is supplied
# NOTE: etc/host.dnsmasq is in format
#
#       I/P address    hostname
#
if [ "$1" != "" ];then
   IP_NAME=$1
   IP_RANGE=`grep -i "$1" /etc/hosts.dnsmasq  | awk '{print $1}'`
   logger -t "($(basename $0))" $$ "Lookup '$1' in DNSMASQ returned:>$IP_RANGE<"

   # If entry not matched in /etc/hosts.dnsmasq see if it exists in our VPN_MASKS.txt lookup file
   #
   #       KEY     I/P address
   #
   if [ "$IP_RANGE" = "" ];then

      IP_RANGE=`grep -i "^$1" $USEPATH/VPN_MASKS.txt | awk '{print $2}'`
      logger -t "($(basename $0))" $$ "Lookup '$1' in $USEPATH/VPN_MASKS.txt returned:>$IP_RANGE<"
   fi

else
   IP_NAME="U200-115"
   IP_RANGE=`grep -i $IP_NAME /etc/hosts.dnsmasq  | awk '{print $1}'`
   logger -t "($(basename $0))" $$ "DEFAULT '$IP_NAME' lookup returned:>$IP_RANGE<"
fi



# Validate the I/P address
REGEX="\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"

CHECK=$(echo $IP_RANGE | egrep $REGEX)
if [[ "$?" -eq 0 ]];then
   echo "Valid IP address " $IP_RANGE
else
   logger -t "($(basename $0))" $$ **ERROR Invalid IP address $IP_RANGE
   echo "Invalid IP address " $IP_RANGE
   exit 1
fi

if [ "$IP_RANGE" = "" ];then
   logger -t "($(basename $0))" $$ "**ERROR Missing arg: DNSMASQ hostname or IP address"
   echo "Missing arg: Hostname or IP address"
   exit 1
fi

ACTION=$2

# Flip the VPN selective routing if the tracking file exists and no explicit directive supplied
if [ -e $USEPATH/VPN_$IP_RANGE.txt ] && [ "$2" = "" ] ;then

   # Retrieve the previous known status (Reboot should definitely delete these files?  - see post-mount or ip_down event?)
   ON_OFF=`cat $USEPATH/VPN_$IP_RANGE.txt` 

   if [ "$ON_OFF" = "1" ];then
      ACTION="OFF"
      logger -t "($(basename $0))" $$ "Current '$IP_NAME' tracking file is MARK=$ON_OFF (ON)"
   else     
      ACTION="ON"
      logger -t "($(basename $0))" $$ "Current '$IP_NAME' tracking file is MARK=$ON_OFF (OFF)"
   fi


fi


# Turn selective routing ON or OFF
if [ "$ACTION" = "OFF" ];then
   ON_OFF=0
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE set MARK=$ON_OFF "(OFF)"
else
   ON_OFF=1
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE set MARK=$ON_OFF "(ON)"
fi
   
# Enable the selective rerouting
iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark $ON_OFF

# Optionally FORCE the use of the VPN tunnel, so if the VPN tunnel drops, the device will not use the unencrypted default WAN
if [ "$3" = "FORCE" ];then
   iptables -I FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
fi

# Track known status of VPN selective routing.....
echo $ON_OFF > $USEPATH/VPN_$IP_RANGE.txt

exit

Regards,
 
!!! I have cracked it !!!

For those interested, I have managed to get selective routing with the pptp client fully working!

Further, the solution allows all services on the router to be used as normal - eg AiCloud, Transmission - and you can access them remotely.

I will be putting up a separate post in a day or so. With, I hope, pptp client start on wan.

Regards
 
Hi Everyone,

Hoping to get some help with this.

I am not looking to use OpenVPN. I simply want everything but my ROKU to go through default DNS. I want the Roku to go though Unblock-US.

How can I setup the script to do this? (My ROKU has a reserved DHCP address, so its always the same)

Thanks,
 
Hi dpjanda, I'm keen to give pptp selective routing a go. Do you have any updates?

Regards

Edit: I assume if i use DJR747's script I would change tun_if="tun11" to tun_if="pptp5" or whichever pptp interface I was using according to the system log?
 
Last edited:
See my post on PPTP selective routing / Split Tunnel.

The script posted on this thread will not work with PPTP. It's for OpenVPN.

Regards
 
This is all I do. I reject the route push from the server by adding route-nopull to the custom config section.

Then I run a custom script by adding these lines to the custom config as well.

script-security 2
route-up /jffs/scripts/vpn_route_up.sh

Here is the script. I didn't want to mess with any of the default routes and tables so I just added two new tables to direct traffic.

Code:
#
ip route flush table 10
ip route del default table 10
ip rule del fwmark 10 table 10
ip route flush table 12
ip route del default table 12
ip rule del fwmark 12 table 12
ip route flush cache
iptables -t mangle -F PREROUTING

tun_if="tun11"
tun_ip=$(ifconfig $tun_if | grep 'inet addr:'| cut -d: -f2 | awk '{ print $1}')

ip route add default via $tun_ip dev $tun_if table 10
ip rule add fwmark 10 table 10
ip route add default via $(nvram get wan_gateway) dev eth0 table 12
ip rule add fwmark 12 table 12

echo 0 > /proc/sys/net/ipv4/conf/$tun_if/rp_filter

iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.7.40-192.168.7.49 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -i br0 -p tcp --dport 563 -j MARK --set-mark 12

exit

I imagine there is some way to pass out the tunnel interface name as well just haven't gotten that far yet. So for now it is just hard coded.

I hope someone can help me. I am trying to run this script on my Asus RT-AC66U using merlins firmware 3.0.0.4.374.39_0

When I try to run the script manually, I get the following output:

RTNETLINK answers: No such process
RTNETLINK answers: No such process

Yes, I have included "#!/bin/sh" at the beginning of the script. By adding some echos in the script, I found the following lines to be the cause of the messages:

ip route del default table 10
and
ip route del default table 12

Could it be possible that the latest firmware includes changes which conflict with these commands?
 
I hope someone can help me. I am trying to run this script on my Asus RT-AC66U using merlins firmware 3.0.0.4.374.39_0

When I try to run the script manually, I get the following output:

RTNETLINK answers: No such process
RTNETLINK answers: No such process

Yes, I have included "#!/bin/sh" at the beginning of the script. By adding some echos in the script, I found the following lines to be the cause of the messages:

ip route del default table 10
and
ip route del default table 12

Could it be possible that the latest firmware includes changes which conflict with these commands?

The script ensures that if a new I/P is assigned from the VPN, then the routes in the custom tables will be set to the correct values.

Are the tables correctly created when the script runs?

Does the selective routing work?

Hopefully the answer to both questions is YES.

Regards,
 
Oh, yes, I forgot to say: The selective routing does not work, every client goes through VPN.

This is my VPN client custom configuration:

script-security 2
route-up /jffs/scripts/vpn_route_up.sh

How can I check whether or not the tables are correctly created?
 
Oh, yes, I forgot to say: The selective routing does not work, every client goes through VPN.

This is my VPN client custom configuration:

script-security 2
route-up /jffs/scripts/vpn_route_up.sh

How can I check whether or not the tables are correctly created?

To see if the custom tables have been created issue:

Code:
ip rule ls
ip route show table 100

If you issue the following, you should get a list of targets that are to be explicitly routed via the VPN

e.g. I have one of my PS3s routed via the VPN MARK=1

Code:
iptables -t mangle -L -nv --line


Chain PREROUTING (policy ACCEPT 107K packets, 10M bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 MARK       tcp  --  br0    *       0.0.0.0/0            0.0.0.0/0            tcp dpt:563 MARK set 0x2
2        0     0 MARK       all  --  br0    *       0.0.0.0/0            0.0.0.0/0            source IP range 10.88.8.142-10.88.8.142 MARK set 0x1

assuming that by default all other devices do not have an entry (or implied MARK=0)

Regards,
 
Last edited:
This is the output of the commands:

Code:
ASUSWRT-Merlin RT-AC66U_3.0.0.4 Fri Jan 31 05:20:23 UTC 2014
admin@RT-AC66U:/tmp/home/root# ip rule ls
0:      from all lookup local
32764:  from all fwmark 0xc lookup 12
32765:  from all fwmark 0xa lookup 10
32766:  from all lookup main
32767:  from all lookup default
admin@RT-AC66U:/tmp/home/root# ip route show table 100
admin@RT-AC66U:/tmp/home/root# iptables -t mangle -L -nv --line
Chain PREROUTING (policy ACCEPT 129M packets, 130G bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      29M 2642M MARK       all  --  br0    *       0.0.0.0/0            0.0.0.0/0           source IP range 192.168.2.101-192.168.2.101 MARK set 0xa
2        0     0 MARK       tcp  --  br0    *       0.0.0.0/0            0.0.0.0/0           tcp dpt:563 MARK set 0xc

Chain INPUT (policy ACCEPT 50M packets, 65G bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 79M packets, 64G bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 30M packets, 4739M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 109M packets, 69G bytes)
num   pkts bytes target     prot opt in     out     source               destination

"ip route show table 100" doesn't result in any output.
 
This is the output of the commands:

Code:
ASUSWRT-Merlin RT-AC66U_3.0.0.4 Fri Jan 31 05:20:23 UTC 2014
admin@RT-AC66U:/tmp/home/root# ip rule ls
0:      from all lookup local
32764:  from all fwmark 0xc lookup 12
32765:  from all fwmark 0xa lookup 10
32766:  from all lookup main
32767:  from all lookup default
admin@RT-AC66U:/tmp/home/root# ip route show table 100
admin@RT-AC66U:/tmp/home/root# iptables -t mangle -L -nv --line
Chain PREROUTING (policy ACCEPT 129M packets, 130G bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      29M 2642M MARK       all  --  br0    *       0.0.0.0/0            0.0.0.0/0           source IP range 192.168.2.101-192.168.2.101 MARK set 0xa
2        0     0 MARK       tcp  --  br0    *       0.0.0.0/0            0.0.0.0/0           tcp dpt:563 MARK set 0xc

Chain INPUT (policy ACCEPT 50M packets, 65G bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 79M packets, 64G bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 30M packets, 4739M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 109M packets, 69G bytes)
num   pkts bytes target     prot opt in     out     source               destination

"ip route show table 100" doesn't result in any output.

Apologies, I use custom table 100 etc., clearly you should enquire on tables 10/12.

Regards,
 
admin@RT-AC66U:/tmp/home/root# ip route show table 10
admin@RT-AC66U:/tmp/home/root# ip route show table 12
default via 188.194.yyy.xxx dev eth0

(yyy.xxx replaced)
 
admin@RT-AC66U:/tmp/home/root# ip route show table 10
admin@RT-AC66U:/tmp/home/root# ip route show table 12
default via 188.194.yyy.xxx dev eth0

(yyy.xxx replaced)

If only table 12 is correctly populated, then U need to check why table 10 is not being populated.

Code:
tun_if="tun11"
tun_ip=$(ifconfig $tun_if | grep 'inet addr:'| cut -d: -f2 | awk '{ print $1}')

ip route add default via $tun_ip dev $tun_if table 10

So you should debug the above statements to see if the variables

Code:
   $tun_ip
   $tun_if

are being resolved correctly.

NOTE: On the OpenVPN Client tab do U have 'Redirect Internet Traffic=YES' ?

Regards,
 
This is all I do. I reject the route push from the server by adding route-nopull to the custom config section.

Then I run a custom script by adding these lines to the custom config as well.

script-security 2
route-up /jffs/scripts/vpn_route_up.sh

Here is the script. I didn't want to mess with any of the default routes and tables so I just added two new tables to direct traffic.

Code:
#
ip route flush table 10
ip route del default table 10
ip rule del fwmark 10 table 10
ip route flush table 12
ip route del default table 12
ip rule del fwmark 12 table 12
ip route flush cache
iptables -t mangle -F PREROUTING

tun_if="tun11"
tun_ip=$(ifconfig $tun_if | grep 'inet addr:'| cut -d: -f2 | awk '{ print $1}')

ip route add default via $tun_ip dev $tun_if table 10
ip rule add fwmark 10 table 10
ip route add default via $(nvram get wan_gateway) dev eth0 table 12
ip rule add fwmark 12 table 12

echo 0 > /proc/sys/net/ipv4/conf/$tun_if/rp_filter

iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.7.40-192.168.7.49 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -i br0 -p tcp --dport 563 -j MARK --set-mark 12

exit

I imagine there is some way to pass out the tunnel interface name as well just haven't gotten that far yet. So for now it is just hard coded.

I decided to give VyprVPN a try with the intention of sending any of my P2P traffic over it and everything else bypassing the VPN, but doing this hopefully globally. Thanks to all the information here on setting up OpenVPN and the above solution to setting routes I have it half working.

What's working - all traffic is bypassing the VPN.
What's not working - traffic sending over a specific port (59934) for P2P is NOT going over the VPN.

I know zip about using iptables and all the attempts I've made at putting something in have failed. I tried these 2 commands to get that port going over the VPN:

iptables -t mangle -A PREROUTING -i br0 -p tcp --dport 59934 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -i br0 -p udp --dport 59934 -j MARK --set-mark 10

Here is some output from the tables:

admin@RT-N66U:/tmp/home/root# iptables -t mangle -L -nv --line
Chain PREROUTING (policy ACCEPT 141K packets, 95M bytes)
num pkts bytes target prot opt in out source destination
1 8 496 MARK tcp -- br0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:59934 MARK set 0xa
2 3 174 MARK udp -- br0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:59934 MARK set 0xa
3 27473 1620K MARK all -- br0 * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.1.2-192.168.1.254 MARK set 0xc

Chain INPUT (policy ACCEPT 45262 packets, 3159K bytes)
num pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 95349 packets, 92M bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 42982 packets, 15M bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 138K packets, 107M bytes)
num pkts bytes target prot opt in out source destination
admin@RT-N66U:/tmp/home/root# ip route show table 10
default via 10.10.1.116 dev tun11
admin@RT-N66U:/tmp/home/root# ip route show table 12
default via 72.185.64.1 dev eth0
admin@RT-N66U:/tmp/home/root#

What am I doing wrong? I'm not currently adding anything via the script except for setting up the default route(s). I wanted to make sure that was working before manually putting in commands to get the above to work.

So to reiterate, what I want to do is send ALL traffic, minus P2P on port 59934, out the wan normally. Then I want to send traffic on port 59934 over the VPN. I'm sure I can get this to work if I just sent all traffic from a source IP over the VPN, but that would kill some other things I do so I want this to be port specific if possible.

Help?!

And just so you can see what it's in the script right now:

---
#!/bin/sh
#
ip route flush table 10
ip route del default table 10
ip rule del fwmark 10 table 10
ip route flush table 12
ip route del default table 12
ip rule del fwmark 12 table 12
ip route flush cache
iptables -t mangle -F PREROUTING

tun_if="tun11"
tun_ip=$(ifconfig $tun_if | grep 'inet addr:'| cut -d: -f2 | awk '{ print $1}')

ip route add default via $tun_ip dev $tun_if table 10
ip rule add fwmark 10 table 10
ip route add default via $(nvram get wan0_gateway) dev eth0 table 12
ip rule add fwmark 12 table 12

echo 0 > /proc/sys/net/ipv4/conf/$tun_if/rp_filter

#iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.7.40-192.168.7.49 -j MARK --set-mark 10
#iptables -t mangle -A PREROUTING -i br0 -p tcp --dport 563 -j MARK --set-mark 12

iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.1.2-192.168.1.254 -j MARK --set-mark 12

exit
---
 
Ok…. I "think" I have this working now, but I'm not sure if I need to add anything else. I ran these via command line and then tested. I did this after dumping all other routes and whatnot.

iptables -t mangle -I PREROUTING -p tcp --sport 59934 -j MARK --set-mark 10
iptables -t mangle -I PREROUTING -p udp --sport 59934 -j MARK --set-mark 10

I didn't even have this line in there so I'm not sure if it's needed or not:

iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.1.2-192.168.1.254 -j MARK --set-mark 12

The only way I can tell it's working is because A) my speeds tanked (I expected this) and on the OpenVPN Client 1 stats I was actually seeing some traffic running through it. Also if I looked at the table I could see traffic running over those 2 rules.

So as I said, I "think" this works now. Any other input would be great and also if there's a way to prevent traffic on that port if for some reason the VPN is down would be great. What's that called… IP leak?
 

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

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