eibgrad

merlin-ovpn-client-killswitch.sh

Sep 28th, 2021 (edited)
2,903
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/sh
  2. #DEBUG= # uncomment/comment to enable/disable debug mode
  3.  
  4. #          name: merlin-ovpn-client-killswitch.sh
  5. #       version: 2.0.0, 22-jul-2022, by eibgrad
  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. #    2. ssh to router and copy/paste the following command:
  12. #         curl -kLs bit.ly/merlin-installer|tr -d '\r'|sh -s F2GmyrCC
  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. SCRIPTS_DIR="/jffs/scripts"
  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. #       are inspected)
  43. #   no state (default):
  44. #     * any pre-existing LAN->WAN connections are stopped/blocked
  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. #FW_STATE='-m state --state NEW'
  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. 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.     # deny access to wan by *all* lan clients
  83.     iptables -I FORWARD -i br+ -o $WAN_IF $FW_STATE -j REJECT
  84.  
  85.     exit 0
  86. done
  87.  
  88. # create user-defined chain
  89. iptables -N $FW_CHAIN
  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.             $([ "$f4" ] && echo "-d $f4") -j RETURN
  104.         continue
  105.     fi
  106.  
  107.     # handle vpn pbr rule
  108.     echo $f5 | grep -q 'OVPN' || continue
  109.  
  110.     # isolate vpn client number
  111.     f5="$(echo $f5 | grep -o [1-5])"
  112.  
  113.     # prerequisite: vpn client is killswitch participant
  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 ---------------------------- #
Add Comment
Please, Sign In to add comment