Advertisement
MartineauPASTEBIN

ChkVPNConfig.sh

Feb 12th, 2018
625
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 17.54 KB | None | 0 0
  1. #!/bin/sh
  2. VER="v1.01b14"
  3. #============================================================================== © 2018 Martineau, v01.01b14
  4. #
  5. # Check VPN Selective routing configuration.
  6. #
  7. #       Schedule via cru/cron to have the VPN status tracked/dumped to Syslog.
  8. #
  9. #          ChkVPNConfig     [-h|help] [ all ] [ curldata]
  10. #
  11. #          ChkVPNConfig
  12. #                           Check only the currently ACTIVE VPN Client connections
  13. #          ChkVPNConfig     all
  14. #                           Check all VPN Client connections
  15. #          ChkVPNConfig     curldata
  16. #                           For each ACTIVE VPN Client attempt a 12MB data download
  17.  
  18. # [URL="https://www.snbforums.com/threads/multiple-vpn-clients-active-for-different-devices.40674/#post-379572"]Multiple VPN clients active for different devices[/URL]
  19. #*=====================================Functions=====================================================
  20.  
  21. # Print between line beginning with'#==' to first blank line inclusive
  22. ShowHelp() {
  23.     echo -en $cBWHT >&2
  24.     awk '/^#==/{f=1} f{print; if (!NF) exit}' $0
  25.     echo -en $cRESET >&2
  26. }
  27. Say(){
  28.    echo -e $$ $@ | logger -st "($(basename $0))"
  29. }
  30. SayT(){
  31.    echo -e $$ $@ | logger -t "($(basename $0))"
  32. }
  33. ANSIColours() {
  34.  
  35.     cRESET="\e[0m";cBLA="\e[30m";cRED="\e[31m";cGRE="\e[32m";cYEL="\e[33m";cBLU="\e[34m";cMAG="\e[35m";cCYA="\e[36m";cGRA="\e[37m"
  36.     cBGRA="\e[90m";cBRED="\e[91m";cBGRE="\e[92m";cBYEL="\e[93m";cBBLU="\e[94m";cBMAG="\e[95m";cBCYA="\e[96m";cBWHT="\e[97m"
  37.     aBOLD="\e[1m";aDIM="\e[2m";aUNDER="\e[4m";aBLINK="\e[5m";aREVERSE="\e[7m"
  38.     cRED_="\e[41m";cGRE_="\e[42m"
  39.  
  40. }
  41. Chain_exists() {
  42.  
  43.     # Args: {chain_name} [table_name]
  44.  
  45.     local CHAIN="$1"
  46.     shift
  47.  
  48.     [ $# -eq 1 ] && local TABLE="-t $1"
  49.  
  50.     iptables $TABLE -n -L $CHAIN >/dev/null 2>&1
  51.     local RC=$?
  52.     if [ $RC -ne 0 ];then
  53.         echo "N"
  54.         return 1
  55.     else
  56.         echo "Y"
  57.         return 0
  58.     fi
  59. }
  60. Check_DuplicateVPNPorts() {
  61.  
  62.     local VPN_ID=
  63.     local VPN_ADDR=
  64.     local VPN_PORTS=
  65.  
  66.     local VPN_ID_LIST="1 2 3 4 5"
  67.  
  68.  
  69.     #local VPN_CLIENTPORTS=$(nvram show 2> /dev/null | grep -E "vpn_client.*port" | grep -v "client_port")
  70.     for VPN_ID in $VPN_ID_LIST
  71.         do
  72.             VPN_ADDR=$(nvram get vpn_client${VPN_ID}_addr)
  73.  
  74.             if [ -z "$VPN_ADDR" ];then
  75.                 continue                                # VPN Client instance not configured?
  76.             fi
  77.             # vpn_client1_port=553
  78.             # vpn_client1_proto=udp
  79.             if [ "$1" == "2" ];then
  80.                 local VPN_STATE=$(nvram get "vpn_client"$VPN_ID"_state")
  81.                 if [ "$VPN_STATE" != "2" ];then
  82.                     continue
  83.                 fi
  84.             fi
  85.             local THIS=$(echo $(nvram get vpn_client${VPN_ID}_port)":"$(nvram get vpn_client${VPN_ID}_proto | tr "a-z" "A-Z") )
  86.             if [ "$2" == "diag" ];then
  87.                 local VPN_PORTS=$( echo -e "$VPN_PORTS VPN client" $VPN_ID "ACTIVE using port" $THIS", ")
  88.             else
  89.                 local VPN_PORTS=$(echo -e "$VPN_PORTS ${THIS}\n")
  90.             fi
  91.         done
  92.     if [ "$2" != "diag" ];then
  93.         # Convert words to individual lines and report on duplicates
  94.         echo $VPN_PORTS | tr ' ' '\n' | sort -n | uniq -d
  95.     else
  96.         echo $VPN_PORTS
  97.     fi
  98.  
  99. }
  100. ChkVPNIP() {
  101.  
  102.     local RESULT=0
  103.     local VPN_ID=$1
  104.  
  105.     if [ -f /usr/sbin/gettunnelip.sh ];then
  106.         sh /usr/sbin/gettunnelip.sh ${VPN_ID}
  107.         local VPN_WANIP="$(nvram get vpn_client${VPN_ID}_rip)"
  108.     fi
  109.  
  110.     if [ -z "$VPN_WANIP" ];then
  111.         local VPN_WANIP=$(curl --connect-timeout 5 -s --interface "tun1"${VPN_ID} "http://ipecho.net/plain")
  112.     fi
  113.  
  114.     local IPINFOIO=$(curl --connect-timeout 5 -s --interface "tun1"${VPN_ID} ipinfo.io)
  115.  
  116.     if [ ! -z "$VPN_WANIP" ];then
  117.         local RESULT=0
  118.     else
  119.         local RESULT=1
  120.     fi
  121.  
  122.     echo -e $VPN_WANIP" --> "$IPINFOIO
  123.  
  124.     return $RESULT
  125. }
  126. Is_Private_IPv4() {
  127.     grep -oE "(^127\.)|(^(0)?10\.)|(^172\.(0)?1[6-9]\.)|(^172\.(0)?2[0-9]\.)|(^172\.(0)?3[0-1]\.)|(^169\.254\.)|(^192\.168\.)"
  128. }
  129. Is_Private_IPv6 () {
  130.     grep -oE "(::1$)|([fF][cCdD])"
  131. }
  132. Data_Transfer() {
  133.  
  134.     local VPN_ID=$1
  135.  
  136.     # FORCE a small data transfer retrieval to confirm?
  137.     if [ -z "$2" ];then
  138.             echo -en $cBWHT"\n"
  139.             Say "Starting curl data transfer.....(Expect 12MB approx @3.1MB/sec on 20Mbps download = 00:04 secs)"
  140.             echo -en $cBYEL
  141.     fi
  142.  
  143.     echo -en $cBBLU
  144.     WGET_DATA="http://proof.ovh.net/files/100Mb.dat"
  145.     curl --interface tun1${VPN_ID} -o /dev/null $WGET_DATA
  146.     RC=$?
  147.     if [ $RC -eq 0 ];then
  148.         local STATUS=1
  149.     else
  150.         echo -en $cBRED
  151.         Say "***ERROR curl '"$WGET_DATA"' transfer FAILED RC="$RC
  152.         if [ $RC -ne 8 ];then
  153.             local STATUS=0                                              # Override PING/curl status!!
  154.         else
  155.             Say "*Warning curl '"$WGET_DATA"' URL invalid?"     # URL invalid so could be OFFLINE so ignore it
  156.         fi
  157.     fi
  158.  
  159.     return $STATUS
  160.  
  161. }
  162. CheckDNS() {
  163.  
  164.     local RESULT=0
  165.     local VPN_ID=$1
  166.    
  167.     local ETC="etc"
  168.    
  169.     echo -e $cBWHT
  170.     Say "VPN Client" ${VPN_TAB:2:1} "DNS config"
  171.  
  172.     if [ -f "/${ETC}/openvpn/dns/client${VPN_ID}.resolv" ];then
  173.         echo -en $cBGRE
  174.         echo -e "'/${ETC}/openvpn/dns/client${VPN_ID}.resolv'"
  175.  
  176.         cat "/${ETC}/openvpn/dns/client${VPN_ID}.resolv"
  177.         echo -e
  178.     fi
  179.    
  180.     echo -en $cBGRE
  181.     if [ -f "/${ETC}/openvpn/client${VPN_ID}/config.ovpn" ];then
  182.        Say "VPN Client" ${VPN_TAB:2:1} "Using DNS $(grep -E "^dhcp-option.*DNS" /${ETC}/openvpn/client${VPN_ID}/config.ovpn | awk '{print $3}')"
  183.     fi
  184.     if [ "$(Chain_exists "DNSVPN${VPN_ID}" "nat")" == "Y" ];then
  185.         echo -en $cBGRE
  186.         Say "VPN Client" ${VPN_TAB:2:1} "EXCLUSIVE DNSVPN${VPN_ID} chain configuration:"
  187.         iptables --line -t nat -nvL DNSVPN${VPN_ID}  2>/dev/null
  188.     else
  189.         echo -en $cBLU
  190.         Say "VPN Client" ${VPN_TAB:2:1} "EXCLUSIVE DNSVPN${VPN_ID} chain NOT enabled."
  191.     fi
  192.    
  193.  
  194. }
  195.  
  196. #============================================Main==================================================
  197.  
  198.  
  199. ANSIColours
  200.  
  201. # Provide assistance
  202. if [ "$1" = "-h" ] || [ "$1" = "help" ]; then
  203.    ShowHelp                                                     # Show help
  204.    exit 0
  205. fi
  206.  
  207. echo -e $cBWHT
  208. Say $VER "VPN Selective Routing configuration checker ....."
  209.  
  210. VPN_ROUTES=
  211. WAN_IP=
  212. MULTI_FOUND=
  213.  
  214. VPN_LIST=$(ip route show table 254 | grep -oE "tun1[1-5]" | sort | uniq )
  215. ACTIVE_VPN_CNT=$(ip route show table 254 | grep -oE "tun1[1-5]" | wc -w)
  216.  
  217. CHECKALL=0                                              # Only check ACTIVE VPN configurations
  218. if [ $(echo $@ | grep -cw "all") -gt 0 ];then
  219.     CHECKALL=1
  220.     VPN_LIST="111 112 113 114 115"  # 'all' directive found; Check all VPNs
  221. fi
  222.  
  223. DATA_TRANSFER=0                                         # Don't perform the 12MB curl data transfer
  224. if [ $(echo $@ | grep -cw "curldata") -gt 0 ];then
  225.     DATA_TRANSFER=1
  226. fi
  227.  
  228. for VPN_TAB in 254 $VPN_LIST
  229.     do
  230.         NODEFAULT=0
  231.  
  232.         [ "$VPN_TAB" != "254" ] && VPN_TAB=$(echo $VPN_TAB | sed 's/tun1/11/')
  233.         echo -e $cBWHT
  234.         if [ "$VPN_TAB" != "254" ];then
  235.             KILLTXT=
  236.             if [ "$(nvram get vpn_client${VPN_TAB:2:1}_enforce)" == "1" ];then
  237.                 KILLTXT="(VPN KILL switch Protection ENABLED)"
  238.             fi
  239.             Say "VPN Client" ${VPN_TAB:2:1}  "route Table:" $VPN_TAB $KILLTXT
  240.         else
  241.             Say "WAN (main) route Table:" $VPN_TAB
  242.         fi
  243.         echo -en $cBCYA
  244.  
  245.         AROUTE=$(ip route show table $VPN_TAB | awk ' /default/ {print $3}')
  246.  
  247.         # Obfuscate IP address(s)?
  248.         #ip route show table $VPN_TAB |  grep -E "^0\.|^128.|^default|^prohibit|tun1" | ObfuscateIP | ObfuscateCIDR
  249.         ip route show table $VPN_TAB |  grep -E "^0\.|^128.|^default|^prohibit|tun1"
  250.         ip route show table $VPN_TAB |  grep -E "^0\.|^128.|^default|^prohibit|tun1"  >>/tmp/syslog.log
  251.  
  252.         echo -e
  253.  
  254.         if [ -z "$AROUTE" ];then                                                    # No 'default'?
  255.              if [ "$VPN_TAB" != "254" ];then
  256.                 if [ ! -z "$(nvram get vpn_client${VPN_TAB:2:1}_addr)" ];then       # Configured ?
  257.                     VPN_FORCE=$(nvram get vpn_client${VPN_TAB:2:1}_enforce)         # Block if VPN DOWN=YES
  258.                     NODEFAULT=1                                     # No 'default'; but it's OK if there is 'prohibit default'
  259.                     if [ -z "$(ip route show table $VPN_TAB | awk ' /prohibit/ {print $1}')" ];then
  260.                         if [ "$VPN_FORCE" == "1" ];then
  261.                             if [ "$(nvram get vpn_client${VPN_TAB:2:1}_state)" != "2" ];then
  262.                                 echo -en $cBRED"\a"
  263.                                 Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "is missing KILL-switch 'prohibit default' - current WAN leak!"
  264.                             else
  265.                                 echo -en $cBRED"\a"
  266.                                 Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "has no DEFAULT route and is ACTIVE - WAN leak!"
  267.                             fi
  268.                         else
  269.                             if [ ! -z "$(ip route show table $VPN_TAB)" ];then      # Is table isn't empty
  270.                                 echo -en $cBRED"\a"
  271.                                 Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "has no DEFAULT route"
  272.                             else
  273.                                 STATE=$(nvram get vpn_client${VPN_TAB:2:1}_state)
  274.                                 if [ "$STATE" == "0" ];then
  275.                                     echo -en $cGRE
  276.                                     #Say "VPN Client" ${VPN_TAB:2:1} "is OK"
  277.                                 else
  278.                                     echo -en $cRED"\a"
  279.                                     Say "**Warning VPN Client" ${VPN_TAB:2:1} "is in STATE="$STATE
  280.                                 fi
  281.                             fi
  282.                         fi
  283.                     fi
  284.                     # Is there one of my custom WiFi->VPN map rule 20?00 rules
  285.                     if [ "$VPN_FORCE" == "1" ];then
  286.                         if [ ! -z "$(ip rule | grep "^20${VPN_TAB:2:1}00")" ] && [ -z "$(ip route show table $VPN_TAB | awk ' /prohibit/ {print $1}')" ];then
  287.                              echo -en $cBRED"\a"
  288.                              Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "is missing KILL-switch 'prohibit default' - WAN leak!"
  289.                         fi
  290.                     fi
  291.                 else
  292.                     echo -en $cBLU
  293.                     Say "VPN Client" ${VPN_TAB:2:1} "NOT configured".
  294.                 fi
  295.             else
  296.                 # Should ALWAYS have even if 0.0.0.0/1 or 128.0.0.0/1 are present
  297.                 Say "***ERROR*** Main routing table has no DEFAULT route"
  298.             fi
  299.  
  300.             echo -en $cRESET
  301.         fi
  302.  
  303.         if [ -z "$(echo  "$VPN_ROUTES" | grep -oF "\-${AROUTE}" )" ];then
  304.             if [ "$VPN_TAB" != "254" ];then
  305.                 if [ ! -z "$AROUTE" ];then
  306.                     VPN_ROUTES=$VPN_ROUTES" "${VPN_TAB:2:1}-${AROUTE}
  307.                 fi
  308.             else
  309.                 VPN_ROUTES=$VPN_ROUTES" 0-"$AROUTE
  310.             fi
  311.         else
  312.             echo -en $cBRED"\a"
  313.             TXT="ALREADY used by VPN Client "$(echo  "$VPN_ROUTES" | grep -oE "${AROUTE}\-[1-5]+" | cut -d'-' -f2)
  314.             if [ "$WAN_IP" == "$AROUTE" ];then
  315.                 TXT="is via the WAN!!!"
  316.             fi
  317.             Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "route" $AROUTE $TXT
  318.             echo -en $cRESET
  319.         fi
  320.  
  321.         # Check default route matches this VPN Client
  322.         #   default via xxx.xxx.xxx.xxx dev tunXX
  323.         if [ "$VPN_TAB" != "254" ];then
  324.             DEV=$(ip route show table $VPN_TAB | awk ' /default/ {print $5}')
  325.  
  326.             if [ "tun1"${VPN_TAB:2:1} != "$DEV" ];then
  327.                 if [ ! -z "$DEV" ];then
  328.                     echo -en $cBRED"\a"
  329.                     Say "***ERROR*** RPDB rules will be misdirected for VPN Client" ${VPN_TAB:2:1} "via" $DEV
  330.                     echo -en $cRESET
  331.                 fi
  332.             fi
  333.             # Check for either of these in this VPN Client but it's OK if ONLY 1 VPN Client ACTIVE!
  334.             #   0.0.0.0/1 via xxx.xxx.xxx.xxx dev tunXX
  335.             #   128.0.0.0/1 via xxx.xxx.xxx.xxx dev tunXX
  336.             MULTI_DEFAULT=$(ip route show table $VPN_TAB | grep -E -m 1 "^0\.|^128.")
  337.             if [ ! -z "$MULTI_DEFAULT" ];then
  338.                 MULTI_FOUND=$MULTI_FOUND" "${VPN_TAB:2:1}
  339.  
  340.                 if [ $ACTIVE_VPN_CNT -gt 1 ];then
  341.                     echo -en $cBRED"\a"
  342.                 else
  343.                     echo -en $cBYEL"\a"
  344.                 fi
  345.                 # If there is no 'default' rule then probably means Server did not push 'redirect-gateway def1',
  346.                 #    so advise adding it to Client Configuration?
  347.                 RGWTXT=
  348.                 if [ $NODEFAULT -eq 1 ];then
  349.                     RGWTXT="but pushed 'redirect-gateway def1' missing? Add to GUI Client Config???"
  350.                 fi
  351.                 # If device in 0.0.0.0/1 or 128.0.0.0/1 doesn't match this current dev tunXX
  352.                 if [ "$(echo $MULTI_DEFAULT | grep -v "dev tun1${VPN_TAB:2:1}")" ];then
  353.                     Say "***ERROR*** '"$MULTI_DEFAULT"' will misdirect VPN Client" ${VPN_TAB:2:1} "via wrong VPN Client"
  354.                 else
  355.                     Say "**Warning '"$MULTI_DEFAULT"' found in VPN Client" ${VPN_TAB:2:1} $RGWTXT
  356.                 fi
  357.                 echo -en $cRESET
  358.  
  359.             fi
  360.  
  361.             # Can 'prohibit default' exist if VPN is UP..?? - YES if 'Redirect Internet traffic=ALL' ???
  362.             if [ ! -z "$(ip route show table $VPN_TAB | grep "prohibit default")" ];then
  363.                 echo -en $cYEL"\a"
  364.                 Say "**Warning RPDB routing traffic is BLOCKED - ('prohibit default') for VPN Client" ${VPN_TAB:2:1}
  365.                 echo -en $cRESET
  366.             fi
  367.  
  368.             VPN_PUBLIC_IP=$(ChkVPNIP "${VPN_TAB:2:1}")
  369.  
  370.             if [ ! -z "$VPN_PUBLIC_IP" ];then
  371.                 echo -e $cBGRE
  372.                 Say "VPN Client" ${VPN_TAB:2:1} "Public IP address is" $VPN_PUBLIC_IP
  373.                 echo -en $cRESET
  374.             else
  375.                 echo -e $cRED"\a"
  376.                 Say "**Warning VPN Client" ${VPN_TAB:2:1} "Public IP address NOT found (NOTE: Free VPNBook is ALWAYS 'NULL')"
  377.                 echo -en $cRESET
  378.             fi
  379.  
  380.             # Perform a data transfer if requested
  381.             if [ $DATA_TRANSFER -eq 1 ];then
  382.                 Data_Transfer ${VPN_TAB:2:1}
  383.             fi
  384.            
  385.             CheckDNS ${VPN_TAB:2:1}
  386.  
  387.         else
  388.             WAN_IP=$AROUTE
  389.             # Check if WAN IP is private indicating ASUS is behind another router....
  390.             if [ ! -z "$(echo $WAN_IP | Is_Private_IPv4)" ];then
  391.                 echo -en $cRED"\a"
  392.                 Say "**Warning WAN IP address" $WAN_IP "is Private - is Asus router behind an ISP modem?"
  393.                 echo -en $cRESET
  394.             else
  395.             echo -e $cBGRE
  396.             Say "WAN Public IP info -->" $(curl --connect-timeout 5 -s ipinfo.io)
  397.             echo -en $cRESET
  398.             fi
  399.             # Check if pushed VPN override routes are still present in table main
  400.             MULTI_DEFAULT=$(ip route show table $VPN_TAB | grep -E -m 1 "^0\.|^128.")
  401.             if [ ! -z "$MULTI_DEFAULT" ];then
  402.                 echo -en $cBRED"\a"
  403.                 Say "***ERROR*** Selective Routing NOT enabled! - table 'main' is FORCE routing ALL traffic via VPN Client" $(echo $MULTI_DEFAULT | awk '{print $5}' | sed 's/tun1//')
  404.                 echo -en $cRESET
  405.             fi
  406.         fi
  407.     done
  408.  
  409. echo -e $cBWHT
  410. Say "RPDB rules:"
  411. echo -en $cBCYA
  412. ip rule;ip rule >>/tmp/syslog.log
  413.  
  414. echo -e $cBWHT
  415. Say "Count of active GUI LAN (devices/subnets) RPDB rules:"
  416. echo -en $cBGRE
  417.  
  418. # How many GUI entities Selectively routed? i.e. ignore any fwmark (IPSETs etc.) and ^20X00 are the WiFiVPN rules?
  419. ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20"  | sed 's/^.*lookup //' | sort | uniq -c
  420. ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20"  | sed 's/^.*lookup //' | sort | uniq -c >>/tmp/syslog.log
  421.  
  422. echo -e $cBWHT
  423. Say "Count of WiFi SSIDs mapped to VPN RPDB rules:"
  424. echo -en $cBMAG
  425. ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^10"  | sed 's/^.*lookup //' | sort | uniq -c
  426.  
  427. echo -e $cBWHT
  428. Say "Advanced Routing fwmark RPDB rules:"
  429. echo -en $cBYEL
  430. ip rule | grep -E "fwmark" | sed 's/^.*all //' | uniq -c
  431.  
  432. SayT "Summary:$(ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20"  | sed 's/^.*lookup //' | sort | uniq -c)"
  433.  
  434. SayT "VPNRoutes:"$VPN_ROUTES
  435.  
  436. PORTS="$(Check_DuplicateVPNPorts "2")"          # Only interested in ACTIVE VPN Clients (state="2") rather than any configured
  437. if [ ! -z $PORTS ];then
  438.     echo -e "\n"$cYEL
  439.     Say "**Warning for multiple ACTIVE concurrent VPN Clients UNIQUE ports are advised - Port" $PORTS "is configured for use by several VPN Clients"
  440. fi
  441.  
  442.  
  443. # grep "***ERROR" /tmp/syslog.log
  444. #      10:57:17 (ChkVPNConfig.sh): 12149 ***ERROR*** RPDB rules will be misdirected for VPN Client 5 via eth0
  445. #      10:58:05 (ChkVPNConfig.sh): 12433 ***ERROR*** Selective Routing NOT enabled! - table 'main' is FORCE routing ALL traffic via VPN Client 2
  446.  
  447. if [ ! -z "$(grep -io -m 1 "conflicting routing rule" /tmp/syslog.log)" ];then
  448.     echo -e "\n"$cYEL
  449.     Say "**Warning possible VPN routing conflict? - Check use of alternative VPN protocol/port or MAX VPN ISP multiple concurrent connections"
  450. fi
  451.  
  452. echo -e $cRESET
  453.  
  454. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement