howto only tunnel specific hosts route through openvpn client on tomato

54,567

Solution 1

Whether this firmware support iproute2, which may support more than one route table, based on src ip.

echo "200 ovpn" >> /etc/iproute2/rt_tables
ip rule add from YOUR.WIFI.IP.S table ovpn

and add route rule for the table

ip route add default via VPN.ROUTE.IP.ADDR dev vpn_dev table ovpn
ip route flush cache

you can ref this: Linux Advanced Routing & Traffic Control HOWTO : http://lartc.org/howto/index.html

Or, as you are Chinese, you can read my blog on this topic: http://wangxu.me/blog/p/675

Hope this could help

Solution 2

I finally did it :-)

I'm using v1.28.9054 MIPSR2-beta K26 USB vpn3.6, but should work on others, as it's networking.

OpenVPN wants to setup all your routing, you've got to stop that...

In VPN Tunneling/Client/Basic

Uncheck "Create NAT on Tunnel" In VPN Tunneling/Client/Advanced

Uncheck "Redirect Internet Traffic"

Custom Configuration, add the line: route-nopull

In Administration/Scripts/Firewall, make sure you have:

iptables -I FORWARD -i br0 -o tun11 -j ACCEPT
iptables -I FORWARD -i tun11 -o br0 -j ACCEPT
iptables -I INPUT -i tun11 -j REJECT
iptables -t nat -A POSTROUTING -o tun11 -j MASQUERADE

Reboot, and viola, you got nothing...

Then, in a VPN up script (Best choice), or if you have your VPN start with WAN, put in your Administration/Scripts/WANUP

sleep 30
ip route flush table 200
ip route flush cache
ip rule add from 192.168.1.11 lookup 200
ip rule add from 192.168.1.13 lookup 200
VPN_GW=`ifconfig tun11 | awk '/inet addr/ {split ($2,A,":"); print A[2]}'`
ip route add table 200 default via $VPN_GW dev tun11

This probaly isn't the "best" or "proper" way to do it, but it works. Now only 192.168.1.11 and 192.168.2.13 will go through the OpenVPN tunnel. All other devices, and their traffic will go local.

This was extremely important for me, as i didnt want my Transmission torrent traffic going over the VPN. Some guy like SgtPepperKSU is looking at this and probably laughing... Anyway, from one Routing noob to another...

Solution 3

I did things a little differently but still accomplished the same thing pretty much. Thought I'd share it here.

I set up my Tomato router as an OpenVPN Client so that it routes ALL internet traffic through the VPN. I used StrongVPN.com's service for this purpose and they provided step-by-step instructions, so it was pretty easy to get that part going. Google "Tomato OpenVPN Setup Tutorial StrongVPN" and you'll find it

But the "selective routing only certain hosts" thing was very tricky.

I ended up implementing it as a "WAN UP" script (In the Tomato GUI: Administration->Scripts->WAN UP). The c ode below is what I put into that box. It has lots of comments to explain what's going on. It is based heavily on the code I found here:

http://linksysinfo.org/index.php?threads/route-only-specific-ports-through-vpn-openvpn.37240/

And reading this article was extremely helpful:

http://linux-ip.net/html/adv-multi-internet.html

Here's the code:

# This code goes in the WAN UP section of the Tomato GUI.
#
# This script configures "selective" VPN routing. Normally Tomato will route ALL traffic out
# the OpenVPN tunnel. These changes to iptables allow some outbound traffic to use the VPN, and some
# traffic to bypass the VPN and use the regular Internet instead.
#
#  To list the current rules on the router, issue the command:
#      iptables -t mangle -L PREROUTING
#
#  Flush/reset all the rules to default by issuing the command:
#      iptables -t mangle -F PREROUTING
#

#
# First it is necessary to disable Reverse Path Filtering on all
# current and future network interfaces:
#
for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
      echo 0 > $i
done

#
# Delete and table 100 and flush any existing rules if they exist.
#
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

#
# Copy all non-default and non-VPN related routes from the main table into table 100.
# Then configure table 100 to route all traffic out the WAN gateway and assign it mark "1"
#
# NOTE: Here I assume the OpenVPN tunnel is named "tun11".
#
#
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

#
# Define the routing policies for the traffic. The rules will be applied in the order that they
# are listed. In the end, packets with MARK set to "0" will pass through the VPN. If MARK is set
# to "1" it will bypass the VPN.
#
# EXAMPLES:
#
#  All LAN traffic will bypass the VPN (Useful to put this rule first, so all traffic bypasses the VPN and you can configure exceptions afterwards)
#    iptables -t mangle -A PREROUTING -i br0 -j MARK --set-mark 1
#  Ports 80 and 443 will bypass the VPN
#    iptables -t mangle -A PREROUTING -i br0 -p tcp -m multiport --dport 80,443 -j MARK --set-mark 1
#  All traffic from a particular computer on the LAN will use the VPN
#    iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range 192.168.1.2 -j MARK --set-mark 0
#  All traffic to a specific Internet IP address will use the VPN
#    iptables -t mangle -A PREROUTING -i br0 -m iprange --dst-range 216.146.38.70 -j MARK --set-mark 0
#  All UDP and ICMP traffic will bypass the VPN
#    iptables -t mangle -A PREROUTING -i br0 -p udp -j MARK --set-mark 1
#    iptables -t mangle -A PREROUTING -i br0 -p icmp -j MARK --set-mark 1

# By default all traffic bypasses the VPN
iptables -t mangle -A PREROUTING -i br0 -j MARK --set-mark 1

# Spotify explicitly uses the VPN
iptables -t mangle -A PREROUTING -i br0 -m iprange --dst-range 78.31.8.1-78.31.15.254 -j MARK --set-mark 0
iptables -t mangle -A PREROUTING -i br0 -m iprange --dst-range 193.182.8.1-193.182.15.254 -j MARK --set-mark 0
Share:
54,567

Related videos on Youtube

kcome
Author by

kcome

Updated on September 18, 2022

Comments

  • kcome
    kcome almost 2 years

    I am relatively newbie in networking world although I did coding and know some sysadmin background for a long time. and here I'm only one step from my destination.

    The whole picture is : at home I use one LinkSys E3000 as the gateway(don't know yet if this is it's name), wireless AP and no other routing/switching devices. It serves 1 PC and 1 Mac with LAN, 1 Mac Mini + 1 iPad + 2 smartphones with WIFI.

    My goal is use an openvpn client on the E3000 (with tomato firmware) and make my iPad and smartphone's all WiFi traffic through it, and other devices route remain the same non-openvpn route.

    So far I'm able to connect openvpn client on E3000 to an openvpn server, tunnel all my devices' all traffic through that openvpn connection. What's left is howto selectively route by source IP (at least in my guessing) to the tunnel while don't bother others.

    I had learned some 'iptables' and 'route' in past few days however without much luck, so here comes my question. Here are some info which will help you get the structure.

    ifconfig -a output, some useless lines striped, and in the web interface C0:C1:C0:1A:E0:28 is WAN, C0:C1:C0:1A:E0:27 is LAN, C0:C1:C0:1A:E0:29 is 2.4G wifi AP, C0:C1:C0:1A:E0:2A is 5G wifi AP.

    root@router:/tmp/home/root# ifconfig -a

    br0 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:27
    inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

    eth0 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:27
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

    eth1 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:29
    UP BROADCAST RUNNING ALLMULTI MULTICAST MTU:1500 Metric:1

    eth2 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:2A
    UP BROADCAST RUNNING ALLMULTI MULTICAST MTU:1500 Metric:1

    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host

    ppp0 Link encap:Point-to-Point Protocol
    inet addr:172.200.1.43 P-t-P:172.200.0.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING MULTICAST MTU:1480 Metric:1

    vlan1 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:27
    UP BROADCAST RUNNING ALLMULTI MULTICAST MTU:1500 Metric:1

    vlan2 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:28
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

    wl0.1 Link encap:Ethernet HWaddr C0:C1:C0:1A:E0:29
    BROADCAST MULTICAST MTU:1500 Metric:1

    brctl show output

    root@router:/tmp/home/root# brctl show
    bridge name bridge id       STP enabled interfaces
    br0     8000.c0c1c01ae027   no      vlan1
                                eth1
                                eth2
    

    before openvpn route-up script

    root@router:/tmp/home/root# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    172.200.0.1     0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
    192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br0
    127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
    0.0.0.0         172.200.0.1     0.0.0.0         UG    0      0        0 ppp0
    

    openvpn server push

    PUSH: Received control message: 'PUSH_REPLY,redirect-gateway,dhcp-option DNS 8.8.8.8,route 172.20.0.1,topology net30,ping 10,ping-restart 120,ifconfig 172.20.0.6 172.20.0.5'
    

    openvpn's stock route-up script

    Apr 24 14:52:06 router daemon.notice openvpn[1768]: /sbin/ifconfig tun11 172.20.0.6 pointopoint 172.20.0.5 mtu 1500
    Apr 24 14:52:08 router daemon.notice openvpn[1768]: /sbin/route add -net 72.14.177.29 netmask 255.255.255.255 gw 172.200.0.1
    Apr 24 14:52:08 router daemon.notice openvpn[1768]: /sbin/route add -net 0.0.0.0 netmask 128.0.0.0 gw 172.20.0.5
    Apr 24 14:52:08 router daemon.notice openvpn[1768]: /sbin/route add -net 128.0.0.0 netmask 128.0.0.0 gw 172.20.0.5
    Apr 24 14:52:08 router daemon.notice openvpn[1768]: /sbin/route add -net 172.20.0.1 netmask 255.255.255.255 gw 172.20.0.5
    

    route after openvpn

    root@router:/tmp/home/root# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    172.20.0.5      0.0.0.0         255.255.255.255 UH    0      0        0 tun11
    72.14.177.29    172.200.0.1     255.255.255.255 UGH   0      0        0 ppp0
    172.200.0.1     0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
    172.20.0.1      172.20.0.5      255.255.255.255 UGH   0      0        0 tun11
    192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br0
    127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
    0.0.0.0         172.20.0.5      128.0.0.0       UG    0      0        0 tun11
    128.0.0.0       172.20.0.5      128.0.0.0       UG    0      0        0 tun11
    0.0.0.0         172.200.0.1     0.0.0.0         UG    0      0        0 ppp0
    

    something I had noticed and tried: * on the web interface of openvpn client there is an option "Create NAT on tunnel", if i check this, there is the following script (probably executed after openvpn connection established)

    root@router:/tmp/home/root# cat /tmp/etc/openvpn/fw/client1-fw.sh
    #!/bin/sh
    iptables -I INPUT -i tun11 -j ACCEPT
    iptables -I FORWARD -i tun11 -j ACCEPT
    iptables -t nat -I POSTROUTING -s 192.168.1.0/255.255.255.0 -o tun11 -j MASQUERADE
    

    if i uncheck this option, the last line will not appear. Then I guess probably the my issue will be solved by iptables and NAT related commands, I just haven't got enough knowledge to figure them out. I tried run

    iptables -t nat -I POSTROUTING -s 192.168.1.6 -o tun11 -j MASQUERADE
    

    manually after openvpn connected (192.168.1.6 is the ip address of my iPad), then my iPad get internet with openvpn tunnel, however all other devices can't reach internet.

    in case if needed, here is the iptables about NAT

    root@router:/tmp/home/root# iptables -t nat -L -n
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination         
    DROP       all  --  0.0.0.0/0            192.168.1.0/24      
    WANPREROUTING  all  --  0.0.0.0/0            172.200.1.43        
    upnp       all  --  0.0.0.0/0            172.200.1.43        
    
    Chain POSTROUTING (policy ACCEPT)
    target     prot opt source               destination         
    MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0           
    SNAT       all  --  192.168.1.0/24       192.168.1.0/24      to:192.168.1.1 
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain WANPREROUTING (1 references)
    target     prot opt source               destination         
    DNAT       icmp --  0.0.0.0/0            0.0.0.0/0           to:192.168.1.1 
    
    Chain upnp (1 references)
    target     prot opt source               destination         
    DNAT       udp  --  0.0.0.0/0            0.0.0.0/0       udp dpt:5353 to:192.168.1.3:5353 
    

    Thanks in advance for helping and read this so much, I hope i made every info you need to give a help :)

  • kcome
    kcome about 12 years
    very insightful answer :) however finally I set a second table for non-vpn routes. great, thanks :)
  • Quint
    Quint about 12 years
    Sorry, just one more thing, you may want to make that "sleep 30" a little longer, until your tun11 interface is actually built by OpenVPN. Or if you manage to put it in an OpenVPN up script, that would be the best.
  • vgoff
    vgoff over 11 years
    Nice detailed answer, hope to see more of you around!
  • Alan Cor
    Alan Cor about 10 years
    Nice. Now you set VPN as default, but exclude everything except for Spotify. Would it be possible define it the other way around to say: normal WAN is default and use VPN only for Spotify. I don't want to risk that one wrong rule causes all my traffic to go over the VPN.
  • droidgren
    droidgren over 9 years
    @Zyphrax, No, the example is the other way around. The example is what you'd like: VPN for spotify, the rest goes bypasses.