eibgrad

ddwrt-ovpn-split-basic.sh

Mar 21st, 2017 (edited)
2,071
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/sh
  2. DEBUG=; set -x # uncomment/comment to enable/disable debug mode
  3.  
  4. #          name: ddwrt-ovpn-split-basic.sh
  5. #       version: 2.0.1, 17-sep-2020, by eibgrad
  6. #       purpose: redirect specific traffic over the WAN|VPN
  7. #   script type: openvpn route-up/route-pre-down
  8. #  installation:
  9. #    1. enable jffs2 (administration->jffs2)
  10. #    2. enable syslogd (services->services->system log)
  11. #    3. use shell (telnet/ssh) to execute one of the following commands:
  12. #         curl -kLs bit.ly/ddwrt-installer|tr -d '\r'|sh -s -- --dir /jffs W2P3TDZT
  13. #       or
  14. #         wget -qO - bit.ly/ddwrt-installer|tr -d '\r'|sh -s -- --dir /jffs W2P3TDZT
  15. #    4. use vi editor to modify script w/ your rules:
  16. #         vi /jffs/ddwrt-ovpn-split-basic.sh
  17. #    5. create symbolic links:
  18. #         ln -sf /jffs/ddwrt-ovpn-split-basic.sh /jffs/route-up
  19. #         ln -sf /jffs/ddwrt-ovpn-split-basic.sh /jffs/route-down
  20. #    6. add the following to openvpn client additional config:
  21. #         route-up /jffs/route-up
  22. #         route-pre-down /jffs/route-down
  23. #    7. optional: by default, the default gateway is changed to the VPN,
  24. #       so the rules reroute over the WAN; to set/lockdown the default
  25. #       gateway to the WAN and have the rules reroute to the VPN, add the
  26. #       following directives to openvpn client additional config:
  27. #         pull-filter ignore "redirect-gateway"
  28. #         redirect-private def1
  29. #    8. disable/clear policy based routing (services->vpn->openvpn client)
  30. #    9. reboot
  31. #   limitations:
  32. #     - this script is only supported by dd-wrt v43904 (7/23/20) or later
  33. #     - this script is NOT compatible w/ dd-wrt policy based routing
  34. #     - rules are limited to source ip/network/interface and destination
  35. #       ip/network; split tunneling within any given source or destination
  36. #       (protocol, port, etc.) is NOT supported
  37. #     - rules do NOT support domain names (e.g., google.com)
  38. {
  39. add_rules() {
  40. # ----------------------------------- FYI ------------------------------------ #
  41. # * the order of rules doesn't matter (there is no order of precedence)
  42. # * if any rule matches, those packets bypass the current default gateway
  43. # ---------------------------------------------------------------------------- #
  44.  
  45. # ------------------------------- BEGIN RULES -------------------------------- #
  46. # specify source ip(s)/network(s)/interface(s) to be rerouted
  47. #add_rule iif br1             # guest network
  48. #add_rule from 192.168.1.7    # mary's pc
  49. #add_rule from 192.168.2.0/24 # iot network
  50.  
  51. # specify destination ip(s)/network(s) to be rerouted
  52. #add_rule to 4.79.142.0/24    # grc.com
  53. #add_rule to 172.217.6.142    # maps.google.com
  54.  
  55. # specify source + destination to be rerouted
  56. #add_rule iif br2             to 121.121.121.121
  57. #add_rule from 192.168.1.10   to 122.122.122.122
  58. #add_rule from 192.168.2.0/24 to 133.133.133.0/24
  59. # -------------------------------- END RULES --------------------------------- #
  60. :;}
  61. # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
  62.  
  63. ENV_VARS='/tmp/env_vars'
  64.  
  65. # make environment variables persistent across openvpn events
  66. [ "$script_type" == 'route-up' ] && env > $ENV_VARS
  67.  
  68. # utility function for retrieving environment variable values
  69. env_get() { echo $(grep -Em1 "^$1=" $ENV_VARS | cut -d = -f2); }
  70.  
  71. TID='200'
  72.  
  73. add_rule() {
  74.     # precede addition w/ deletion to avoid dupes
  75.     ip rule del table $TID "$@" 2> /dev/null
  76.     ip rule add table $TID "$@"
  77. }
  78.  
  79. up() {
  80.     # call dd-wrt route-up script
  81.     /tmp/openvpncl/route-up.sh 2> /dev/null
  82.  
  83.     # copy main routing table to alternate (exclude all default gateways)
  84.     ip route show | grep -Ev '^default |^0.0.0.0/1 |^128.0.0.0/1 ' \
  85.       | while read route; do
  86.             ip route add $route table $TID
  87.         done
  88.  
  89.     if ip route | grep -q "^0\.0\.0\.0/1 .*$(env_get dev)"; then
  90.         # add WAN as default gateway to alternate routing table
  91.         ip route add default via $(env_get route_net_gateway) table $TID
  92.     else
  93.         # add VPN as default gateway to alternate routing table
  94.         ip route add default via $(env_get route_vpn_gateway) table $TID
  95.     fi
  96.  
  97.     # start split tunnel
  98.     add_rules
  99.  
  100.     # force routing system to recognize changes
  101.     ip route flush cache
  102. }
  103.  
  104. down() {
  105.     # stop split tunnel
  106.     while ip rule del from 0/0 to 0/0 table $TID 2> /dev/null; do :; done
  107.  
  108.     # delete alternate routing table
  109.     ip route flush table $TID
  110.  
  111.     # force routing system to recognize changes
  112.     ip route flush cache
  113.  
  114.     # cleanup
  115.     rm -f $ENV_VARS
  116.  
  117.     # call dd-wrt route-pre-down script
  118.     /tmp/openvpncl/route-down.sh 2> /dev/null
  119. }
  120.  
  121. main() {
  122.     # reject cli invocation; script only applicable to routed (tun) tunnels
  123.     [[ -t 0 || "$(env_get dev_type)" != 'tun' ]] && return 1
  124.  
  125.     # gui-based policy based routing can NOT be active at the same time
  126.     if [ "$(nvram get openvpncl_route)" ]; then
  127.         echo 'ERROR: Policy based routing is already active in the GUI!'
  128.         exit 1
  129.     fi
  130.  
  131.     # trap event-driven callbacks by openvpn and take appropriate action(s)
  132.     case "$script_type" in
  133.               route-up) up;;
  134.         route-pre-down) down;;
  135.                      *) echo "WARNING: unexpected invocation: $script_type";;
  136.     esac
  137.  
  138.     return 0
  139. }
  140.  
  141. main
  142.  
  143. } 2>&1 | logger -p user.$([ ${DEBUG+x} ] && echo 'debug' || echo 'notice') \
  144.     -t $(echo $(basename $0) | grep -Eo '^.{0,23}')[$$]
RAW Paste Data