Advertisement
eibgrad

ddwrt-ovpn-split.sh

Mar 12th, 2015 (edited)
1,248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.93 KB | None | 0 0
  1. #!/bin/sh
  2. export DEBUG= # uncomment/comment to enable/disable debug mode
  3. # ---------------------------------------------------------------------------- #
  4. # ddwrt-ovpn-split.sh: v1.0.4, 20 January 2017, by eibgrad
  5. # ---------------------------------------------------------------------------- #
  6.  
  7. OVPN_DIR="/tmp"
  8. OVPN_SPLIT="$OVPN_DIR/ovpn-split.sh"
  9. OVPN_SPLIT_BOOT="$OVPN_DIR/ovpn-split-boot.sh"
  10.  
  11. # ----------------------------- BEGIN OVPN_SPLIT ----------------------------- #
  12. cat << "EOF" > $OVPN_SPLIT
  13. #!/bin/sh
  14.  
  15. dev_type="$(grep -Em1 '^dev ' /tmp/openvpncl/openvpn.conf | \
  16.    awk '{print substr($2,0,3)}')"
  17. # this script is only applicable to routed (tun) tunnels
  18. [ "$dev_type" != "tun" ] && exit
  19.  
  20. (
  21. [ ${DEBUG+x} ] && set -x
  22. # ---------------------------------------------------------------------------- #
  23. # GW_MODE="WAN" : make WAN default gateway, firewall rules bypass WAN for VPN
  24. # GW_MODE="VPN" : make VPN default gateway, firewall rules bypass VPN for WAN
  25. # GW_MODE=""    : firewall rules bypass current default gateway for WAN/VPN
  26. # ---------------------------------------------------------------------------- #
  27.  
  28. #GW_MODE="WAN"
  29. #GW_MODE="VPN"
  30. GW_MODE=""
  31.  
  32. TID="200"
  33. FW_MARK="0x88"
  34.  
  35. VPN_IF="$(grep -Em1 '^dev ' /tmp/openvpncl/openvpn.conf | awk '{print $2}')"
  36. VPN_GW="$(ifconfig $VPN_IF | awk '/inet addr/ {split ($3,A,":"); print A[2]}')"
  37. WAN_IF="$(ip route | awk '/^default/{print $NF}')"
  38. WAN_GW="$(nvram get wan_gateway)"
  39.  
  40. DFLT_GW_MASK='^default|^0.0.0.0/1|^128.0.0.0/1'
  41.  
  42. is_gw_redirected() {
  43.     # scan main routing table for VPN default gateway
  44.     ip route show | grep -E $DFLT_GW_MASK | grep -Eqm1 "$VPN_IF"
  45. }
  46.  
  47. change_main_default_gw() {
  48.     # add more specific default routes to WAN/VPN in main routing table
  49.     ip route add   0.0.0.0/2 via $1
  50.     ip route add  64.0.0.0/2 via $1
  51.     ip route add 128.0.0.0/2 via $1
  52.     ip route add 192.0.0.0/2 via $1
  53. }
  54.  
  55. # if GW_MODE unspecified/invalid, assume current default gateway
  56. if [[ "$GW_MODE" != "WAN" && "$GW_MODE" != "VPN" ]]; then
  57.     is_gw_redirected && GW_MODE="VPN" || GW_MODE="WAN"
  58. fi
  59.  
  60. # copy main routing table to bypass routing table (exclude all
  61. # default gateways)
  62. ip route show | grep -Ev $DFLT_GW_MASK \
  63.   | while read route; do
  64.         ip route add $route table $TID
  65.     done
  66.  
  67. # determine whether to add WAN or VPN to bypass routing table,
  68. # and whether main routing table needs default gateway changed
  69. if   [ "$GW_MODE" == "WAN" ]; then
  70.     # add VPN as default gateway to bypass routing table
  71.     ip route add default via $VPN_GW table $TID
  72.     # add WAN as default gateway to main routing table
  73.     is_gw_redirected && change_main_default_gw $WAN_GW
  74.  
  75. else # "$GW_MODE" == "VPN"
  76.     # add WAN as default gateway to bypass routing table
  77.     ip route add default via $WAN_GW table $TID
  78.     # add VPN as default gateway to main routing table
  79.     is_gw_redirected || change_main_default_gw $VPN_GW
  80. fi
  81.  
  82. # force routing system to recognize our changes
  83. ip route flush cache
  84.  
  85. # disable reverse path filtering
  86. for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
  87.     echo 0 > $i
  88. done
  89.  
  90. # install additional iptables modules
  91. insmod  xt_mac 2>/dev/null
  92. insmod ipt_mac 2>/dev/null
  93.  
  94. # useful abbreviations
  95. IPT_MARK="-j MARK --set-mark $FW_MARK"
  96. IPT_RTR="iptables -t mangle -A OUTPUT"
  97. IPT_LAN="iptables -t mangle -A PREROUTING"
  98.  
  99. # WARNING: IPT_MARK must be specified last when used in any firewall rules or
  100. #          else dd-wrt will generate a segmentation fault!
  101.  
  102. # bypass WAN/VPN (router only)
  103. # --------------------------- BEGIN FIREWALL RULES --------------------------- #
  104. $IPT_RTR -p tcp -m multiport --sports 2222,8080 $IPT_MARK # router services
  105. # ---------------------------- END FIREWALL RULES ---------------------------- #
  106.  
  107. # bypass WAN/VPN (lan only)
  108. # --------------------------- BEGIN FIREWALL RULES --------------------------- #
  109. $IPT_LAN -s 192.168.1.113 $IPT_MARK
  110. $IPT_LAN -p tcp -s 192.168.1.42 --sport 22 $IPT_MARK # port forward
  111. $IPT_LAN -p tcp -s 192.168.1.107 --sport 80 $IPT_MARK # port forward
  112. $IPT_LAN -p tcp -s 192.168.1.155 --sport 80 $IPT_MARK # port forward
  113. $IPT_LAN -p tcp --dport 443 $IPT_MARK
  114. $IPT_LAN -m mac --mac-source b8:70:f4:b3:4d:6a $IPT_MARK
  115. # ---------------------------- END FIREWALL RULES ---------------------------- #
  116.  
  117. # if NAT enabled, then NAT everything (router and all)
  118. if iptables -t nat -vnL POSTROUTING | grep -q $VPN_IF; then
  119.     # enable NAT for all over WAN
  120.     iptables -t nat -I POSTROUTING -o $WAN_IF -j MASQUERADE
  121.     # enable NAT for all over VPN
  122.     iptables -t nat -I POSTROUTING -o $VPN_IF -j MASQUERADE
  123. fi
  124.  
  125. # start split tunnel
  126. ip rule add fwmark $FW_MARK table $TID
  127.  
  128. ) 2>&1 | logger -t $(basename $0)[$$]
  129. EOF
  130. chmod +x $OVPN_SPLIT
  131. # ------------------------------ END OVPN_SPLIT ------------------------------ #
  132.  
  133. # -------------------------- BEGIN OVPN_SPLIT_BOOT --------------------------- #
  134. cat << "EOF" > $OVPN_SPLIT_BOOT
  135. #!/bin/sh
  136. (
  137. [ ${DEBUG+x} ] && set -x
  138. WAIT_TIME="10"
  139.  
  140. # wait for OpenVPN to start
  141. while ! pidof openvpn >/dev/null 2>&1; do
  142.     sleep $WAIT_TIME
  143. done
  144.  
  145. # wait for OpenVPN network interface to be defined
  146. while :; do
  147.     VPN_IF="$(grep -Em1 '^dev ' /tmp/openvpncl/openvpn.conf 2>/dev/null | \
  148.        awk '{print $2}')"
  149.     [ ! "$VPN_IF" ] && sleep $WAIT_TIME || break
  150. done
  151.  
  152. # wait for OpenVPN network interface to be initialized (w/ ip address)
  153. while :; do
  154.     VPN_GW="$(ifconfig $VPN_IF | \
  155.        awk '/inet addr/ {split ($3,A,":"); print A[2]}')"
  156.     [ ! "$VPN_GW" ] && sleep $WAIT_TIME || break
  157. done
  158.  
  159. # wait for OpenVPN initialized network interface to appear in routing table
  160. while ! ip route show | grep -m1 $VPN_GW | grep -q $VPN_IF; do
  161.     sleep $WAIT_TIME
  162. done
  163.  
  164. # start split tunnel
  165. $OVPN_SPLIT &
  166.  
  167. ) 2>&1 | logger -t $(basename $0)[$$]
  168. EOF
  169. sed -i "s:\$OVPN_SPLIT:$OVPN_SPLIT:" $OVPN_SPLIT_BOOT
  170. chmod +x $OVPN_SPLIT_BOOT
  171. # --------------------------- END OVPN_SPLIT_BOOT ---------------------------- #
  172.  
  173. # start bootstrap
  174. $OVPN_SPLIT_BOOT &
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement