Working VPN kill switch for selective Routing Policy (v131)

Discussion in 'Tomato Firmware' started by GetVladimir, Oct 16, 2015.

  1. GetVladimir

    GetVladimir Reformed Router Member

    Step-by-step guide on how to implement VPN Kill Switch for selective routing policies

    The new VPN Routing Policy in Tomato by Shibby v131 is amazing! It makes the setting up of very useful advanced routing to be a breeze.

    To compliment the new feature, I was looking for an effective selective VPN Kill Switch that will prevent leaks if the VPN looses connection, but will not affect the devices that are not routed through the VPN.

    There were quite a few great posts (both old and recent) on the subject, but none of them seemed to had a complete guide on how to accomplish exactly this on v131.

    I wanted to share what I found that is working for me. Any help to improve it will be more than welcome.

    Let's begin:

    Step 1: First, in "VPN Tunneling" > "OpenVPN Client" > "Routing Policy" setup the VPN and the routing policy as you normally do. I've included a sample picture as of how it may look:
    routing policy some.png

    Step 2: As the VPN Routing Policy table (table 111) gets flushed from time to time, make sure that in "Administration" > "Scheduler" you include this code:

    VPN_GW=`ifconfig tun11 | awk '/inet addr/ {split ($2,A,":"); print A[2]}'`
    ip route add table 111 default via $VPN_GW dev tun11
    And set it to run every 3 minutes. This will read the most current VPN gateway and repopulate table 111 with it if the table is flushed.

    It should look like something like this:

    Step 3: Now for the VPN Kill Switch. To make sure there is no VPN leak between the table being flushed and repopulated, or if the VPN looses connection, we're going to add this code in "Administration" > "Scripts" > "Firewall":

    For every "From Source IP" in that you have in "Routing Policy" add this (replacing only the source ip address):
    iptables -I FORWARD -i br0 -s -o `nvram get wan_iface` -j DROP
    For every "To Domain" in that you have "Routing Policy" add this (replacing only the domain name):
    iptables -I FORWARD ! -o tun11 -d -j DROP
    iptables -I FORWARD -o `nvram get wan_iface` -d -j DROP

    So it all looks similar to this example:
    firewall iptables some.png

    Save it and that's it! You will now have an effective selective VPN Kill Switch that will prevent leaks if the VPN looses connection, but will not affect the devices that are not routed through the VPN.

    Thanks goes to @eibgrad and @Rockstead that pointed me in the right direction with their post HERE and the people from this older post HERE
    Last edited: Oct 16, 2015
    devmau5, M_ars, Cl00ny and 4 others like this.
  2. Thomas Begley

    Thomas Begley Serious Server Member

    Hi there, thank you for the info!

    However, when I add the info for the source IP to my firewall and stop the vpn I have no connectivity on my devices. If i delete the
    iptables -I FORWARD -i br0 -s -o `nvram get wan_iface` -j DROP
    from the firewall and restart the firewall connectivity comes back.
  3. Ragtag

    Ragtag Reformed Router Member

    GetVladimir likes this.
  4. GetVladimir

    GetVladimir Reformed Router Member

    Yes, exactly! The point of the VPN kill switch is NOT to have connectivity on the routed IP if the VPN is down.

    Just make sure you add only the IP addresses of the devices that you route through the VPN, not the devices that you would like to function directly through the WAN.
  5. GetVladimir

    GetVladimir Reformed Router Member

    Thank you @Ragtag ! I'm glad if it's useful
  6. BrianTren

    BrianTren New Member Member

    This is great. Thanks for the tutorial. Quick follow-up question -

    I have Transmission running on Tomato and PIA configured as my OpenVPN connection. Is there a way to create a kill switch for Transmission so that it only uses the VPN?
  7. Thomas Begley

    Thomas Begley Serious Server Member

    Ive had a nightmare with transmission and VPN the only way I could get it working right was to redirect all traffic in the vpn.

    The best way I have currently found around it is to require encryption and add the trackers hardcoded IPs to the To Destination IP in the routing policy.

    This way the torrent communication with the tracker uses the vpn and the actually p2p connections are encrypted over the WAN. Im hoping that my ISP cannot see what im doing using this method as redirecting all traffic is a no go for me as my ISP download is 200 Mbps and max over VPN is 25 Mbps.
  8. GetVladimir

    GetVladimir Reformed Router Member

    Thank you for your comment, @BrianTren ! I'm glad if the tutorial is useful.

    I have no experience with that at all. Thanks @Thomas Begley for answering the question.
  9. spliff

    spliff LI Guru Member

  10. spliff

    spliff LI Guru Member

    One question, I believe it is no longer 111 but 311? This is what is in my /tmp/etc/openvpn/fw/ file when I'm using Shibby's 136

    root@unknown:/tmp/etc/openvpn/fw# cat


    echo 0 > /proc/sys/net/ipv4/conf/tun11/rp_filter

    echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

    iptables -t mangle -A PREROUTING -m set --match-set vpnrouting311 dst,src -j MARK --set-mark 311

    iptables -t mangle -A PREROUTING -s -j MARK --set-mark 311

    iptables -t mangle -A PREROUTING -s -j MARK --set-mark 311
  11. jdjgjc

    jdjgjc New Member Member

    Hello! Can anyone redirect me to the manual(s) for following topic(s)?

    1) the Kill Switch for OpenVPN client
    2) the Automatic Re-Establishing the OpenVPN tunnel by OpenVPN Client
    3) the way to establishing the enough level of the sequrity of the Shibby Tomato OpenVPN Client (for example, when the Shibby offers only a little options to configure the sequrity level of the OpenVPN tunnel, the DD-WRT offers even the DHE Ciphering for TLS (the DHE is the good and the modern level of the Handshaking's sequrity)

    Thank you all in advance!
  12. GetVladimir

    GetVladimir Reformed Router Member

    Thank you @spliff ! I haven't used any of the Multi-WAN versions, so I don't really know what is changed or if the scheduler part is needed.

    Welcome @jdjgjc to the forum and thank you for your question. I'm not aware of any manuals regarding the procedure (if that is what you've meant), but you can find the source links at the bottom of the tutorial in the first post.
  13. jdjgjc

    jdjgjc New Member Member

    Thank you! The first of my questionS was NOT about the selective Kill Switch but about a reliable universal Kill switch (universal = for full router). Now i put the following lines but I do not sure about it: they are copyed from AirVPN site and do not know that Shibby's tun is the 11 and not 0 :( . When I try set tun+ instead of exact number (tun11) then not all lines was good with this :( . I hope that the bolded line is enough to defend me - but I do not know about other lines:
    iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
    iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
    iptables -I FORWARD -i br0 -o eth1 -j DROP
    iptables -I FORWARD -i br0 -o `nvram get wan_iface` -j DROP
    iptables -I INPUT -i tun0 -j REJECT
    iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

    I will thankfull to anybody who will try to redirect me to the places with an ability to help me for rest of my questions!!!
  14. opiateofblame

    opiateofblame New Member Member

    Hi GetVladimir, sorry to resurrect this old topic, but i've started to have the intermittent issues with VPN routed devices 'dropping' connection, after enabling the selective routing on my Netgear R7000.

    I just wondered if you could share your experience of this resolution in practice, in terms of what happens to the VPN connection when the script runs, and repopulates the 111 table, every 3 mins. Does this 'repopulating' of the table causes the VPN connection to drop and reconnect, or does it not interrupt an existing connection at all?

    Many thanks in advance!
  15. GetVladimir

    GetVladimir Reformed Router Member

    I haven't tested with the Netgear R7000, but repopulating the table should not cause any interruptions.

    An easy way to test this would be to remove the script from "Administration" > "Scheduler" only and see if you get disconnects again.

    If it doesn't disconnect anymore, then you might check if your VPN is actually tun11 (as the scheduler script diverts to tun11 assuming that's your default VPN).
    opiateofblame likes this.
  16. ed1chandler

    ed1chandler New Member Member

    This line in step 2 throws a syntax error "EOF in backquote substitution"

    VPN_GW=`ifconfig tun11 | awk '/inet addr/ {split ($2,A,":"); print A[2]}'`
    Any ideas?
  17. eibgrad

    eibgrad Network Guru Member

    Nothing wrong w/ that statement. Ran it here myself, works fine.

    Btw, I don't recommend using backticks. Far too easy to mistake them for single quotes. I've also seen ppl edit a script in a word processor, which then changes it to some stylized quote, then upload the file to the router, only to have bash report errors. Errors that don't appear to be errors until you look more closely and see it's not a normal quote/backtick. For these reasons, I recommend staying away from backticks in favor of $(...) syntax.

    VPN_GW="$(ifconfig tun11 | awk '/inet addr/ {split ($2,A,":"); print A[2]}')"
    Now there's no chance for mistakes.

    It's also a good idea to place the command in quotes just in case it returns something w/ embedded spaces, tabs, etc. In this case that's not likely, but just in general.

    Also, sometimes when it reports errors, it's actually the result of something earlier in the script, such as an opening quote not having a closing quote. So much further down in the script, something else has an opening quote (which closes the prior opening quote), and now the current line (which is fine) gets blamed.
    Last edited: Mar 1, 2018
  18. koitsu

    koitsu Network Guru Member

    Sorry if this comment/question is off-topic or gets away from solving the real issue.

    There's probably an easier -- or cleaner -- way get whatever this information is that's wanted. I can read the shell script just fine, but I've never seen output from ifconfig tunXX interface on TomatoUSB (I don't use VPNs/tunnels) so I can't tell what is being extracted or wanted. I'd need to see that data (maybe with some fake IPs, but please retain the syntax!).

    The variable name VPN_GW implies gateway of the tunnel interface, yes? Can this information not be extracted using an OpenVPN up script that echos the relevant bits into a file in /tmp (possibly source'd directly), or stores them in NVRAM (no nvram commit needed, i.e. no NVRAM wear/tear) and extracted with nvram get?

    TomatoUSB's GUI fields seems to be notorious for having issues with special characters, botching/eating them in different ways. We've seen several reports of it already, and it's kind of "the nature of the beast" when it comes to web interfaces of shell "stuff".
  19. eibgrad

    eibgrad Network Guru Member

    There's a history behind this, and that might help clear things up.

    The reason for the "VPN_GW" portion of the OP's script is because there's a long standing bug in Routing Policy. Whenever there's a soft-restart w/ the OpenVPN client, the router is not aware that the alternate routing table (111) is being flushed. This routing table is supposed to contain the VPN's default gateway, so that clients configured in Routing Policy using that routing table, are routed over the VPN. But there's no practical way to fix it *within* the OpenVPN client itself (on a soft-restart, scripts aren't called, only on a hard-restart). The only means to fix it is to monitor that routing table, see if it's empty (presumably because of a soft-restart), then repopulate it by picking off the current VPN gateway IP from a dump of ifconfig.

    Not pretty, I agree. But since this bug (afaik) in Routing Policy has never been fixed, it's all we have. And there are numerous other bugs in Routing Policy as well. I don't even use it for these reasons. I just use my own scripts which don't have these problems.

    The "kill switch" is just something the OP added. I've done something similar w/ dd-wrt, except I read the contents of the policy based routing field from nvram in order to construct the kill switch. IOW, it's all automatic. Just install and go.

    It's actually quite popular, if the hit count is any indicator. I'm sure it could be adapted for tomato as well. Butthe Routing Policy tab is so buggy anyway, I just never even considered it.
  20. geolink

    geolink New Member Member

    The script mentioned above will not work because of ; symbol in it.
    The scheduler from Tomato cuts all the code after the character ; and the script does not work as intended.
    The correct one will be:

    VPN_GW="$(ifconfig tun11 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}')"
    ip route add table 311 default via $VPN_GW dev tun11
    Moreover, there is no need in two lines of code, it is much easier and more understandable to implement it with a single line.

    ip route add table 311 default via "$(ifconfig tun11 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}')" dev tun11
  21. GetVladimir

    GetVladimir Reformed Router Member

    Thank you so much for the reply and for the updated code!

    The symbol ; is in the quoted line ', so it did seem to work before (as far as I know). I haven't tested it with any newer versions, so I can't say for sure.

    Also, thanks for the shortened code, it's more far more neat.

    Could you confirm with what version it works?
  22. eibgrad

    eibgrad Network Guru Member

    Here's an even better improvement.

    Just use my own PBR (policy based routing) script, which totally replaces the GUI's Routing Policy. The Routing Policy GUI has so many bugs (and they never seem to get fixed), that I don't even use it anymore. Just got tired of having to apply multiple fixes when it should be working correctly by now.

    Plus, you get more features, like being able to specify input network interface (iif) rather than source IPs, and even destination IPs.

    GetVladimir likes this.
  23. GetVladimir

    GetVladimir Reformed Router Member

    Thank you eibgrad! That script is actually a much better and robust solution than the GUI Routing Policy. I would recommend using it instead if possible.
  24. Evan Gelion

    Evan Gelion New Member Member

    And for Destination IP it will be like this?

    iptables -I FORWARD ! -o tun11 -d -j DROP
    iptables -I FORWARD -o `nvram get wan_iface` -d -j DROP
  25. GetVladimir

    GetVladimir Reformed Router Member

    Yes, you can simply replace the domain with an actual IP address
  26. Evan Gelion

    Evan Gelion New Member Member

    And one more question. On my router i have added selective routing policies for few remote IP`s. All of them are using by only one pc. But i don`t want to redirect all internet traffic from this pc via VPN. How to make killswich to drop all internet connection to current pc when vpn is down for one of the routing policies...
  27. GetVladimir

    GetVladimir Reformed Router Member

    Either I didn't understood your question, or the solution is in the #1 post of this topic.
  28. PatrickvanBavel

    PatrickvanBavel New Member Member

    Hi, I have a question: is it possible to enable the VPN only for a specific ip AND port? I want SABnzb on my NAS ( to use the VPN and have a kill switch, but all the other applications on my NAS should always be accessible. Thanks, Patrick
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice