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 ---------------------------- # |