eibgrad

ddwrt-ovpn-split-basic.sh

Mar 21st, 2017 (edited)
2,534
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: 3.1.0, 08-aug-2022, by eibgrad
  6. #       purpose: basic ip/network/interface based openvpn split tunneling
  7. #   script type: openvpn route-up/route-pre-down
  8. #  installation:
  9. #    1. enable jffs2 (administration->jffs2)
  10. #    2. disable policy based routing (services->vpn->openvpn client)
  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 W2P3TDZT
  13. #       or
  14. #         wget -qO - bit.ly/ddwrt-installer|tr -d '\r'|sh -s W2P3TDZT
  15. #    4. use vi editor to add/modify rules:
  16. #         vi /jffs/etc/config/ddwrt-ovpn-split-basic.sh
  17. #       note: rules can be managed outside the script by placing them in a
  18. #       file(s) w/ the extension .rules in the installation directory; these
  19. #       will be imported and used at runtime in leu of the script's embedded
  20. #       rules
  21. #    5. optional: by default, the default gateway is set to the WAN, so
  22. #       the rules reroute over the VPN; to set/lockdown the default gateway
  23. #       to the VPN and have the rules reroute to the WAN, disable the
  24. #       following directives as shown in openvpn client additional config:
  25. #         #pull-filter ignore redirect-gateway
  26. #         #redirect-private def1
  27. #       note: default routing is configurable during installation
  28. #    6. reboot
  29. #   limitations, known issues, and miscellany:
  30. #     - this script is only supported by dd-wrt v43904 (7/23/20) or later
  31. #     - this script is NOT compatible w/ dd-wrt policy based routing
  32. #     - rules are limited to source ip/network/interface and destination
  33. #       ip/network w/ most firmware; source/destination ports are also
  34. #       available on select firmware (e.g., rt-ac68u)
  35. #     - rules do NOT support domain names (e.g., google.com)
  36. #     - lan->wan default routing excludes the router itself from the vpn,
  37. #       whereas lan->vpn does NOT; something you may wish to consider when
  38. #       deciding on your preference
  39. {
  40. add_rules() {
  41. # ----------------------------------- FYI ------------------------------------ #
  42. # * the order of rules doesn't matter (there is no order of precedence)
  43. # * if any rule matches, those packets bypass the current default gateway
  44. # ---------------------------------------------------------------------------- #
  45.  
  46. # ------------------------------- BEGIN RULES -------------------------------- #
  47.  
  48. # specify source ip/network/interface/port to be rerouted
  49. #   warning: sport/dport NOT supported on all firmware
  50. #add_rule iif br1                      # guest network
  51. #add_rule from 192.168.1.14            # jim's laptop
  52. #add_rule from 192.168.2.0/24          # iot network
  53. #add_rule from 192.168.1.10 sport 80   # webserver
  54. #add_rule from 192.168.1.11 dport 443  # mike's laptop
  55.  
  56. # specify destination ip/network to be rerouted
  57. #add_rule to 4.79.142.0/24  # grc.com
  58. #add_rule to 172.217.6.142  # maps.google.com
  59.  
  60. # specify source + destination to be rerouted
  61. #add_rule iif br2             to 121.121.121.121
  62. #add_rule from 192.168.1.10   to 122.122.122.122
  63. #add_rule from 192.168.2.0/24 to 133.133.133.0/24
  64.  
  65. # -------------------------------- END RULES --------------------------------- #
  66. :;}
  67. # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
  68.  
  69. ENV_VARS='/tmp/env_vars'
  70.  
  71. # make environment variables persistent across openvpn events
  72. [ "$script_type" == 'route-up' ] && env > $ENV_VARS
  73.  
  74. # utility function for retrieving environment variable values
  75. env_get() { echo $(grep -Em1 "^$1=" $ENV_VARS | cut -d = -f2); }
  76.  
  77. IMPORT_RULES_FILESPEC="$(dirname $0)/*.rules"
  78.  
  79. TID='200'
  80.  
  81. # function add_rule( rule )
  82. add_rule() {
  83.     # precede addition w/ deletion to avoid dupes
  84.     ip rule del table $TID "$@" 2>/dev/null
  85.     ip rule add table $TID "$@"
  86. }
  87.  
  88. # function up()
  89. up() {
  90.     # call dd-wrt route-up script
  91.     /tmp/openvpncl/route-up.sh 2>/dev/null
  92.  
  93.     # copy main routing table to alternate (exclude all default gateways)
  94.     ip route show | grep -Ev '^default |^0\.0\.0\.0/1 |^128\.0\.0\.0/1 ' \
  95.       | while read route; do
  96.             ip route add $route table $TID
  97.         done
  98.  
  99.     if ip route | grep -q "^0\.0\.0\.0/1 .*$(env_get dev)"; then
  100.         # add WAN as default gateway to alternate routing table
  101.         ip route add default via $(env_get route_net_gateway) table $TID
  102.     else
  103.         # add VPN as default gateway to alternate routing table
  104.         ip route add default via $(env_get route_vpn_gateway) table $TID
  105.     fi
  106.  
  107.     # start split tunnel
  108.     local files="$(echo $IMPORT_RULES_FILESPEC)"
  109.     if [ "$files" != "$IMPORT_RULES_FILESPEC" ]; then
  110.         # convert from dos to linux file format (as necessary)
  111.         for file in $files; do
  112.             grep -q '\r' "$file" && sed -i 's/\r//g' "$file"
  113.         done
  114.         # add rules from import file(s) (if any)
  115.         for file in $files; do . "$file"; done
  116.     else
  117.         # use embedded rules
  118.         add_rules
  119.     fi
  120.  
  121.     # force routing system to recognize changes
  122.     ip route flush cache
  123. }
  124.  
  125. # function down()
  126. down() {
  127.     # stop split tunnel
  128.     while ip rule del from 0/0 to 0/0 table $TID 2>/dev/null; do :; done
  129.  
  130.     # delete alternate routing table
  131.     ip route flush table $TID
  132.  
  133.     # force routing system to recognize changes
  134.     ip route flush cache
  135.  
  136.     # cleanup
  137.     rm -f $ENV_VARS
  138.  
  139.     # call dd-wrt route-pre-down script
  140.     /tmp/openvpncl/route-down.sh 2>/dev/null
  141. }
  142.  
  143. # reject cli invocation; script only applicable to routed (tun) tunnels
  144. [[ -t 0 || "$(env_get dev_type)" != 'tun' ]] && exit 1
  145.  
  146. # gui-based policy based routing can NOT be active at the same time
  147. if [ "$(nvram get openvpncl_spbr)" ]; then
  148.     if [ "$(nvram get openvpncl_spbr)" != '0' ]; then
  149.         echo 'fatal error: policy based routing already active in gui'
  150.         exit 1
  151.     fi
  152. elif [ "$(nvram get openvpncl_route)" ]; then
  153.     echo 'fatal error: policy based routing already active in gui'
  154.     exit 1
  155. fi
  156.  
  157. # trap event-driven callbacks by openvpn and take appropriate action(s)
  158. case "$script_type" in
  159.           'route-up') up;;
  160.     'route-pre-down') down;;
  161.                    *) echo "warning: unexpected invocation: $script_type";;
  162. esac
  163.  
  164. exit 0
  165. } 2>&1 | logger -t "$(basename $0 .${0##*.} | grep -Eo '^.{0,23}')[$$]"
RAW Paste Data Copied