Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- #DEBUG=; set -x # uncomment/comment to enable/disable debug mode
- # name: ddwrt-ovpn-split-basic.sh
- # version: 3.1.0, 08-aug-2022, by eibgrad
- # purpose: basic ip/network/interface based openvpn split tunneling
- # script type: openvpn route-up/route-pre-down
- # installation:
- # 1. enable jffs2 (administration->jffs2)
- # 2. disable policy based routing (services->vpn->openvpn client)
- # 3. use shell (telnet/ssh) to execute one of the following commands:
- # curl -kLs bit.ly/ddwrt-installer|tr -d '\r'|sh -s W2P3TDZT
- # or
- # wget -qO - bit.ly/ddwrt-installer|tr -d '\r'|sh -s W2P3TDZT
- # 4. use vi editor to add/modify rules:
- # vi /jffs/etc/config/ddwrt-ovpn-split-basic.sh
- # note: rules can be managed outside the script by placing them in a
- # file(s) w/ the extension .rules in the installation directory; these
- # will be imported and used at runtime in leu of the script's embedded
- # rules
- # 5. optional: by default, the default gateway is set to the WAN, so
- # the rules reroute over the VPN; to set/lockdown the default gateway
- # to the VPN and have the rules reroute to the WAN, disable the
- # following directives as shown in openvpn client additional config:
- # #pull-filter ignore redirect-gateway
- # #redirect-private def1
- # note: default routing is configurable during installation
- # 6. reboot
- # limitations, known issues, and miscellany:
- # - this script is only supported by dd-wrt v43904 (7/23/20) or later
- # - this script is NOT compatible w/ dd-wrt policy based routing
- # - rules are limited to source ip/network/interface and destination
- # ip/network w/ most firmware; source/destination ports are also
- # available on select firmware (e.g., rt-ac68u)
- # - rules do NOT support domain names (e.g., google.com)
- # - lan->wan default routing excludes the router itself from the vpn,
- # whereas lan->vpn does NOT; something you may wish to consider when
- # deciding on your preference
- {
- add_rules() {
- # ----------------------------------- FYI ------------------------------------ #
- # * the order of rules doesn't matter (there is no order of precedence)
- # * if any rule matches, those packets bypass the current default gateway
- # ---------------------------------------------------------------------------- #
- # ------------------------------- BEGIN RULES -------------------------------- #
- # specify source ip/network/interface/port to be rerouted
- # warning: sport/dport NOT supported on all firmware
- #add_rule iif br1 # guest network
- #add_rule from 192.168.1.14 # jim's laptop
- #add_rule from 192.168.2.0/24 # iot network
- #add_rule from 192.168.1.10 sport 80 # webserver
- #add_rule from 192.168.1.11 dport 443 # mike's laptop
- # specify destination ip/network to be rerouted
- #add_rule to 4.79.142.0/24 # grc.com
- #add_rule to 172.217.6.142 # maps.google.com
- # specify source + destination to be rerouted
- #add_rule iif br2 to 121.121.121.121
- #add_rule from 192.168.1.10 to 122.122.122.122
- #add_rule from 192.168.2.0/24 to 133.133.133.0/24
- # -------------------------------- END RULES --------------------------------- #
- :;}
- # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
- ENV_VARS='/tmp/env_vars'
- # make environment variables persistent across openvpn events
- [ "$script_type" == 'route-up' ] && env > $ENV_VARS
- # utility function for retrieving environment variable values
- env_get() { echo $(grep -Em1 "^$1=" $ENV_VARS | cut -d = -f2); }
- IMPORT_RULES_FILESPEC="$(dirname $0)/*.rules"
- TID='200'
- # function add_rule( rule )
- add_rule() {
- # precede addition w/ deletion to avoid dupes
- ip rule del table $TID "$@" 2>/dev/null
- ip rule add table $TID "$@"
- }
- # function up()
- up() {
- # call dd-wrt route-up script
- /tmp/openvpncl/route-up.sh 2>/dev/null
- # copy main routing table to alternate (exclude all default gateways)
- ip route show | grep -Ev '^default |^0\.0\.0\.0/1 |^128\.0\.0\.0/1 ' \
- | while read route; do
- ip route add $route table $TID
- done
- if ip route | grep -q "^0\.0\.0\.0/1 .*$(env_get dev)"; then
- # add WAN as default gateway to alternate routing table
- ip route add default via $(env_get route_net_gateway) table $TID
- else
- # add VPN as default gateway to alternate routing table
- ip route add default via $(env_get route_vpn_gateway) table $TID
- fi
- # start split tunnel
- local files="$(echo $IMPORT_RULES_FILESPEC)"
- if [ "$files" != "$IMPORT_RULES_FILESPEC" ]; then
- # convert from dos to linux file format (as necessary)
- for file in $files; do
- grep -q '\r' "$file" && sed -i 's/\r//g' "$file"
- done
- # add rules from import file(s) (if any)
- for file in $files; do . "$file"; done
- else
- # use embedded rules
- add_rules
- fi
- # force routing system to recognize changes
- ip route flush cache
- }
- # function down()
- down() {
- # stop split tunnel
- while ip rule del from 0/0 to 0/0 table $TID 2>/dev/null; do :; done
- # delete alternate routing table
- ip route flush table $TID
- # force routing system to recognize changes
- ip route flush cache
- # cleanup
- rm -f $ENV_VARS
- # call dd-wrt route-pre-down script
- /tmp/openvpncl/route-down.sh 2>/dev/null
- }
- # reject cli invocation; script only applicable to routed (tun) tunnels
- [[ -t 0 || "$(env_get dev_type)" != 'tun' ]] && exit 1
- # gui-based policy based routing can NOT be active at the same time
- if [ "$(nvram get openvpncl_spbr)" ]; then
- if [ "$(nvram get openvpncl_spbr)" != '0' ]; then
- echo 'fatal error: policy based routing already active in gui'
- exit 1
- fi
- elif [ "$(nvram get openvpncl_route)" ]; then
- echo 'fatal error: policy based routing already active in gui'
- exit 1
- fi
- # trap event-driven callbacks by openvpn and take appropriate action(s)
- case "$script_type" in
- 'route-up') up;;
- 'route-pre-down') down;;
- *) echo "warning: unexpected invocation: $script_type";;
- esac
- exit 0
- } 2>&1 | logger -t "$(basename $0 .${0##*.} | grep -Eo '^.{0,23}')[$$]"
Add Comment
Please, Sign In to add comment