Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- VER="v1.01b14"
- #============================================================================== © 2018 Martineau, v01.01b14
- #
- # Check VPN Selective routing configuration.
- #
- # Schedule via cru/cron to have the VPN status tracked/dumped to Syslog.
- #
- # ChkVPNConfig [-h|help] [ all ] [ curldata]
- #
- # ChkVPNConfig
- # Check only the currently ACTIVE VPN Client connections
- # ChkVPNConfig all
- # Check all VPN Client connections
- # ChkVPNConfig curldata
- # For each ACTIVE VPN Client attempt a 12MB data download
- # [URL="https://www.snbforums.com/threads/multiple-vpn-clients-active-for-different-devices.40674/#post-379572"]Multiple VPN clients active for different devices[/URL]
- #*=====================================Functions=====================================================
- # Print between line beginning with'#==' to first blank line inclusive
- ShowHelp() {
- echo -en $cBWHT >&2
- awk '/^#==/{f=1} f{print; if (!NF) exit}' $0
- echo -en $cRESET >&2
- }
- Say(){
- echo -e $$ $@ | logger -st "($(basename $0))"
- }
- SayT(){
- echo -e $$ $@ | logger -t "($(basename $0))"
- }
- ANSIColours() {
- 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"
- cBGRA="\e[90m";cBRED="\e[91m";cBGRE="\e[92m";cBYEL="\e[93m";cBBLU="\e[94m";cBMAG="\e[95m";cBCYA="\e[96m";cBWHT="\e[97m"
- aBOLD="\e[1m";aDIM="\e[2m";aUNDER="\e[4m";aBLINK="\e[5m";aREVERSE="\e[7m"
- cRED_="\e[41m";cGRE_="\e[42m"
- }
- Chain_exists() {
- # Args: {chain_name} [table_name]
- local CHAIN="$1"
- shift
- [ $# -eq 1 ] && local TABLE="-t $1"
- iptables $TABLE -n -L $CHAIN >/dev/null 2>&1
- local RC=$?
- if [ $RC -ne 0 ];then
- echo "N"
- return 1
- else
- echo "Y"
- return 0
- fi
- }
- Check_DuplicateVPNPorts() {
- local VPN_ID=
- local VPN_ADDR=
- local VPN_PORTS=
- local VPN_ID_LIST="1 2 3 4 5"
- #local VPN_CLIENTPORTS=$(nvram show 2> /dev/null | grep -E "vpn_client.*port" | grep -v "client_port")
- for VPN_ID in $VPN_ID_LIST
- do
- VPN_ADDR=$(nvram get vpn_client${VPN_ID}_addr)
- if [ -z "$VPN_ADDR" ];then
- continue # VPN Client instance not configured?
- fi
- # vpn_client1_port=553
- # vpn_client1_proto=udp
- if [ "$1" == "2" ];then
- local VPN_STATE=$(nvram get "vpn_client"$VPN_ID"_state")
- if [ "$VPN_STATE" != "2" ];then
- continue
- fi
- fi
- local THIS=$(echo $(nvram get vpn_client${VPN_ID}_port)":"$(nvram get vpn_client${VPN_ID}_proto | tr "a-z" "A-Z") )
- if [ "$2" == "diag" ];then
- local VPN_PORTS=$( echo -e "$VPN_PORTS VPN client" $VPN_ID "ACTIVE using port" $THIS", ")
- else
- local VPN_PORTS=$(echo -e "$VPN_PORTS ${THIS}\n")
- fi
- done
- if [ "$2" != "diag" ];then
- # Convert words to individual lines and report on duplicates
- echo $VPN_PORTS | tr ' ' '\n' | sort -n | uniq -d
- else
- echo $VPN_PORTS
- fi
- }
- ChkVPNIP() {
- local RESULT=0
- local VPN_ID=$1
- if [ -f /usr/sbin/gettunnelip.sh ];then
- sh /usr/sbin/gettunnelip.sh ${VPN_ID}
- local VPN_WANIP="$(nvram get vpn_client${VPN_ID}_rip)"
- fi
- if [ -z "$VPN_WANIP" ];then
- local VPN_WANIP=$(curl --connect-timeout 5 -s --interface "tun1"${VPN_ID} "http://ipecho.net/plain")
- fi
- local IPINFOIO=$(curl --connect-timeout 5 -s --interface "tun1"${VPN_ID} ipinfo.io)
- if [ ! -z "$VPN_WANIP" ];then
- local RESULT=0
- else
- local RESULT=1
- fi
- echo -e $VPN_WANIP" --> "$IPINFOIO
- return $RESULT
- }
- Is_Private_IPv4() {
- grep -oE "(^127\.)|(^(0)?10\.)|(^172\.(0)?1[6-9]\.)|(^172\.(0)?2[0-9]\.)|(^172\.(0)?3[0-1]\.)|(^169\.254\.)|(^192\.168\.)"
- }
- Is_Private_IPv6 () {
- grep -oE "(::1$)|([fF][cCdD])"
- }
- Data_Transfer() {
- local VPN_ID=$1
- # FORCE a small data transfer retrieval to confirm?
- if [ -z "$2" ];then
- echo -en $cBWHT"\n"
- Say "Starting curl data transfer.....(Expect 12MB approx @3.1MB/sec on 20Mbps download = 00:04 secs)"
- echo -en $cBYEL
- fi
- echo -en $cBBLU
- WGET_DATA="http://proof.ovh.net/files/100Mb.dat"
- curl --interface tun1${VPN_ID} -o /dev/null $WGET_DATA
- RC=$?
- if [ $RC -eq 0 ];then
- local STATUS=1
- else
- echo -en $cBRED
- Say "***ERROR curl '"$WGET_DATA"' transfer FAILED RC="$RC
- if [ $RC -ne 8 ];then
- local STATUS=0 # Override PING/curl status!!
- else
- Say "*Warning curl '"$WGET_DATA"' URL invalid?" # URL invalid so could be OFFLINE so ignore it
- fi
- fi
- return $STATUS
- }
- CheckDNS() {
- local RESULT=0
- local VPN_ID=$1
- local ETC="etc"
- echo -e $cBWHT
- Say "VPN Client" ${VPN_TAB:2:1} "DNS config"
- if [ -f "/${ETC}/openvpn/dns/client${VPN_ID}.resolv" ];then
- echo -en $cBGRE
- echo -e "'/${ETC}/openvpn/dns/client${VPN_ID}.resolv'"
- cat "/${ETC}/openvpn/dns/client${VPN_ID}.resolv"
- echo -e
- fi
- echo -en $cBGRE
- if [ -f "/${ETC}/openvpn/client${VPN_ID}/config.ovpn" ];then
- Say "VPN Client" ${VPN_TAB:2:1} "Using DNS $(grep -E "^dhcp-option.*DNS" /${ETC}/openvpn/client${VPN_ID}/config.ovpn | awk '{print $3}')"
- fi
- if [ "$(Chain_exists "DNSVPN${VPN_ID}" "nat")" == "Y" ];then
- echo -en $cBGRE
- Say "VPN Client" ${VPN_TAB:2:1} "EXCLUSIVE DNSVPN${VPN_ID} chain configuration:"
- iptables --line -t nat -nvL DNSVPN${VPN_ID} 2>/dev/null
- else
- echo -en $cBLU
- Say "VPN Client" ${VPN_TAB:2:1} "EXCLUSIVE DNSVPN${VPN_ID} chain NOT enabled."
- fi
- }
- #============================================Main==================================================
- ANSIColours
- # Provide assistance
- if [ "$1" = "-h" ] || [ "$1" = "help" ]; then
- ShowHelp # Show help
- exit 0
- fi
- echo -e $cBWHT
- Say $VER "VPN Selective Routing configuration checker ....."
- VPN_ROUTES=
- WAN_IP=
- MULTI_FOUND=
- VPN_LIST=$(ip route show table 254 | grep -oE "tun1[1-5]" | sort | uniq )
- ACTIVE_VPN_CNT=$(ip route show table 254 | grep -oE "tun1[1-5]" | wc -w)
- CHECKALL=0 # Only check ACTIVE VPN configurations
- if [ $(echo $@ | grep -cw "all") -gt 0 ];then
- CHECKALL=1
- VPN_LIST="111 112 113 114 115" # 'all' directive found; Check all VPNs
- fi
- DATA_TRANSFER=0 # Don't perform the 12MB curl data transfer
- if [ $(echo $@ | grep -cw "curldata") -gt 0 ];then
- DATA_TRANSFER=1
- fi
- for VPN_TAB in 254 $VPN_LIST
- do
- NODEFAULT=0
- [ "$VPN_TAB" != "254" ] && VPN_TAB=$(echo $VPN_TAB | sed 's/tun1/11/')
- echo -e $cBWHT
- if [ "$VPN_TAB" != "254" ];then
- KILLTXT=
- if [ "$(nvram get vpn_client${VPN_TAB:2:1}_enforce)" == "1" ];then
- KILLTXT="(VPN KILL switch Protection ENABLED)"
- fi
- Say "VPN Client" ${VPN_TAB:2:1} "route Table:" $VPN_TAB $KILLTXT
- else
- Say "WAN (main) route Table:" $VPN_TAB
- fi
- echo -en $cBCYA
- AROUTE=$(ip route show table $VPN_TAB | awk ' /default/ {print $3}')
- # Obfuscate IP address(s)?
- #ip route show table $VPN_TAB | grep -E "^0\.|^128.|^default|^prohibit|tun1" | ObfuscateIP | ObfuscateCIDR
- ip route show table $VPN_TAB | grep -E "^0\.|^128.|^default|^prohibit|tun1"
- ip route show table $VPN_TAB | grep -E "^0\.|^128.|^default|^prohibit|tun1" >>/tmp/syslog.log
- echo -e
- if [ -z "$AROUTE" ];then # No 'default'?
- if [ "$VPN_TAB" != "254" ];then
- if [ ! -z "$(nvram get vpn_client${VPN_TAB:2:1}_addr)" ];then # Configured ?
- VPN_FORCE=$(nvram get vpn_client${VPN_TAB:2:1}_enforce) # Block if VPN DOWN=YES
- NODEFAULT=1 # No 'default'; but it's OK if there is 'prohibit default'
- if [ -z "$(ip route show table $VPN_TAB | awk ' /prohibit/ {print $1}')" ];then
- if [ "$VPN_FORCE" == "1" ];then
- if [ "$(nvram get vpn_client${VPN_TAB:2:1}_state)" != "2" ];then
- echo -en $cBRED"\a"
- Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "is missing KILL-switch 'prohibit default' - current WAN leak!"
- else
- echo -en $cBRED"\a"
- Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "has no DEFAULT route and is ACTIVE - WAN leak!"
- fi
- else
- if [ ! -z "$(ip route show table $VPN_TAB)" ];then # Is table isn't empty
- echo -en $cBRED"\a"
- Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "has no DEFAULT route"
- else
- STATE=$(nvram get vpn_client${VPN_TAB:2:1}_state)
- if [ "$STATE" == "0" ];then
- echo -en $cGRE
- #Say "VPN Client" ${VPN_TAB:2:1} "is OK"
- else
- echo -en $cRED"\a"
- Say "**Warning VPN Client" ${VPN_TAB:2:1} "is in STATE="$STATE
- fi
- fi
- fi
- fi
- # Is there one of my custom WiFi->VPN map rule 20?00 rules
- if [ "$VPN_FORCE" == "1" ];then
- if [ ! -z "$(ip rule | grep "^20${VPN_TAB:2:1}00")" ] && [ -z "$(ip route show table $VPN_TAB | awk ' /prohibit/ {print $1}')" ];then
- echo -en $cBRED"\a"
- Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "is missing KILL-switch 'prohibit default' - WAN leak!"
- fi
- fi
- else
- echo -en $cBLU
- Say "VPN Client" ${VPN_TAB:2:1} "NOT configured".
- fi
- else
- # Should ALWAYS have even if 0.0.0.0/1 or 128.0.0.0/1 are present
- Say "***ERROR*** Main routing table has no DEFAULT route"
- fi
- echo -en $cRESET
- fi
- if [ -z "$(echo "$VPN_ROUTES" | grep -oF "\-${AROUTE}" )" ];then
- if [ "$VPN_TAB" != "254" ];then
- if [ ! -z "$AROUTE" ];then
- VPN_ROUTES=$VPN_ROUTES" "${VPN_TAB:2:1}-${AROUTE}
- fi
- else
- VPN_ROUTES=$VPN_ROUTES" 0-"$AROUTE
- fi
- else
- echo -en $cBRED"\a"
- TXT="ALREADY used by VPN Client "$(echo "$VPN_ROUTES" | grep -oE "${AROUTE}\-[1-5]+" | cut -d'-' -f2)
- if [ "$WAN_IP" == "$AROUTE" ];then
- TXT="is via the WAN!!!"
- fi
- Say "***ERROR*** VPN Client" ${VPN_TAB:2:1} "route" $AROUTE $TXT
- echo -en $cRESET
- fi
- # Check default route matches this VPN Client
- # default via xxx.xxx.xxx.xxx dev tunXX
- if [ "$VPN_TAB" != "254" ];then
- DEV=$(ip route show table $VPN_TAB | awk ' /default/ {print $5}')
- if [ "tun1"${VPN_TAB:2:1} != "$DEV" ];then
- if [ ! -z "$DEV" ];then
- echo -en $cBRED"\a"
- Say "***ERROR*** RPDB rules will be misdirected for VPN Client" ${VPN_TAB:2:1} "via" $DEV
- echo -en $cRESET
- fi
- fi
- # Check for either of these in this VPN Client but it's OK if ONLY 1 VPN Client ACTIVE!
- # 0.0.0.0/1 via xxx.xxx.xxx.xxx dev tunXX
- # 128.0.0.0/1 via xxx.xxx.xxx.xxx dev tunXX
- MULTI_DEFAULT=$(ip route show table $VPN_TAB | grep -E -m 1 "^0\.|^128.")
- if [ ! -z "$MULTI_DEFAULT" ];then
- MULTI_FOUND=$MULTI_FOUND" "${VPN_TAB:2:1}
- if [ $ACTIVE_VPN_CNT -gt 1 ];then
- echo -en $cBRED"\a"
- else
- echo -en $cBYEL"\a"
- fi
- # If there is no 'default' rule then probably means Server did not push 'redirect-gateway def1',
- # so advise adding it to Client Configuration?
- RGWTXT=
- if [ $NODEFAULT -eq 1 ];then
- RGWTXT="but pushed 'redirect-gateway def1' missing? Add to GUI Client Config???"
- fi
- # If device in 0.0.0.0/1 or 128.0.0.0/1 doesn't match this current dev tunXX
- if [ "$(echo $MULTI_DEFAULT | grep -v "dev tun1${VPN_TAB:2:1}")" ];then
- Say "***ERROR*** '"$MULTI_DEFAULT"' will misdirect VPN Client" ${VPN_TAB:2:1} "via wrong VPN Client"
- else
- Say "**Warning '"$MULTI_DEFAULT"' found in VPN Client" ${VPN_TAB:2:1} $RGWTXT
- fi
- echo -en $cRESET
- fi
- # Can 'prohibit default' exist if VPN is UP..?? - YES if 'Redirect Internet traffic=ALL' ???
- if [ ! -z "$(ip route show table $VPN_TAB | grep "prohibit default")" ];then
- echo -en $cYEL"\a"
- Say "**Warning RPDB routing traffic is BLOCKED - ('prohibit default') for VPN Client" ${VPN_TAB:2:1}
- echo -en $cRESET
- fi
- VPN_PUBLIC_IP=$(ChkVPNIP "${VPN_TAB:2:1}")
- if [ ! -z "$VPN_PUBLIC_IP" ];then
- echo -e $cBGRE
- Say "VPN Client" ${VPN_TAB:2:1} "Public IP address is" $VPN_PUBLIC_IP
- echo -en $cRESET
- else
- echo -e $cRED"\a"
- Say "**Warning VPN Client" ${VPN_TAB:2:1} "Public IP address NOT found (NOTE: Free VPNBook is ALWAYS 'NULL')"
- echo -en $cRESET
- fi
- # Perform a data transfer if requested
- if [ $DATA_TRANSFER -eq 1 ];then
- Data_Transfer ${VPN_TAB:2:1}
- fi
- CheckDNS ${VPN_TAB:2:1}
- else
- WAN_IP=$AROUTE
- # Check if WAN IP is private indicating ASUS is behind another router....
- if [ ! -z "$(echo $WAN_IP | Is_Private_IPv4)" ];then
- echo -en $cRED"\a"
- Say "**Warning WAN IP address" $WAN_IP "is Private - is Asus router behind an ISP modem?"
- echo -en $cRESET
- else
- echo -e $cBGRE
- Say "WAN Public IP info -->" $(curl --connect-timeout 5 -s ipinfo.io)
- echo -en $cRESET
- fi
- # Check if pushed VPN override routes are still present in table main
- MULTI_DEFAULT=$(ip route show table $VPN_TAB | grep -E -m 1 "^0\.|^128.")
- if [ ! -z "$MULTI_DEFAULT" ];then
- echo -en $cBRED"\a"
- 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//')
- echo -en $cRESET
- fi
- fi
- done
- echo -e $cBWHT
- Say "RPDB rules:"
- echo -en $cBCYA
- ip rule;ip rule >>/tmp/syslog.log
- echo -e $cBWHT
- Say "Count of active GUI LAN (devices/subnets) RPDB rules:"
- echo -en $cBGRE
- # How many GUI entities Selectively routed? i.e. ignore any fwmark (IPSETs etc.) and ^20X00 are the WiFiVPN rules?
- ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20" | sed 's/^.*lookup //' | sort | uniq -c
- ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20" | sed 's/^.*lookup //' | sort | uniq -c >>/tmp/syslog.log
- echo -e $cBWHT
- Say "Count of WiFi SSIDs mapped to VPN RPDB rules:"
- echo -en $cBMAG
- ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^10" | sed 's/^.*lookup //' | sort | uniq -c
- echo -e $cBWHT
- Say "Advanced Routing fwmark RPDB rules:"
- echo -en $cBYEL
- ip rule | grep -E "fwmark" | sed 's/^.*all //' | uniq -c
- SayT "Summary:$(ip rule | grep -vE "fwmark" | grep -vE "local|default|^32766|^20" | sed 's/^.*lookup //' | sort | uniq -c)"
- SayT "VPNRoutes:"$VPN_ROUTES
- PORTS="$(Check_DuplicateVPNPorts "2")" # Only interested in ACTIVE VPN Clients (state="2") rather than any configured
- if [ ! -z $PORTS ];then
- echo -e "\n"$cYEL
- Say "**Warning for multiple ACTIVE concurrent VPN Clients UNIQUE ports are advised - Port" $PORTS "is configured for use by several VPN Clients"
- fi
- # grep "***ERROR" /tmp/syslog.log
- # 10:57:17 (ChkVPNConfig.sh): 12149 ***ERROR*** RPDB rules will be misdirected for VPN Client 5 via eth0
- # 10:58:05 (ChkVPNConfig.sh): 12433 ***ERROR*** Selective Routing NOT enabled! - table 'main' is FORCE routing ALL traffic via VPN Client 2
- if [ ! -z "$(grep -io -m 1 "conflicting routing rule" /tmp/syslog.log)" ];then
- echo -e "\n"$cYEL
- Say "**Warning possible VPN routing conflict? - Check use of alternative VPN protocol/port or MAX VPN ISP multiple concurrent connections"
- fi
- echo -e $cRESET
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement