SHOW:
|
|
- or go back to the newest paste.
| 1 | #!/bin/sh | |
| 2 | - | # version: 1.0.0, 28-sep-2021, by eibgrad |
| 2 | + | #DEBUG= # uncomment/comment to enable/disable debug mode |
| 3 | - | # href: https://tinyurl.com/crwtpkep |
| 3 | + | |
| 4 | # name: merlin-ovpn-client-killswitch.sh | |
| 5 | # version: 2.0.0, 22-jul-2022, by eibgrad | |
| 6 | - | SCRIPT="$SCRIPTS_DIR/firewall-start" |
| 6 | + | # purpose: openvpn client firewall-based killswitch |
| 7 | # type(s): firewall-start | |
| 8 | # href: https://tinyurl.com/35xww7ue | |
| 9 | # installation: | |
| 10 | # 1. enable jffs custom scripts and configs (administration->system) | |
| 11 | - | cat << "EOF" > $SCRIPT |
| 11 | + | # 2. ssh to router and copy/paste the following command: |
| 12 | # curl -kLs bit.ly/merlin-installer|tr -d '\r'|sh -s F2GmyrCC | |
| 13 | - | set -x # uncomment/comment to enable/disable debug mode |
| 13 | + | # 3. modify script w/ your preferred options using nano editor: |
| 14 | # nano /jffs/scripts/merlin-ovpn-client-killswitch.sh | |
| 15 | # 4. reboot | |
| 16 | ||
| 17 | - | # openvpn clients that will participate in the kill switch (all by default) |
| 17 | + | |
| 18 | SCRIPT1="$SCRIPTS_DIR/merlin-ovpn-client-killswitch.sh" | |
| 19 | SCRIPT2="$SCRIPTS_DIR/firewall-start" | |
| 20 | ||
| 21 | mkdir -p $SCRIPTS_DIR | |
| 22 | ||
| 23 | # ------------------- begin merlin-ovpn-client-killswitch -------------------- # | |
| 24 | cat << 'EOF' > $SCRIPT1 | |
| 25 | #!/bin/sh | |
| 26 | #set -x # comment/uncomment to disable/enable debug mode | |
| 27 | {
| |
| 28 | # ------------------------------ BEGIN OPTIONS ------------------------------- # | |
| 29 | ||
| 30 | # openvpn clients that will participate in the killswitch (all by default) | |
| 31 | VPN_CLIENTS='1 2 3 4 5' | |
| 32 | ||
| 33 | # uncomment/comment to enable/disable autostart checking | |
| 34 | VPN_AUTOSTART_ONLY= # only consider auto-started openvpn clients | |
| 35 | ||
| 36 | # state checking: "state NEW" vs. no state | |
| 37 | # state NEW: | |
| 38 | # * any pre-existing LAN->WAN connections persist unless/until they | |
| 39 | # timeout/close | |
| 40 | # * remote access (WAN->LAN) is allowed (provided port forwarding is enabled) | |
| 41 | # * more efficient (only LAN->WAN packets used to establish NEW connections | |
| 42 | - | PBR_RULES="$(cat /jffs/openvpn/vpndirector_rulelist)" |
| 42 | + | |
| 43 | - | FW_CHAIN='ovpn_block_wan' |
| 43 | + | |
| 44 | - | WAN_IF="$(nvram get wan0_ifname)" |
| 44 | + | |
| 45 | # * remote access (WAN->LAN) is denied (even if port forwarding is enabled) | |
| 46 | # * less efficient (every LAN->WAN packet is inspected) | |
| 47 | ||
| 48 | # uncomment/comment to enable/disable state checking | |
| 49 | - | # function is_kill_switch_participant( vpn-client-number ) |
| 49 | + | |
| 50 | - | is_kill_switch_participant() { echo $VPN_CLIENTS | grep -q $1; }
|
| 50 | + | |
| 51 | # ------------------------------- END OPTIONS -------------------------------- # | |
| 52 | ||
| 53 | # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- # | |
| 54 | ||
| 55 | WAN_IF="$([ $1 ] && echo $1 || echo $(nvram get wan0_ifname))" | |
| 56 | PBR_RULES="$(sed 's/\s//g' /jffs/openvpn/vpndirector_rulelist 2>/dev/null)" | |
| 57 | FW_CHAIN='ovpnc_block_wan' | |
| 58 | ||
| 59 | # function is_autostart_enabled( vpn-client-number ) | |
| 60 | is_autostart_enabled() { nvram get vpn_clientx_eas | grep -q $1; }
| |
| 61 | ||
| 62 | # function is_killswitch_participant( vpn-client-number ) | |
| 63 | - | # prerequisite: vpn client has "Yes(all)" routing policy |
| 63 | + | is_killswitch_participant() { echo $VPN_CLIENTS | grep -q $1; }
|
| 64 | ||
| 65 | # function is_redirect_all( vpn-client-number ) | |
| 66 | is_redirect_all() { [ "$(nvram get vpn_client${1}_rgw)" == '1' ]; }
| |
| 67 | ||
| 68 | # cleanup from possible prior execution | |
| 69 | {
| |
| 70 | iptables -D FORWARD -i br+ -o $WAN_IF $FW_STATE -j REJECT | |
| 71 | iptables -D FORWARD -i br+ -o $WAN_IF $FW_STATE -j $FW_CHAIN | |
| 72 | iptables -F $FW_CHAIN && iptables -X $FW_CHAIN | |
| 73 | } &>/dev/null | |
| 74 | ||
| 75 | for i in $VPN_CLIENTS; do | |
| 76 | # handle vpn client w/ "Yes(all)" routing policy | |
| 77 | is_redirect_all $i || continue | |
| 78 | ||
| 79 | # prerequisite: vpn client has autostart enabled (when applicable) | |
| 80 | [ ${VPN_AUTOSTART_ONLY+x} ] && ! is_autostart_enabled $i && continue
| |
| 81 | ||
| 82 | - | # prerequisite: enabled vpn pbr rule |
| 82 | + | |
| 83 | - | { [ "$f1" == '1' ] && echo $f5 | grep -q 'OVPN'; } || continue
|
| 83 | + | |
| 84 | ||
| 85 | exit 0 | |
| 86 | done | |
| 87 | ||
| 88 | - | # prerequisite: vpn client is kill switch participant |
| 88 | + | |
| 89 | - | is_kill_switch_participant $f5 || continue |
| 89 | + | |
| 90 | ||
| 91 | # iterate over the pbr (policy based routing) rules | |
| 92 | for i in $(echo "$PBR_RULES" | tr '<' '\n'); do | |
| 93 | # parse the rule into separate fields (ignore description field (#2)) | |
| 94 | for j in 1 3 4 5; do eval f$j="$(echo $i | cut -d'>' -f$j)"; done | |
| 95 | ||
| 96 | # prerequisite: enabled rule | |
| 97 | [ "$f1" == '1' ] || continue | |
| 98 | ||
| 99 | # handle wan pbr rule | |
| 100 | if echo $f5 | grep -q 'WAN'; then | |
| 101 | # do NOT deny access to this local and/or remote ip/network | |
| 102 | iptables -A $FW_CHAIN $([ "$f3" ] && echo "-s $f3") \ | |
| 103 | - | #} >/tmp/$(basename $0).$$.log 2>&1 |
| 103 | + | $([ "$f4" ] && echo "-d $f4") -j RETURN |
| 104 | continue | |
| 105 | fi | |
| 106 | - | chmod +x $SCRIPT |
| 106 | + | |
| 107 | # handle vpn pbr rule | |
| 108 | echo $f5 | grep -q 'OVPN' || continue | |
| 109 | - | if [ -f $SCRIPT ]; then |
| 109 | + | |
| 110 | - | echo "error: $SCRIPT already exists; requires manual installation" |
| 110 | + | |
| 111 | f5="$(echo $f5 | grep -o [1-5])" | |
| 112 | ||
| 113 | - | echo 'Done.' |
| 113 | + | # prerequisite: vpn client is killswitch participant |
| 114 | - | fi |
| 114 | + | is_killswitch_participant $f5 || continue |
| 115 | ||
| 116 | # prerequisite: vpn client has autostart enabled (when applicable) | |
| 117 | [ ${VPN_AUTOSTART_ONLY+x} ] && ! is_autostart_enabled $f5 && continue
| |
| 118 | ||
| 119 | # deny access to wan for this local and/or remote ip/network | |
| 120 | iptables -A $FW_CHAIN $([ "$f3" ] && echo "-s $f3") \ | |
| 121 | $([ "$f4" ] && echo "-d $f4") -j REJECT | |
| 122 | done | |
| 123 | ||
| 124 | # force LAN->WAN traffic thru user-defined chain for inspection | |
| 125 | iptables -I FORWARD -i br+ -o $WAN_IF $FW_STATE -j $FW_CHAIN | |
| 126 | ||
| 127 | exit 0 | |
| 128 | } 2>&1 | logger -t $(basename $0 .sh)[$$] | |
| 129 | EOF | |
| 130 | [ ${DEBUG+x} ] && sed -ri '2 s/^#(set -x)/\1/' $SCRIPT1
| |
| 131 | chmod +x $SCRIPT1 | |
| 132 | echo "installed: $SCRIPT1" | |
| 133 | # -------------------- end merlin-ovpn-client-killswitch --------------------- # | |
| 134 | ||
| 135 | # --------------------------- begin firewall-start --------------------------- # | |
| 136 | create_script() {
| |
| 137 | cat << 'EOF' > $SCRIPT2 | |
| 138 | #!/bin/sh | |
| 139 | #set -x # comment/uncomment to disable/enable debug mode | |
| 140 | {
| |
| 141 | $SCRIPT1 | |
| 142 | } 2>&1 | logger -t $(basename $0)[$$] | |
| 143 | EOF | |
| 144 | [ ${DEBUG+x} ] && sed -ri '2 s/^#(set -x)/\1/' $SCRIPT2
| |
| 145 | sed "s:\$SCRIPT1:$SCRIPT1:g" -i $SCRIPT2 | |
| 146 | chmod +x $SCRIPT2 | |
| 147 | } | |
| 148 | ||
| 149 | if [ -f $SCRIPT2 ]; then | |
| 150 | echo "error: $SCRIPT2 already exists; requires manual installation" | |
| 151 | else | |
| 152 | create_script | |
| 153 | echo "installed: $SCRIPT2" | |
| 154 | fi | |
| 155 | # ---------------------------- end firewall-start ---------------------------- # |