diff --git a/README.md b/README.md
index 742370f..75d9bf3 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# VPNMON-R3 v1.6.1
+# VPNMON-R3 v1.6.2
Asus-Merlin OpenVPN/Wireguard Monitor R3
-Updated on 2025-Aug-23
+Updated on 2025-Aug-24
---
diff --git a/vpnmon-r3-1.6.0.sh b/archive/vpnmon-r3-1.6.0.sh
similarity index 100%
rename from vpnmon-r3-1.6.0.sh
rename to archive/vpnmon-r3-1.6.0.sh
diff --git a/changelog.txt b/changelog.txt
index b2b77a1..ef72001 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,8 @@
+v1.6.2 - (August 24, 2025)
+ - PATCH: Apologies for the successive bug fix patches, but found another one stemming from an Unbound
+ variable that was not being reset, and causing the [UB] indicator to show up on slots that weren't
+ designated as Unbound slots.
+
v1.6.1 - (August 23, 2025)
- PATCH: Small bug fix to prevent "Invalid WG PING Information" log errors from coming through even if
WG functionality was not enabled. Thanks much to @scootertramp for reporting this issue!
diff --git a/version.txt b/version.txt
index 9c6d629..fdd3be6 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.6.1
+1.6.2
diff --git a/vpnmon-r3-1.6.1.sh b/vpnmon-r3-1.6.1.sh
new file mode 100644
index 0000000..ed47949
--- /dev/null
+++ b/vpnmon-r3-1.6.1.sh
@@ -0,0 +1,6845 @@
+#!/bin/sh
+
+# VPNMON-R3 v1.6.1 (VPNMON-R3.SH) is an all-in-one script that is optimized to maintain multiple VPN connections and is
+# able to provide for the capabilities to randomly reconnect using a specified server list containing the servers of your
+# choice. Special care has been taken to ensure that only the VPN connections you want to have monitored are tended to.
+# This script will check the health of up to 5 VPN connections on a regular interval to see if monitored VPN conenctions
+# are connected, and sends a ping to a host of your choice through each active connection. If it finds that a connection
+# has been lost, it will execute a series of commands that will kill that single VPN client, and randomly picks one of
+# your specified servers to reconnect to for each VPN client.
+# Last Modified: 2025-Aug-23
+##########################################################################################
+
+#Preferred standard router binaries path
+export PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"
+
+#Static Variables - please do not change
+version="1.6.1" # Version tracker
+beta=0 # Beta switch
+screenshotmode=0 # Switch to present bogus info for screenshots
+apppath="/jffs/scripts/vpnmon-r3.sh" # Static path to the app
+logfile="/jffs/addons/vpnmon-r3.d/vpnmon-r3.log" # Static path to the log
+dlverpath="/jffs/addons/vpnmon-r3.d/version.txt" # Static path to the version file
+config="/jffs/addons/vpnmon-r3.d/vpnmon-r3.cfg" # Static path to the config file
+lockfile="/jffs/addons/vpnmon-r3.d/resetlock.txt" # Static path to the reset lock file
+vr3emails="/jffs/addons/vpnmon-r3.d/vr3emails.txt" # Static path to email rate limit file
+availableslots="1 2 3 4 5" # Available slots tracker
+logsize=2000 # Log file size in rows
+timerloop=60 # Timer loop in sec
+recover=3 # Number of loops to allow for connection recovery
+schedule=0 # Scheduler enable y/n
+schedulehrs=1 # Scheduler hours
+schedulemin=0 # Scheduler mins
+autostart=0 # Auto start on router reboot y/n
+unboundclient=0 # Unbound bound to VPN client slot#
+unboundwgclient=0 # Unbound bound to WG client slot#
+unboundshowip=0 # Show expanded Unbound VPN IP on UI
+ResolverTimer=1 # Timer to give DNS resolver time to settle
+vpnping=0 # Tracking VPN Tunnel Pings
+refreshserverlists=0 # Tracking Automated Custom VPN Server List Reset
+monitorwan=0 # Tracking WAN/Dual WAN Monitoring
+useovpn=1 # Tracking OVPN Display/Monitoring
+usewg=1 # Tracking WG Display/Monitoring
+lockactive=0 # Check for active locks
+bypassscreentimer=0 # Check to see if screen timer can be bypassed
+pingreset=500 # Maximum ping in ms before reset
+updateskynet=0 # Check for VPN IP whitelisting in Skynet
+amtmemailsuccess=0 # AMTM Email Success Message Option
+amtmemailfailure=0 # AMTM Email Failure Message Option
+rstspdmerlin=0 # Reset spdMerlin Interfaces Option
+timeoutcmd="" # For "timeout" cmd for "nvram" calls
+timeoutsec="" # For "timeout" cmd for "nvram" calls
+timeoutlng="" # For "timeout" cmd for "nvram" calls
+hideoptions=1 # Hide/Show menu options flag
+ratelimit=0 # Rate limiting number of emails/houre
+vrcnt=0 # Counter for VPN connection recovery
+wrcnt=0 # Counter for WG connection recovery
+
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Oct-05] ##
+##-------------------------------------##
+readonly PING_HOST_Deflt="8.8.8.8"
+readonly IPv4octet_RegEx="([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
+readonly IPv4addrs_RegEx="(${IPv4octet_RegEx}\.){3}${IPv4octet_RegEx}"
+LAN_HostName=""
+prevHideOpts=X # Avoid redisplaying the menu options unnecessarily too often #
+
+PINGHOST="$PING_HOST_Deflt" # Ping host
+
+## Custom Email Library Notification Variables ##
+readonly scriptFileName="${0##*/}"
+readonly scriptFileNTag="${scriptFileName%.*}"
+readonly CEM_LIB_TAG="master"
+readonly CEM_LIB_URL="https://raw.githubusercontent.com/Martinski4GitHub/CustomMiscUtils/${CEM_LIB_TAG}/EMail"
+readonly CUSTOM_EMAIL_LIBDir="/jffs/addons/shared-libs"
+readonly CUSTOM_EMAIL_LIBName="CustomEMailFunctions.lib.sh"
+readonly CUSTOM_EMAIL_LIBFile="${CUSTOM_EMAIL_LIBDir}/$CUSTOM_EMAIL_LIBName"
+
+# Color variables
+CBlack="\e[1;30m"
+InvBlack="\e[1;40m"
+CRed="\e[1;31m"
+InvRed="\e[1;41m"
+CGreen="\e[1;32m"
+InvGreen="\e[1;42m"
+CDkGray="\e[1;90m"
+InvDkGray="\e[1;100m"
+InvLtGray="\e[1;47m"
+CYellow="\e[1;33m"
+InvYellow="\e[1;43m"
+CBlue="\e[1;34m"
+InvBlue="\e[1;44m"
+CMagenta="\e[1;35m"
+CCyan="\e[1;36m"
+InvCyan="\e[1;46m"
+CWhite="\e[1;37m"
+InvWhite="\e[1;107m"
+CClear="\e[0m"
+
+# -------------------------------------------------------------------------------------------------------------------------
+# blackwhite is a simple function that removes all color attributes
+blackwhite()
+{
+
+CBlack=""
+InvBlack=""
+CRed=""
+InvRed=""
+CGreen=""
+InvGreen=""
+CDkGray=""
+InvDkGray=""
+InvLtGray=""
+CYellow=""
+InvYellow=""
+CBlue=""
+InvBlue=""
+CMagenta=""
+CCyan=""
+InvCyan=""
+CWhite=""
+InvWhite=""
+CClear=""
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# LogoNM is a function that displays the VPNMON-R3 script name in a cool ASCII font without menu options
+
+logoNM () {
+ clear
+ echo ""
+ echo ""
+ echo ""
+ echo -e "${CDkGray} _ ______ _ ____ _______ _ __ ____ _____"
+ echo -e " | | / / __ \/ | / / |/ / __ \/ | / / / __ \__ /"
+ echo -e " | | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ //_ < "
+ echo -e " | |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/__/ / "
+ echo -e " |___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ v$version"
+ echo ""
+ echo ""
+ printf "\r ${CGreen} [ INITIALIZING ] ${CClear}"
+ sleep 2
+ clear
+ echo ""
+ echo ""
+ echo ""
+ echo -e "${CYellow} _ ______ _ ____ _______ _ __ ____ _____"
+ echo -e " | | / / __ \/ | / / |/ / __ \/ | / / / __ \__ /"
+ echo -e " | | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ //_ < "
+ echo -e " | |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/__/ / "
+ echo -e " |___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ v$version"
+ echo ""
+ echo ""
+ printf "\r ${CGreen}[ INITIALIZING ... DONE ]${CClear}"
+ sleep 1
+ printf "\r ${CGreen} [ LOADING... ] ${CClear}"
+ sleep 2
+}
+
+logoNMexit () {
+ clear
+ echo ""
+ echo ""
+ echo ""
+ echo -e "${CYellow} _ ______ _ ____ _______ _ __ ____ _____"
+ echo -e " | | / / __ \/ | / / |/ / __ \/ | / / / __ \__ /"
+ echo -e " | | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ //_ < "
+ echo -e " | |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/__/ / "
+ echo -e " |___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ v$version"
+ echo ""
+ echo ""
+ printf "\r ${CGreen} [ SHUTTING DOWN ] ${CClear}"
+ sleep 2
+ clear
+ echo ""
+ echo ""
+ echo ""
+ echo -e "${CDkGray} _ ______ _ ____ _______ _ __ ____ _____"
+ echo -e " | | / / __ \/ | / / |/ / __ \/ | / / / __ \__ /"
+ echo -e " | | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ //_ < "
+ echo -e " | |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/__/ / "
+ echo -e " |___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ v$version"
+ echo ""
+ echo ""
+ printf "\r ${CGreen} [ SHUTTING DOWN ] ${CClear}"
+ sleep 1
+ printf "\r ${CDkGray} [ GOODBYE... ] ${CClear}\n\n"
+ sleep 2
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Promptyn is a simple function that accepts y/n input
+
+promptyn () { # No defaults, just y or n
+ while true; do
+ read -p '[y/n]? ' YESNO
+ case "$YESNO" in
+ [Yy]* ) return 0 ;;
+ [Nn]* ) return 1 ;;
+ * ) echo -e "\nPlease answer y or n.";;
+ esac
+ done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Spinner is a script that provides a small indicator on the screen to show script activity
+
+spinner()
+{
+ spins=$1
+
+ spin=0
+ totalspins=$((spins / 4))
+ while [ $spin -le $totalspins ]; do
+ for spinchar in / - \\ \|; do
+ printf "\r$spinchar"
+ sleep 1
+ done
+ spin=$((spin+1))
+ done
+
+ printf "\r"
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Preparebar and Progressbar is a script that provides a nice progressbar to show script activity
+##----------------------------------------##
+## Modified by Martinski W. [2024-Nov-01] ##
+##----------------------------------------##
+preparebar()
+{
+ barlen="$1"
+ barspaces="$(printf "%*s" "$1" ' ')"
+ barchars="$(printf "%*s" "$1" ' ' | tr ' ' "$2")"
+}
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Nov-02] ##
+##----------------------------------------##
+progressbaroverride()
+{
+ insertspc=" "
+ bypasswancheck=0
+
+ _GetPercent_() { printf "%.1f" "$(echo "$1" | awk "{print $1}")" ; }
+
+ if [ "$1" -eq -1 ]
+ then
+ printf "\r $barspaces\r"
+ else
+ if [ $# -gt 6 ] && [ -n "$7" ] && [ "$1" -ge "$7" ]
+ then
+ barch="$(($7*barlen/$2))"
+ barsp="$((barlen-barch))"
+ percnt="$(_GetPercent_ "(100*$1/$2)")"
+ else
+ barch="$(($1*barlen/$2))"
+ barsp="$((barlen-barch))"
+ percnt="$(_GetPercent_ "(100*$1/$2)")"
+ fi
+
+ if [ $# -gt 5 ] && [ -n "$6" ]; then AltNum="$6" ; else AltNum="$1" ; fi
+
+ if [ "$5" = "Standard" ]
+ then
+ printf " ${CWhite}${InvDkGray}%3d${4} /%5.1f%%${CClear} [${CGreen}e${CClear}=Exit] [Selection? ${InvGreen} ${CClear}${CGreen}]\r${CClear}" "$AltNum" "$percnt"
+ fi
+ fi
+
+ # Borrowed this wonderful keypress capturing mechanism from @Eibgrad... thank you! :)
+ key_press=''; read -rsn1 -t 1 key_press < "$(tty 0>&2)"
+
+ if [ "$key_press" ]
+ then
+ case "$key_press" in
+ [1]) echo ""; restartvpn 1; sendmessage 0 "VPN Reset" 1; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [2]) echo ""; restartvpn 2; sendmessage 0 "VPN Reset" 2; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [3]) echo ""; restartvpn 3; sendmessage 0 "VPN Reset" 3; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [4]) echo ""; restartvpn 4; sendmessage 0 "VPN Reset" 4; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [5]) echo ""; restartvpn 5; sendmessage 0 "VPN Reset" 5; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [6]) echo ""; restartwg 1; sendmessage 0 "WG Reset" 1; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [7]) echo ""; restartwg 2; sendmessage 0 "WG Reset" 2; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [8]) echo ""; restartwg 3; sendmessage 0 "WG Reset" 3; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [9]) echo ""; restartwg 4; sendmessage 0 "WG Reset" 4; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [0]) echo ""; restartwg 5; sendmessage 0 "WG Reset" 5; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\!]) echo ""; killunmonvpn 1; sendmessage 0 "VPN Killed" 1; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\@]) echo ""; killunmonvpn 2; sendmessage 0 "VPN Killed" 2; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\#]) echo ""; killunmonvpn 3; sendmessage 0 "VPN Killed" 3; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\$]) echo ""; killunmonvpn 4; sendmessage 0 "VPN Killed" 4; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\%]) echo ""; killunmonvpn 5; sendmessage 0 "VPN Killed" 5; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\^]) echo ""; killunmonwg 1; sendmessage 0 "WG Killed" 1; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\&]) echo ""; killunmonwg 2; sendmessage 0 "WG Killed" 2; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\-]) echo ""; killunmonwg 3; sendmessage 0 "WG Killed" 3; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\+]) echo ""; killunmonwg 4; sendmessage 0 "WG Killed" 4; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\=]) echo ""; killunmonwg 5; sendmessage 0 "WG Killed" 5; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [Aa]) autostart;;
+ [Cc]) vsetup;;
+ [Dd]) wgserverlistautomation;;
+ [Ee]) logoNMexit; echo -e "${CClear}\n"; exit 0;;
+ [Hh]) hideoptions=1 ; [ "$hideoptions" != "$prevHideOpts" ] && timerreset=1 ;;
+ [Ii]) amtmevents;;
+ [Ll]) vlogs;;
+ [Mm]) vpnslots;;
+ [Pp]) maxping;;
+ [Rr]) schedulevpnreset;;
+ [Ss]) hideoptions=0 ; [ "$hideoptions" != "$prevHideOpts" ] && timerreset=1 ;;
+ [Tt]) timerloopconfig;;
+ [Uu]) vpnserverlistautomation;;
+ [Vv]) vpnserverlistmaint;;
+ [Ww]) wgserverlistmaint;;
+ [Xx]) uninstallr2;;
+ *) ;; ##IGNORE INVALID key presses ##
+ esac
+ bypasswancheck=1
+ fi
+}
+
+progressbarpause()
+{
+ insertspc=" "
+ bypasswancheck=0
+
+ if [ "$1" -eq -1 ]
+ then
+ printf "\r $barspaces\r"
+ else
+ if [ $# -gt 6 ] && [ -n "$7" ] && [ "$1" -ge "$7" ]
+ then
+ barch="$(($7*barlen/$2))"
+ barsp="$((barlen-barch))"
+ progr="$((100*$1/$2))"
+ else
+ barch="$(($1*barlen/$2))"
+ barsp="$((barlen-barch))"
+ progr="$((100*$1/$2))"
+ fi
+
+ if [ $# -gt 5 ] && [ -n "$6" ]; then AltNum="$6" ; else AltNum="$1" ; fi
+
+ if [ "$5" = "Standard" ]
+ then
+ printf " ${CWhite}${InvDkGray}Continuing Reset in $AltNum/5...${CClear} [${CGreen}p${CClear}=Pause] [${CGreen}e${CClear}=Exit] [Selection? ${InvGreen} ${CClear}${CGreen}]\r${CClear}" "$barchars" "$barspaces"
+ fi
+ fi
+
+ # Borrowed this wonderful keypress capturing mechanism from @Eibgrad... thank you! :)
+ key_press=''; read -rsn1 -t 1 key_press < "$(tty 0>&2)"
+
+ if [ $key_press ]
+ then
+ case $key_press in
+ [Pp]) vpause;;
+ [Ee]) logoNMexit; echo -e "${CClear}\n"; exit 0;;
+ esac
+ bypasswancheck=1
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# This function optionally uninstalls VPNMON-R2 if still found present on local router
+
+uninstallr2()
+{
+
+if [ -f /jffs/scripts/vpnmon-r2.sh ]
+then
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R2 Uninstall Utility ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} This utility allows you to uninstall VPNMON-R2. NOTE: Please know that VPNMON-R2"
+ echo -e "${InvGreen} ${CClear} development is ceasing, and product support will be sunset in the very near future."
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} VPNMON-R2 was still found installed on your router. This menu gives you the option"
+ echo -e "${InvGreen} ${CClear} to launch (if needed) or uninstall the old legacy VPNMON-R2. Thank you!"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ printf "${CClear}Please select? (${CGreen}u${CClear}=UNinstall R2, ${CGreen}r${CClear}=Run R2, ${CGreen}e${CClear}=Exit)"
+ read -p ": " SelectR2
+ case $SelectR2 in
+ [Uu])
+ echo -e "\n${CClear}Please type 'Y' to validate you wish to proceed with the uninstall of VPNMON-R2.${CClear}"
+ if promptyn "(y/n): "
+ then
+ echo -e "\n${CClear}Uninstalling VPNMON-R2 components...${CClear}"
+
+ if [ "$(cat /jffs/addons/vpnmon-r2.d/vpnmon-r2.cfg | grep "UpdateUnbound" | cut -d '=' -f 2-)" = "1" ]
+ then
+ # Delete all additions made to files to enable Unbound over VPN functionality
+ echo ""
+ echo -e "\n${CClear}Unbinding Unbound from VPN..."
+ # Disable vpn functionality with Unbound
+ sh /jffs/addons/unbound/unbound_manager.sh vpn=disable >/dev/null 2>&1
+ # Remove Unbound failsafe in post-mount
+ if [ -f /jffs/scripts/post-mount ]; then
+ sed -i -e '/vpn=disable/d' /jffs/scripts/post-mount >/dev/null 2>&1
+ fi
+ # Remove Unbound VPN helper script in openvpn-event
+ if [ -f /jffs/scripts/openvpn-event ]; then
+ sed -i -e '/unbound_DNS_via_OVPN.sh/d' /jffs/scripts/openvpn-event >/dev/null 2>&1
+ fi
+ # Remove RPDB Rules added to nat-start
+ if [ -f /jffs/scripts/nat-start ]; then
+ sed -i -e '/Added by vpnmon-r2/d' /jffs/scripts/nat-start >/dev/null 2>&1
+ fi
+ # Remove the unbound_DNS_via_OVPN.sh file
+ if [ -f /jffs/addons/unbound/unbound_DNS_via_OVPN.sh ]; then
+ rm /jffs/addons/unbound/unbound_DNS_via_OVPN.sh
+ fi
+ echo -e "\n${CClear}If Unbound-over-VPN is enabled on VPNMON-R3, you may need to disable/re-enable"
+ echo -e "this feature under the setup/configuration menu again. Conflicts may have"
+ echo -e "arisen with both products having this feature enabled."
+ fi
+
+ echo -e "\n${CClear}Removing VPNMON-R2 Files..."
+ # Remove R2 Files
+ rm -f -r /jffs/addons/vpnmon-r2.d
+ rm -f /jffs/scripts/vpnmon-r2.sh
+ if [ -f /jffs/scripts/post-mount ]; then
+ sed -i -e '/vpnmon-r2.sh/d' /jffs/scripts/post-mount >/dev/null 2>&1
+ fi
+ echo -e "\n${CClear}VPNMON-R2 has been uninstalled...${CClear}"
+ echo ""
+ read -rsp $'Press any key to continue...\n' -n1 key
+ timer="$timerloop"
+ echo -e "${CClear}\n"
+ return
+ else
+ timer="$timerloop"
+ echo -e "${CClear}\n"
+ return
+ fi
+ ;;
+
+ [Rr]) exec sh /jffs/scripts/vpnmon-r2.sh -setup; exit 0;;
+ [Ee]) timer="$timerloop" ; echo -e "${CClear}\n"; return;;
+
+ esac
+fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# This function presents an Operational Menu in a Pause state, usually during VPN slot errors which give you a 5 second
+# opportunity to pause in order to make any particular changes that might help your situation
+
+vpause()
+{
+
+while true
+do
+ if [ "$availableslots" = "1 2" ]
+ then
+ clear
+ displayopsmenu
+ printf "${CClear}Please select? (${CGreen}n${CClear}=UNpause, ${CGreen}e${CClear}=Exit)"
+ read -p ": " SelectSlot
+ case $SelectSlot in
+ [1]) echo ""; restartvpn 1; sendmessage 0 "VPN Reset" 1; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [2]) echo ""; restartvpn 2; sendmessage 0 "VPN Reset" 2; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\!]) echo ""; killunmonvpn 1; sendmessage 0 "VPN Killed" 1; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\@]) echo ""; killunmonvpn 2; sendmessage 0 "VPN Killed" 2; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [Aa]) autostart;;
+ [Cc]) vsetup;;
+ [Ee]) echo -e "${CClear}\n"; exit 0;;
+ [Ii]) amtmevents;;
+ [Ll]) vlogs;;
+ [Mm]) vpnslots;;
+ [Pp]) maxping;;
+ [Rr]) schedulevpnreset;;
+ [Tt]) timerloopconfig;;
+ [Uu]) vpnserverlistautomation;;
+ [Vv]) vpnserverlistmaint;;
+ [Nn]) exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ *) exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ esac
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ clear
+ displayopsmenu
+ printf "${CClear}Please select? (${CGreen}n${CClear}=UNpause, ${CGreen}e${CClear}=Exit)"
+ read -p ": " SelectSlot
+ case $SelectSlot in
+ [1]) echo ""; restartvpn 1; sendmessage 0 "VPN Reset" 1; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [2]) echo ""; restartvpn 2; sendmessage 0 "VPN Reset" 2; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [3]) echo ""; restartvpn 3; sendmessage 0 "VPN Reset" 3; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [4]) echo ""; restartvpn 4; sendmessage 0 "VPN Reset" 4; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [5]) echo ""; restartvpn 5; sendmessage 0 "VPN Reset" 5; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [6]) echo ""; restartwg 1; sendmessage 0 "WG Reset" 1; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [7]) echo ""; restartwg 2; sendmessage 0 "WG Reset" 2; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [8]) echo ""; restartwg 3; sendmessage 0 "WG Reset" 3; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [9]) echo ""; restartwg 4; sendmessage 0 "WG Reset" 4; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [0]) echo ""; restartwg 5; sendmessage 0 "WG Reset" 5; restartrouting; resetspdmerlin; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\!]) echo ""; killunmonvpn 1; sendmessage 0 "VPN Killed" 1; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\@]) echo ""; killunmonvpn 2; sendmessage 0 "VPN Killed" 2; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\#]) echo ""; killunmonvpn 3; sendmessage 0 "VPN Killed" 3; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\$]) echo ""; killunmonvpn 4; sendmessage 0 "VPN Killed" 4; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\%]) echo ""; killunmonvpn 5; sendmessage 0 "VPN Killed" 5; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\^]) echo ""; killunmonwg 1; sendmessage 0 "WG Killed" 1; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\&]) echo ""; killunmonwg 2; sendmessage 0 "WG Killed" 2; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\-]) echo ""; killunmonwg 3; sendmessage 0 "WG Killed" 3; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\+]) echo ""; killunmonwg 4; sendmessage 0 "WG Killed" 4; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [\=]) echo ""; killunmonwg 5; sendmessage 0 "WG Killed" 5; exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ [Aa]) autostart;;
+ [Cc]) vsetup;;
+ [Ee]) echo -e "${CClear}\n"; exit 0;;
+ [Ii]) amtmevents;;
+ [Ll]) vlogs;;
+ [Mm]) vpnslots;;
+ [Pp]) maxping;;
+ [Rr]) schedulevpnreset;;
+ [Tt]) timerloopconfig;;
+ [Uu]) vpnserverlistautomation;;
+ [Vv]) vpnserverlistmaint;;
+ [Ww]) wgserverlistmaint;;
+ [Nn]) exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ *) exec sh /jffs/scripts/vpnmon-r3.sh -noswitch;;
+ esac
+ fi
+done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# creates needed config files if they don't exist
+
+createconfigs()
+{
+
+ # Fix older versions using incorrect client slots
+ if [ "$availableslots" = "1 2 3" ]
+ then
+ availableslots="1 2"
+ rm -f /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ rm -f /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ saveconfig
+ fi
+
+ # Create initial vr3clients.txt & vr3timers.txt file
+ if [ ! -f /jffs/addons/vpnmon-r3.d/vr3clients.txt ]
+ then
+ if [ "$availableslots" = "1 2" ]
+ then
+ { echo 'VPN1=0'
+ echo 'VPN2=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3clients.txt
+
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ { echo 'VPN1=0'
+ echo 'VPN2=0'
+ echo 'VPN3=0'
+ echo 'VPN4=0'
+ echo 'VPN5=0'
+ echo 'WG1=0'
+ echo 'WG2=0'
+ echo 'WG3=0'
+ echo 'WG4=0'
+ echo 'WG5=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ fi
+ fi
+
+ if [ ! -f /jffs/addons/vpnmon-r3.d/vr3timers.txt ]
+ then
+ if [ "$availableslots" = "1 2" ]
+ then
+ { echo 'VPNTIMER1=0'
+ echo 'VPNTIMER2=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3timers.txt
+
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ { echo 'VPNTIMER1=0'
+ echo 'VPNTIMER2=0'
+ echo 'VPNTIMER3=0'
+ echo 'VPNTIMER4=0'
+ echo 'VPNTIMER5=0'
+ echo 'WGTIMER1=0'
+ echo 'WGTIMER2=0'
+ echo 'WGTIMER3=0'
+ echo 'WGTIMER4=0'
+ echo 'WGTIMER5=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ fi
+ fi
+
+
+ if [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ # Determine if the new Wireguard client values are present, if not, add them
+ if ! grep -q "WG" "/jffs/addons/vpnmon-r3.d/vr3clients.txt"
+ then
+ # Check for and remove empty lines after the last entry before the EOF
+ awk 'NF > 0 {for (i=1; i<=b; i++) print ""; b=0; print} NF==0 {b++}' "/jffs/addons/vpnmon-r3.d/vr3clients.txt" > "/jffs/addons/vpnmon-r3.d/vr3clients.tmp"
+ # Overwrite the original file with the cleaned-up version.
+ mv "/jffs/addons/vpnmon-r3.d/vr3clients.tmp" "/jffs/addons/vpnmon-r3.d/vr3clients.txt"
+ # Write the new Wireguard timer values
+ cat << EOF >> "/jffs/addons/vpnmon-r3.d/vr3clients.txt"
+WG1=0
+WG2=0
+WG3=0
+WG4=0
+WG5=0
+EOF
+
+ fi
+
+ # Determine if the new Wireguard timer values are present, if not, add them
+ if ! grep -q "WGTIMER" "/jffs/addons/vpnmon-r3.d/vr3timers.txt"
+ then
+ # Check for and remove empty lines after the last entry before the EOF
+ awk 'NF > 0 {for (i=1; i<=b; i++) print ""; b=0; print} NF==0 {b++}' "/jffs/addons/vpnmon-r3.d/vr3timers.txt" > "/jffs/addons/vpnmon-r3.d/vr3timers.tmp"
+ # Overwrite the original file with the cleaned-up version.
+ mv "/jffs/addons/vpnmon-r3.d/vr3timers.tmp" "/jffs/addons/vpnmon-r3.d/vr3timers.txt"
+ # Write the new Wireguard timer values
+ cat << EOF >> "/jffs/addons/vpnmon-r3.d/vr3timers.txt"
+WGTIMER1=0
+WGTIMER2=0
+WGTIMER3=0
+WGTIMER4=0
+WGTIMER5=0
+EOF
+
+ fi
+ fi
+
+}
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Oct-05] ##
+##-------------------------------------##
+_SetUpTimeoutCmdVars_()
+{
+ # If the timeout utility is available then use it #
+ if [ -z "${timeoutcmd:+xSETx}" ] && [ -f "/opt/bin/timeout" ]
+ then
+ timeoutcmd="timeout "
+ timeoutsec="10"
+ timeoutlng="60"
+ fi
+}
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Oct-05] ##
+##-------------------------------------##
+_SetLAN_HostName_()
+{
+ [ -z "${LAN_HostName:+xSETx}" ] && \
+ LAN_HostName="$($timeoutcmd$timeoutsec nvram get lan_hostname)"
+}
+
+_GetLAN_HostName_()
+{ _SetLAN_HostName_ ; echo "$LAN_HostName" ; }
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vsetup provide a menu interface to allow for initial component installs, uninstall, etc.
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-05] ##
+##----------------------------------------##
+vsetup()
+{
+ _SetUpTimeoutCmdVars_
+
+while true
+do
+ clear # Initial Setup
+ if [ ! -f "$config" ]; then # Write /jffs/addons/vpnmon-r3.d/vpnmon-r3.cfg
+ saveconfig
+ fi
+
+ createconfigs
+
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 Main Setup and Configuration Menu ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please choose from the various options below, which allow you to perform high level${CClear}"
+ echo -e "${InvGreen} ${CClear} actions in the management of the VPNMON-R3 script.${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(1)${CClear} : Custom configuration options for VPNMON-R3${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(2)${CClear} : Force reinstall Entware dependencies${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(3)${CClear} : Check for latest updates${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(4)${CClear} : Uninstall VPNMON-R3${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} | ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(e)${CClear} : Exit${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ read -p "Please select? (1-4, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) # Check for existence of entware, and if so proceed and install the timeout package, then run vpnmon-r3 -config
+ clear
+ if [ -f "/opt/bin/timeout" ] && [ -f "/opt/sbin/screen" ] && [ -f "/opt/bin/jq" ]
+ then
+ vconfig
+ else
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Install Dependencies ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Missing dependencies required by VPNMON-R3 will be installed during this process."
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ echo -e "VPNMON-R3 has some dependencies in order to function correctly, namely, CoreUtils-Timeout"
+ echo -e "JQ, and the Screen utility. These utilities require you to have Entware already installed"
+ echo -e "using the AMTM tool. If Entware is present, the Timeout, JQ and Screen utilities will"
+ echo -e "automatically be downloaded and installed during this process."
+ echo ""
+ echo -e "${CGreen}CoreUtils-Timeout${CClear} is a utility that provides more stability for certain routers (like"
+ echo -e "the RT-AC86U) which has a tendency to randomly hang scripts running on this router model."
+ echo ""
+ echo -e "${CGreen}JQuery${CClear} is a utility for querying data across the internet through the the means of"
+ echo -e "APIs for the purposes of interacting with the various VPN providers to get a list"
+ echo -e "of available VPN hosts in the selected location(s)."
+ echo ""
+ echo -e "${CGreen}Screen${CClear} is a utility that allows you to run SSH scripts in a standalone environment"
+ echo -e "directly on the router itself, instead of running your commands or a script from a network-"
+ echo -e "attached SSH client. This can provide greater stability due to it running on the router"
+ echo -e "itself."
+ echo ""
+ echo -e "Your router model is: ${CGreen}$ROUTERMODEL${CClear}"
+ echo ""
+ echo -e "Ready to install?"
+ if promptyn " (y/n): "
+ then
+ if [ -d "/opt" ]; then # Does entware exist? If yes proceed, if no error out.
+ echo ""
+ echo -e "\n${CClear}Updating Entware Packages..."
+ echo ""
+ opkg update
+ echo ""
+ echo -e "Installing Entware ${CGreen}CoreUtils-Timeout${CClear} Package...${CClear}"
+ echo ""
+ opkg install coreutils-timeout
+ echo ""
+ echo -e "Installing Entware ${CGreen}JQuery${CClear} Package...${CClear}"
+ echo ""
+ opkg install jq
+ echo ""
+ echo -e "Installing Entware ${CGreen}Screen${CClear} Package...${CClear}"
+ echo ""
+ opkg install screen
+ echo ""
+ echo -e "Install completed..."
+ echo ""
+ read -rsp $'Press any key to continue...\n' -n1 key
+ echo ""
+ echo -e "Executing Configuration Utility..."
+ sleep 2
+ vconfig
+ else
+ clear
+ echo -e "${CRed}ERROR: Entware was not found on this router...${CClear}"
+ echo -e "Please install Entware using the AMTM utility before proceeding..."
+ echo ""
+ read -rsp $'Press any key to continue...\n' -n1 key
+ fi
+ else
+ echo ""
+ echo -e "\nExecuting Configuration Utility..."
+ sleep 2
+ vconfig
+ fi
+ fi
+ ;;
+
+ 2) # Force re-install the CoreUtils timeout/screen package
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Re-install Dependencies ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Missing dependencies required by VPNMON-R3 will be re-installed during this process."
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ echo -e "Would you like to re-install the CoreUtils-Timeout, JQ and the Screen utility? These"
+ echo -e "utilities require you to have Entware already installed using the AMTM tool. If Entware"
+ echo -e "is present, the Timeout and Screen utilities will be uninstalled, downloaded and re-"
+ echo -e "installed during this setup process..."
+ echo ""
+ echo -e "${CGreen}CoreUtils-Timeout${CClear} is a utility that provides more stability for certain routers (like"
+ echo -e "the RT-AC86U) which has a tendency to randomly hang scripts running on this router"
+ echo -e "model."
+ echo ""
+ echo -e "${CGreen}JQuery${CClear} is a utility for querying data across the internet through the the means of"
+ echo -e "APIs for the purposes of interacting with the various VPN providers to get a list"
+ echo -e "of available VPN hosts in the selected location(s)."
+ echo ""
+ echo -e "${CGreen}Screen${CClear} is a utility that allows you to run SSH scripts in a standalone environment"
+ echo -e "directly on the router itself, instead of running your commands or a script from a"
+ echo -e "network-attached SSH client. This can provide greater stability due to it running on"
+ echo -e "the router itself."
+ echo ""
+ echo -e "Your router model is: ${CGreen}$ROUTERMODEL${CClear}"
+ echo ""
+ echo -e "Force Re-install?"
+ if promptyn "[y/n]: "
+ then
+ if [ -d "/opt" ]; then # Does entware exist? If yes proceed, if no error out.
+ echo ""
+ echo -e "\nUpdating Entware Packages..."
+ echo ""
+ opkg update
+ echo ""
+ echo -e "Force Re-installing Entware ${CGreen}CoreUtils-Timeout${CClear} Package..."
+ echo ""
+ opkg install --force-reinstall coreutils-timeout
+ echo ""
+ echo -e "Force Re-installing Entware ${CGreen}JQuery${CClear} Package..."
+ echo ""
+ opkg install --force-reinstall . jq
+ echo ""
+ echo -e "Force Re-installing Entware ${CGreen}Screen${CClear} Package..."
+ echo ""
+ opkg install --force-reinstall screen
+ echo ""
+ echo -e "Re-install completed..."
+ echo ""
+ read -rsp $'Press any key to continue...\n' -n1 key
+ else
+ clear
+ echo -e "${CRed}ERROR: Entware was not found on this router...${CClear}"
+ echo -e "Please install Entware using the AMTM utility before proceeding..."
+ echo ""
+ read -rsp $'Press any key to continue...\n' -n1 key
+ fi
+ fi
+ ;;
+ 3) vupdate;;
+ 4) vuninstall;;
+ [Ee])
+ echo ""
+ timer="$timerloop"
+ break;;
+ esac
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vconfig is a function that provides a UI to choose various options for vpnmon-r3
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-05] ##
+##----------------------------------------##
+vconfig()
+{
+ _SetUpTimeoutCmdVars_
+
+# Grab the VPNMON-R3 config file and read it in
+if [ -f "$config" ]
+then
+ source "$config"
+else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 config file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+fi
+
+while true
+do
+ if [ "$availableslots" = "1 2" ]; then
+ availableslotsdisp="2 x VPN"
+ elif [ "$availableslots" = "1 2 3 4 5" ]; then
+ availableslotsdisp="5 x VPN | 5 x WG"
+ fi
+
+ if [ "$unboundclient" -eq 0 ]; then
+ unboundclientexp="Disabled"
+ else
+ unboundclientexp="Enabled, VPN$unboundclient"
+ fi
+
+ if [ "$unboundwgclient" -eq 0 ]; then
+ unboundwgclientexp="Disabled"
+ else
+ unboundwgclientexp="Enabled, WGC$unboundwgclient"
+ fi
+
+ if [ "$unboundclient" -eq 0 ] && [ "$unboundwgclient" -eq 0 ]; then
+ unboundshowip=0
+ saveconfig
+ fi
+
+ if [ "$unboundshowip" -eq 0 ]; then
+ unboundshowipdisp="Disabled"
+ else
+ unboundshowipdisp="Enabled"
+ fi
+
+ if [ "$refreshserverlists" -eq 0 ]; then
+ refreshserverlistsdisp="Disabled"
+ else
+ refreshserverlistsdisp="Enabled"
+ fi
+
+ if [ "$monitorwan" -eq 0 ]; then
+ monitorwandisp="Disabled"
+ else
+ monitorwandisp="Enabled"
+ fi
+
+ if [ "$useovpn" -eq 0 ] && [ "$usewg" -eq 0 ]; then
+ useovpnwgDisp="${CRed}VPN/WG Disabled"
+ elif
+ [ "$useovpn" -eq 1 ] && [ "$usewg" -eq 0 ]; then
+ useovpnwgDisp="${CGreen}VPN Only"
+ elif
+ [ "$useovpn" -eq 0 ] && [ "$usewg" -eq 1 ]; then
+ useovpnwgDisp="${CGreen}WG Only"
+ elif
+ [ "$useovpn" -eq 1 ] && [ "$usewg" -eq 1 ]; then
+ useovpnwgDisp="${CGreen}VPN/WG Enabled"
+ fi
+
+ if [ "$updateskynet" -eq 0 ]; then
+ updateskynetdisp="Disabled"
+ else
+ updateskynetdisp="Enabled"
+ fi
+
+ if [ "$amtmemailsuccess" = "0" ] && [ "$amtmemailfailure" = "0" ]; then
+ amtmemailsuccfaildisp="Disabled"
+ elif [ "$amtmemailsuccess" = "1" ] && [ "$amtmemailfailure" = "0" ]; then
+ amtmemailsuccfaildisp="Success"
+ elif [ "$amtmemailsuccess" = "0" ] && [ "$amtmemailfailure" = "1" ]; then
+ amtmemailsuccfaildisp="Failure"
+ elif [ "$amtmemailsuccess" = "1" ] && [ "$amtmemailfailure" = "1" ]; then
+ amtmemailsuccfaildisp="Success, Failure"
+ else
+ amtmemailsuccfaildisp="Disabled"
+ fi
+
+ rldisp=""
+ if [ "$amtmemailsuccess" = "1" ] || [ "$amtmemailfailure" = "1" ]
+ then
+ if [ "$ratelimit" = "0" ]; then
+ rldisp="| ${CRed}RL"
+ else
+ rldisp="| ${CGreen}RL:$ratelimit/h"
+ fi
+ fi
+
+ if [ "$rstspdmerlin" -eq 0 ]; then
+ rstspdmerlindisp="Disabled"
+ else
+ rstspdmerlindisp="Enabled"
+ fi
+
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 Configuration Options ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please choose from the various options below, which allow you to modify certain${CClear}"
+ echo -e "${InvGreen} ${CClear} customizable parameters that affect the operation of this script.${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 1)${CClear} : Number of VPN/WG Client Slots available : ${CGreen}$availableslotsdisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 2)${CClear} : Custom PING host to determine VPN health : ${CGreen}$PINGHOST"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 3)${CClear} : Custom Event Log size (rows) : ${CGreen}$logsize"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 4)${CClear} : Unbound DNS Lookups over VPN Integration : ${CGreen}$unboundclientexp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 5)${CClear} : Unbound DNS Lookups over WG Integration : ${CGreen}$unboundwgclientexp"
+ if [ "$unboundclient" -ge 1 ] || [ "$unboundwgclient" -ge 1 ]; then
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 6)${CClear} -- Show Expanded Unbound IP Info? : ${CGreen}$unboundshowipdisp"
+ else
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 6)${CClear} -- ${CDkGray}Show Expanded Unbound IP Info? : $unboundshowipdisp"
+ fi
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 7)${CClear} : Refresh Custom Server Lists on -RESET Switch : ${CGreen}$refreshserverlistsdisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 8)${CClear} : Provide additional WAN/Dual WAN monitoring : ${CGreen}$monitorwandisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( 9)${CClear} : Enable/Disable VPN/WG Slot Monitoring : $useovpnwgDisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(10)${CClear} : Whitelist VPN Server IP Lists in Skynet : ${CGreen}$updateskynetdisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(11)${CClear} : AMTM Email Notifications / Rate Limiting : ${CGreen}$amtmemailsuccfaildisp $rldisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}(12)${CClear} : Reset spdMerlin Interfaces on VPN Reset : ${CGreen}$rstspdmerlindisp"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} | ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}( e)${CClear} : Exit${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ read -p "Please select? (1-12, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Number of VPN/WG Client Slots Available on Router ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate how many VPN/WG client slots your router is configured with. Certain${CClear}"
+ echo -e "${InvGreen} ${CClear} older model routers (RT-AC68U) can only handle a maximum of 2 VPN client slots, and${CClear}"
+ echo -e "${InvGreen} ${CClear} natively can't handle WG without some effort using 3rd party scripts, while the vast${CClear}"
+ echo -e "${InvGreen} ${CClear} majority of newer models can handle 5 VPN and 5 WG slots. Easiest way to tell is by${CClear}"
+ echo -e "${InvGreen} ${CClear} looking at your VPN settings within the Merlin Web UI. Please choose below:"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}(2)${CClear} = 2 x VPN slots (Older router models)"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}(5)${CClear} = 5 x VPN | 5 x WG slots (Newer router models)"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} (Default = 5 VPN/WG client slots)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$availableslotsdisp${CClear}" ; echo
+ read -p "Please enter value (2 or 5)? (e=Exit): " newAvailableSlots
+ if [ "$newAvailableSlots" = "2" ]
+ then
+ availableslots="1 2"
+ availableslotsdisp="2 x VPN"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Available VPN Client Slot Configuration saved as: $availableslotsdisp" >> $logfile
+ rm -f /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ rm -f /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ saveconfig
+ createconfigs
+ elif [ "$newAvailableSlots" = "5" ]
+ then
+ availableslots="1 2 3 4 5"
+ availableslotsdisp="5 x VPN | 5 x WG"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Available VPN Client Slot Configuration saved as: $availableslotsdisp" >> $logfile
+ rm -f /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ rm -f /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ saveconfig
+ createconfigs
+ elif [ "$newAvailableSlots" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$availableslots"
+ availableslots="${availableslots:=1 2 3 4 5}"
+ availableslotsdisp="5 x VPN | 5 x WG"
+ [ "$availableslots" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Available VPN Client Slot Configuration saved as: $availableslotsdisp" >> $logfile
+ rm -f /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ rm -f /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ saveconfig
+ createconfigs
+ fi
+ ;;
+
+ 2)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Custom PING Host (to determine VPN health) ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate which host you want to PING in order to determine VPN Client health.${CClear}"
+ echo -e "${InvGreen} ${CClear} By default, the script will ping $PING_HOST_Deflt (Google DNS) as it's reliable, fairly${CClear}"
+ echo -e "${InvGreen} ${CClear} standard, and typically available globally. You can change this depending on your"
+ echo -e "${InvGreen} ${CClear} local access and connectivity situation."
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} (Default = ${PING_HOST_Deflt})${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}${PINGHOST}${CClear}" ; echo
+ read -p "Please enter valid IPv4 address? (e=Exit): " newPingHost
+ if [ "$newPingHost" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ elif [ -n "$newPingHost" ] && echo "$newPingHost" | grep -qE "^${IPv4addrs_RegEx}$"
+ then
+ PINGHOST="$newPingHost"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New custom PING host entered: $PINGHOST" >> $logfile
+ saveconfig
+ else
+ previousValue="$PINGHOST"
+ PINGHOST="${PINGHOST:=$PING_HOST_Deflt}"
+ [ "$PINGHOST" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New custom PING host entered: $PINGHOST" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ 3)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Custom Event Log Size ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below how large you would like your Event Log to grow. I'm a poet${CClear}"
+ echo -e "${InvGreen} ${CClear} and didn't even know it. By default, with 2000 rows, you will have many months of${CClear}"
+ echo -e "${InvGreen} ${CClear} Event Log data."
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, max number of rows is 9999. (Default = 2000)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$logsize${CClear}" ; echo
+ read -p "Please enter Log Size (in rows)? (0-9999, e=Exit): " newLogSize
+ if [ "$newLogSize" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ elif echo "$newLogSize" | grep -qE "^(0|[1-9][0-9]{0,3})$" && \
+ [ "$newLogSize" -ge 0 ] && [ "$newLogSize" -le 9999 ]
+ then
+ logsize="$newLogSize"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New custom Event Log Size entered (in rows): $logsize" >> $logfile
+ saveconfig
+ else
+ previousValue="$logsize"
+ logsize="${logsize:=2000}"
+ [ "$logsize" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New custom Event Log Size entered (in rows): $logsize" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ 4)
+
+ if [ "$unboundwgclient" -ge 1 ]; then
+ echo ""
+ echo -e "${CRed}Unbound-over-WG is currently enabled. If you want to enable Unbound-over-VPN, please proceed to 'Disable'"
+ echo -e "the Unbound-over-WG option first, then choose to enable Unbound-over-VPN.${CClear}"
+ echo ""
+ sleep 3
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+ fi
+
+ while true; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Unbound DNS Lookups over VPN Integration ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate if you would like to enable an integration with Unbound which allows${CClear}"
+ echo -e "${InvGreen} ${CClear} you to force any DNS lookups that Unbound would normally handle, but over your VPN${CClear}"
+ echo -e "${InvGreen} ${CClear} connection, essentially allowing you to appear as your own DNS resolver. DNS resolver${CClear}"
+ echo -e "${InvGreen} ${CClear} traffic generated by Unbound is unencrypted as it queries DNS Root Servers by default.${CClear}"
+ echo -e "${InvGreen} ${CClear} This integration encrypts your DNS Resolver traffic up to your Public VPN IP address,${CClear}"
+ echo -e "${InvGreen} ${CClear} after which it goes unencrypted to the DNS Root Servers, preventing any ISP or other${CClear}"
+ echo -e "${InvGreen} ${CClear} traffic inspection snooping when sending this across your WAN connection.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} IMPORTANT: This integration will only work with 1 primary VPN connection that is${CClear}"
+ echo -e "${InvGreen} ${CClear} designated as the connection that will carry DNS resolution traffic. This integration${CClear}"
+ echo -e "${InvGreen} ${CClear} will work when multiple VPN connections are running, but the other VPN connections may${CClear}"
+ echo -e "${InvGreen} ${CClear} not be able to utilize the Unbound functionality, and considered standalone. You will${CClear}"
+ echo -e "${InvGreen} ${CClear} need to identify one VPN Client Slot that will remain on at all times. This integration${CClear}"
+ echo -e "${InvGreen} ${CClear} requires additional scripts and configurations to get it working correctly. Please know${CClear}"
+ echo -e "${InvGreen} ${CClear} that multiple files will either be downloaded or modified, and may increase the${CClear}"
+ echo -e "${InvGreen} ${CClear} complexity in troubleshooting DNS lookup issues.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}WARNING: As of around March 1 2024, the Unbound integration no longer works with the${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}NordVPN Service due to possible blocking on their end. This service continues to work${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}as advertised with other VPN Providers, like AirVPN. Use at your own risk.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}Requirements:"
+ echo -e "${InvGreen} ${CClear} ${CGreen}1. Unbound must already be installed and functioning (AMTM)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}2. One static VPN Slot must be designated for Unbound-over-VPN use"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}These files will be downloaded or modified:"
+ echo -e "${InvGreen} ${CClear} ${CGreen}1. /jffs/scripts/nat-start (modified)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}2. /jffs/scripts/openvpn-event (modified)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}3. /jffs/scripts/post-mount (modified)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}4. /jffs/addons/unbound/unbound_DNS_via_OVPN.sh (downloaded)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}5. Required router reboot - please don't forget to do so!${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} (Default = 0 / Disabled)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ if [ $unboundclient -eq 0 ]; then
+ unboundclientexp="Disabled"
+ else
+ unboundclientexp="Enabled, VPN$unboundclient"
+ fi
+
+ echo -e "${CClear}Current: ${CGreen}$unboundclientexp${CClear}"
+ echo ""
+ read -p "Please enter value (Disabled=0, VPN Client=1-5)? (e=Exit): " unboundovervpn
+
+ if [ ! -d "/jffs/addons/unbound" ]; then
+ echo ""
+ echo -e "${CRed}[Unbound was not detected on this system. Exiting...]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: Unbound was not detected on this system." >> $logfile
+ unboundclient=0
+ saveconfig
+ sleep 3
+ continue
+ fi
+
+ if [ "$unboundovervpn" = "0" ] || [ "$unboundovervpn" = "1" ] || [ "$unboundovervpn" = "2" ] || [ "$unboundovervpn" = "3" ] || [ "$unboundovervpn" = "4" ] || [ "$unboundovervpn" = "5" ] || [ "$unboundovervpn" = "e" ]; then
+ if [ "$unboundovervpn" = "0" ]; then
+
+ # Delete all additions made to files to enable Unbound over VPN functionality
+ echo ""
+ echo -e "${CGreen}[Disabling Unbound over VPN]...${CClear}"
+
+ # Disable vpn functionality with Unbound
+ sh /jffs/addons/unbound/unbound_manager.sh vpn=disable >/dev/null 2>&1
+
+ # Remove Unbound failsafe in post-mount
+ if [ -f /jffs/scripts/post-mount ]; then
+ sed -i -e '/vpn=disable/d' /jffs/scripts/post-mount
+ fi
+
+ # Remove Unbound VPN helper script in openvpn-event
+ if [ -f /jffs/scripts/openvpn-event ]; then
+ sed -i -e '/unbound_DNS_via_OVPN.sh/d' /jffs/scripts/openvpn-event
+ fi
+
+ # Remove RPDB Rules added to nat-start
+ if [ -f /jffs/scripts/nat-start ]; then
+ sed -i -e '/Added by vpnmon/d' /jffs/scripts/nat-start
+ fi
+
+ # Remove the unbound_DNS_via_OVPN.sh file
+ if [ -f /jffs/addons/unbound/unbound_DNS_via_OVPN.sh ]; then
+ rm -f /jffs/addons/unbound/unbound_DNS_via_OVPN.sh
+ fi
+
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound-over-VPN was removed from VPNMON-R3" >> $logfile
+ unboundclient=0
+ saveconfig
+ sleep 3
+ continue
+
+ elif [ "$unboundovervpn" = "1" ] || [ "$unboundovervpn" = "2" ] || [ "$unboundovervpn" = "3" ] || [ "$unboundovervpn" = "4" ] || [ "$unboundovervpn" = "5" ]; then
+
+ if [ "$unboundovervpn" = "$unboundclient" ]; then
+ echo -e "${CClear}\n[Unbound over VPN$unboundovervpn Already Active]"; sleep 2; break
+ fi
+
+ if [ "$unboundovervpn" = "1" ] || [ "$unboundovervpn" = "2" ] || [ "$unboundovervpn" = "3" ] || [ "$unboundovervpn" = "4" ] || [ "$unboundovervpn" = "5" ] && [ $unboundclient -ge 1 ]; then
+ echo ""
+ echo -e "${CRed}When changing a VPN Client Slot (from Slot #$unboundclient to Slot #$unboundovervpn), please proceed to 'Disable'"
+ echo -e "first (option 0), then choose a new VPN Slot."
+ sleep 5; continue
+ fi
+
+ # Modify or create post-mount
+ if [ -f /jffs/scripts/post-mount ]; then
+
+ if ! grep -q -F "[ -n "'"$(which unbound_manager)"'" ] && { sh /jffs/addons/unbound/unbound_manager.sh vpn=disable; }" /jffs/scripts/post-mount; then
+ echo "[ -n "'"$(which unbound_manager)"'" ] && { sh /jffs/addons/unbound/unbound_manager.sh vpn=disable; } # Added by vpnmon-r3" >> /jffs/scripts/post-mount
+ fi
+
+ else
+ echo "#!/bin/sh" > /jffs/scripts/post-mount
+ echo "" >> /jffs/scripts/post-mount
+ echo "[ -n "'"$(which unbound_manager)"'" ] && { sh /jffs/addons/unbound/unbound_manager.sh vpn=disable; } # Added by vpnmon-r3" >> /jffs/scripts/post-mount
+ chmod 755 /jffs/scripts/post-mount
+ fi
+
+ # Modify or create nat-start
+ if [ -f /jffs/scripts/nat-start ]; then
+
+ if ! grep -q -F "sleep 10 # During the boot process nat-start may run multiple times so this is required" /jffs/scripts/nat-start; then
+ echo "" >> /jffs/scripts/nat-start
+ echo "sleep 10 # During the boot process nat-start may run multiple times so this is required - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "" >> /jffs/scripts/nat-start
+ echo "# Ensure duplicate rules are not created - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "for VPN_ID in 0 1 2 3 4 5 # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo " do # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo " ip rule del prio 999$VPN_ID 2>/dev/null # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo " done # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "" >> /jffs/scripts/nat-start
+ echo "# Create the RPDB rules - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x8000/0x8000\" table main prio 9990 # WAN fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x7000/0x7000\" table ovpnc4 prio 9991 # VPN 4 fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x3000/0x3000\" table ovpnc5 prio 9992 # VPN 5 fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x1000/0x1000\" table ovpnc1 prio 9993 # VPN 1 fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x2000/0x2000\" table ovpnc2 prio 9994 # VPN 2 fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ echo "ip rule add from 0/0 fwmark \"0x4000/0x4000\" table ovpnc3 prio 9995 # VPN 3 fwmark - Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ fi
+
+ else
+ curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 2 --retry-all-errors "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/main/Unbound/nat-start" -o "/jffs/scripts/nat-start" && chmod 755 "/jffs/scripts/nat-start"
+ fi
+
+ # Modify or create openvpn-event
+ if [ -f /jffs/scripts/openvpn-event ]; then
+
+ if ! grep -q -F "[ "'"${dev:0:4}"'" = 'tun1' ] && vpn_id" /jffs/scripts/openvpn-event; then
+ echo "[ "'"${dev:0:4}"'" = 'tun1' ] && vpn_id=$unboundovervpn && [ "'"$script_type"'" = 'route-up' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh \$vpn_id start &" >> /jffs/scripts/openvpn-event
+ echo "[ "'"${dev:0:4}"'" = 'tun1' ] && vpn_id=$unboundovervpn && [ "'"$script_type"'" = 'route-pre-down' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh \$vpn_id stop &" >> /jffs/scripts/openvpn-event
+ fi
+
+ else
+ echo "#!/bin/sh" > /jffs/scripts/openvpn-event
+ echo "" >> /jffs/scripts/openvpn-event
+ echo "[ "'"${dev:0:4}"'" = 'tun1' ] && vpn_id=$unboundovervpn && [ "'"$script_type"'" = 'route-up' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh \$vpn_id start &" >> /jffs/scripts/openvpn-event
+ echo "[ "'"${dev:0:4}"'" = 'tun1' ] && vpn_id=$unboundovervpn && [ "'"$script_type"'" = 'route-pre-down' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh \$vpn_id stop &" >> /jffs/scripts/openvpn-event
+ chmod 755 /jffs/scripts/openvpn-event
+ # backup - curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 2 --retry-all-errors "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/main/Unbound/openvpn-event" -o "/jffs/scripts/openvpn-event" && chmod 755 "/jffs/scripts/openvpn-event"
+ fi
+
+ # Download and create the unbound_DNS_via_OVPN.sh file - many thanks to @Martineau and @Swinson
+ if [ ! -f /jffs/addons/unbound/unbound_DNS_via_OVPN.sh ]; then
+ curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 2 --retry-all-errors "https://raw.githubusercontent.com/MartineauUK/Unbound-Asuswrt-Merlin/dev/unbound_DNS_via_OVPN.sh" -o "/jffs/addons/unbound/unbound_DNS_via_OVPN.sh" && chmod 755 "/jffs/addons/unbound/unbound_DNS_via_OVPN.sh"
+ # backup - curl --silent --retry 3 "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/main/Unbound/unbound_DNS_via_OVPN.sh" -o "/jffs/addons/unbound/unbound_DNS_via_OVPN.sh" && chmod 755 "/jffs/addons/unbound/unbound_DNS_via_OVPN.sh"
+ fi
+
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound-over-VPN was enabled for VPNMON-R3" >> $logfile
+ echo -e "${CClear}"
+ unboundclient=$unboundovervpn
+ saveconfig
+ echo "Please reboot your router now if this is your first time or re-enabled Unbound over VPN"
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+
+ elif [ "$unboundovervpn" = "e" ]; then
+ echo -e "${CClear}\n[Exiting]"; sleep 2; break
+ fi
+
+ else
+ echo -e "${CClear}\n[Exiting]"; sleep 2; break
+ fi
+ done
+ ;;
+
+ 5)
+
+ if [ "$unboundclient" -ge 1 ]; then
+ echo ""
+ echo -e "${CRed}Unbound-over-VPN is currently enabled. If you want to enable Unbound-over-WG, please proceed to 'Disable'"
+ echo -e "the Unbound-over-VPN option first, then choose to enable Unbound-over-WG.${CClear}"
+ echo ""
+ sleep 3
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+ fi
+
+ while true; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Unbound DNS Lookups over WG Integration ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate if you would like to enable an integration with Unbound which allows${CClear}"
+ echo -e "${InvGreen} ${CClear} you to force any DNS lookups that Unbound would normally handle, but over your WG${CClear}"
+ echo -e "${InvGreen} ${CClear} connection, essentially allowing you to appear as your own DNS resolver. DNS resolver${CClear}"
+ echo -e "${InvGreen} ${CClear} traffic generated by Unbound is unencrypted as it queries DNS Root Servers by default.${CClear}"
+ echo -e "${InvGreen} ${CClear} This integration encrypts your DNS Resolver traffic up to your Public WG IP address,${CClear}"
+ echo -e "${InvGreen} ${CClear} after which it goes unencrypted to the DNS Root Servers, preventing any ISP or other${CClear}"
+ echo -e "${InvGreen} ${CClear} traffic inspection snooping when sending this across your WAN connection.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} IMPORTANT: This integration will only work with 1 primary WG connection that is${CClear}"
+ echo -e "${InvGreen} ${CClear} designated as the connection that will carry DNS resolution traffic. This integration${CClear}"
+ echo -e "${InvGreen} ${CClear} will work when multiple WG connections are running, but the other WG connections may${CClear}"
+ echo -e "${InvGreen} ${CClear} not be able to utilize the Unbound functionality, and considered standalone. You will${CClear}"
+ echo -e "${InvGreen} ${CClear} need to identify one WG Client Slot that will remain on at all times. This integration${CClear}"
+ echo -e "${InvGreen} ${CClear} is much more elegant and simple when it compares to the Unbound over VPN integration.${CClear}"
+ echo -e "${InvGreen} ${CClear} Should your WG connection go down, browsing/DNS resolution will continue to function${CClear}"
+ echo -e "${InvGreen} ${CClear} by traversing directly out over the WAN.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}WARNING: As of around March 1 2024, the Unbound integration no longer works with the${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}NordVPN Service due to possible blocking on their end. This service continues to work${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CRed}as advertised with other VPN Providers, like AirVPN. Use at your own risk.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}Requirements:"
+ echo -e "${InvGreen} ${CClear} ${CGreen}1. Unbound must already be installed and functioning (AMTM)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}2. One static WG Slot must be designated for Unbound-over-WG use"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${CGreen}The following will be added/modified:"
+ echo -e "${InvGreen} ${CClear} ${CGreen}1. A new virtual br0 interface will be created on 10.99.88.77 (added)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}2. A new ip rule will be added to point your WG Slot to this new br0 interface (added)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}3. The unbound.conf will have its outgoing-interface modified to 10.99.88.77 (modified)"
+ echo -e "${InvGreen} ${CClear} ${CGreen}4. Unbound service will be restarted.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} (Default = 0 / Disabled)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ if [ $unboundwgclient -eq 0 ]; then
+ unboundwgclientexp="Disabled"
+ else
+ unboundwgclientexp="Enabled, WGC$unboundwgclient"
+ fi
+
+ echo -e "${CClear}Current: ${CGreen}$unboundwgclientexp${CClear}"
+ echo ""
+ read -p "Please enter value (Disabled=0, WG Client=1-5)? (e=Exit): " unboundoverwg
+
+ if [ ! -d "/jffs/addons/unbound" ]; then
+ echo ""
+ echo -e "${CRed}[Unbound was not detected on this system. Exiting...]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: Unbound was not detected on this system." >> $logfile
+ unboundwgclient=0
+ saveconfig
+ sleep 3
+ continue
+ fi
+
+ if [ "$unboundoverwg" = "0" ] || [ "$unboundoverwg" = "1" ] || [ "$unboundoverwg" = "2" ] || [ "$unboundoverwg" = "3" ] || [ "$unboundoverwg" = "4" ] || [ "$unboundoverwg" = "5" ] || [ "$unboundoverwg" = "e" ]; then
+ if [ "$unboundoverwg" = "0" ]; then
+
+ # Delete all additions made to files to enable Unbound over VPN functionality
+ echo ""
+ echo -e "${CGreen}[Disabling Unbound over WG]...${CClear}"
+ sleep 2
+
+ # ===============================================
+ # === Disable Unbound-over-WG Integration ===
+ # === Methodology engineered by @ZebMcKayhan ===
+ # ===============================================
+
+ # Modify unbound.conf file - set major variables
+ UNBOUND_CONF="/opt/var/lib/unbound/unbound.conf"
+ DISABLED_LINE="#outgoing-interface: 10.0.20.1 # v1.08 Martineau Use VPN tunnel to hide Root server queries from ISP (or force WAN ONLY)"
+
+ # Check if the unbound.conf file exists and is readable.
+ if [ ! -r "${UNBOUND_CONF}" ]; then
+ echo ""
+ echo -e "${CRed}Error: Unbound Configuration file not found or not readable at ${UNBOUND_CONF}${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Unbound Configuration file not found or not readable at ${UNBOUND_CONF}" >> $logfile
+ sleep 3
+ continue
+ fi
+
+ # Create a temp file to move unbound.conf contents into
+ TMP_FILE="${UNBOUND_CONF}.$$"
+
+ # Remove outgoing-interface contents and replace with a dummy line
+ sed "s/^[[:space:]]*#*[[:space:]]*outgoing-interface:.*/${DISABLED_LINE}/g" "${UNBOUND_CONF}" > "${TMP_FILE}"
+ echo ""
+ echo -e "${CGreen}[Disabled 'outgoing-interface' and set back to default]...${CClear}"
+ sleep 1
+
+ # Ensure the temporary file was created and is not empty before overwriting the original
+ if [ ! -s "${TMP_FILE}" ]; then
+ echo -e "${CRed}Error: Failed to modify configuration. The temporary file is empty or was not created.${CClear}"
+ echo -e "${CRed}No changes have been made to ${UNBOUND_CONF}.${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Failed to modify configuration. The temporary file is empty or was not created." >> $logfile
+ sleep 3
+ continue
+ fi
+
+ # Move the temp file into the unbound.conf file
+ mv "${TMP_FILE}" "${UNBOUND_CONF}" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Modified unbound.conf file back to defaults]...${CClear}"
+ sleep 1
+
+ # Restart unbound service
+ if [ -f "/jffs/addons/unbound/unbound_manager.sh" ]; then
+ unbound_manager restart >/dev/null 2>&1
+ RESTART_STATUS=$?
+ if [ ${RESTART_STATUS} -eq 0 ]; then
+ echo ""
+ echo -e "${CGreen}[Unbound service restarted successfully]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound service restarted successfully" >> $logfile
+ sleep 1
+ else
+ echo ""
+ echo -e "${CRed}[Warning: 'unbound_manager restart' command failed with status ${RESTART_STATUS}]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: 'unbound_manager restart' command failed with status ${RESTART_STATUS}" >> $logfile
+ sleep 3
+ fi
+ else
+ echo ""
+ echo -e "${CRed}[Warning: 'unbound_manager.sh' script not found. Could not restart service]...${CClear}"
+ echo -e "${CRed}[Please restart the unbound service manually]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: 'unbound_manager.sh' script not found. Could not restart service" >> $logfile
+ sleep 3
+ fi
+
+ # Remove the IP rule from VPN Director
+ ip rule del prio 11 >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Removed IP rule for virtual br0 interface at 10.99.88.77]...${CClear}"
+ sleep 1
+
+ # Remove added virtual br0 interface
+ ifconfig br0:UnboundWG down >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Removed virtual br0 interface at 10.99.88.77]...${CClear}"
+ sleep 1
+
+ # Remove Unbound failsafe in init-start
+ if [ -f /jffs/scripts/init-start ]; then
+ sed -i -e '/vpnmon-r3/d' /jffs/scripts/init-start
+ fi
+ echo ""
+ echo -e "${CGreen}[Unbound failsafe removed from init-start file]...${CClear}"
+ sleep 1
+
+ # Remove Unbound failsafe in nat-start
+ if [ -f /jffs/scripts/nat-start ]; then
+ sed -i -e '/vpnmon-r3/d' /jffs/scripts/nat-start
+ fi
+ echo ""
+ echo -e "${CGreen}[Unbound failsafe removed from nat-start file]...${CClear}"
+ sleep 1
+
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound-over-WG was removed from VPNMON-R3" >> $logfile
+ unboundwgclient=0
+ saveconfig
+
+ echo ""
+ echo "Please consider rebooting your router now after major Unbound and system file changes."
+ echo ""
+ sleep 3
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+
+ elif [ "$unboundoverwg" = "1" ] || [ "$unboundoverwg" = "2" ] || [ "$unboundoverwg" = "3" ] || [ "$unboundoverwg" = "4" ] || [ "$unboundoverwg" = "5" ]; then
+
+ if [ "$unboundoverwg" = "$unboundwgclient" ]; then
+ echo -e "${CClear}\n[Unbound over WGC$unboundoverwg Already Active]"; sleep 3; break
+ fi
+
+ if [ "$unboundoverwg" = "1" ] || [ "$unboundoverwg" = "2" ] || [ "$unboundoverwg" = "3" ] || [ "$unboundoverwg" = "4" ] || [ "$unboundoverwg" = "5" ] && [ $unboundwgclient -ge 1 ]; then
+ echo ""
+ echo -e "${CRed}When changing a WG Client Slot (from WGC #$unboundwgclient to WGC #$unboundoverwg), please proceed to 'Disable'"
+ echo -e "first (option 0), then choose a new WG Slot.${CClear}"
+ echo ""
+ sleep 3
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+ fi
+
+ # ===============================================
+ # === Create Unbound-over-WG Integration ===
+ # === Methodology engineered by @ZebMcKayhan ===
+ # ===============================================
+
+ echo ""
+ echo -e "${CGreen}[Enabling Unbound over WG]...${CClear}"
+ sleep 2
+
+ # Create new virtual br0 interface
+ ifconfig br0:UnboundWG 10.99.88.77 netmask 255.255.255.255 up >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Added virtual br0 interface at 10.99.88.77]...${CClear}"
+ sleep 1
+
+ # Point WG slot to new br0 interface for VPN Director
+ ip rule add from 10.99.88.77 lookup wgc$unboundoverwg prio 11 >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Pointed wgc$unboundoverwg to virtual br0 interface at 10.99.88.77]...${CClear}"
+ sleep 1
+
+ # Modify unbound.conf file - set major variables
+ UNBOUND_CONF="/opt/var/lib/unbound/unbound.conf"
+ ENABLED_IP="10.99.88.77"
+ COMMENT="# v1.08 Martineau Use VPN tunnel to hide Root server queries from ISP (or force WAN ONLY)"
+
+ # Check if the unbound.conf file exists and is readable.
+ if [ ! -r "${UNBOUND_CONF}" ]; then
+ echo ""
+ echo -e "${CRed}Error: Unbound Configuration file not found or not readable at ${UNBOUND_CONF}${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Unbound Configuration file not found or not readable at ${UNBOUND_CONF}" >> $logfile
+ sleep 3
+ continue
+ fi
+
+ # Create a temp file to move unbound.conf contents into
+ TMP_FILE="${UNBOUND_CONF}.$$"
+
+ # Create new outgoing-interface contents
+ ENABLED_LINE="outgoing-interface: ${ENABLED_IP} ${COMMENT}"
+ sed "s/^[[:space:]]*#*[[:space:]]*outgoing-interface:.*/${ENABLED_LINE}/g" "${UNBOUND_CONF}" > "${TMP_FILE}"
+
+ # Ensure the temporary file was created and is not empty before overwriting the original
+ if [ ! -s "${TMP_FILE}" ]; then
+ echo -e "${CRed}Error: Failed to modify configuration. The temporary file is empty or was not created.${CClear}"
+ echo -e "${CRed}No changes have been made to ${UNBOUND_CONF}.${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Failed to modify configuration. The temporary file is empty or was not created." >> $logfile
+ sleep 3
+ continue
+ fi
+
+ # Move the temp file into the unbound.conf file
+ mv "${TMP_FILE}" "${UNBOUND_CONF}" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Modified unbound.conf file 'outgoing-interface: 10.99.88.77']...${CClear}"
+ sleep 1
+
+ # Restart unbound service
+ if [ -f "/jffs/addons/unbound/unbound_manager.sh" ]; then
+ unbound_manager restart >/dev/null 2>&1
+ RESTART_STATUS=$?
+ if [ ${RESTART_STATUS} -eq 0 ]; then
+ echo ""
+ echo -e "${CGreen}[Unbound service restarted successfully]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound service restarted successfully" >> $logfile
+ sleep 1
+ else
+ echo ""
+ echo -e "${CRed}[Warning: 'unbound_manager restart' command failed with status ${RESTART_STATUS}]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: 'unbound_manager restart' command failed with status ${RESTART_STATUS}" >> $logfile
+ sleep 3
+ fi
+ else
+ echo ""
+ echo -e "${CRed}[Warning: 'unbound_manager.sh' script not found. Could not restart service]...${CClear}"
+ echo -e "${CRed}[Please restart the unbound service manually]...${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: 'unbound_manager.sh' script not found. Could not restart service" >> $logfile
+ sleep 3
+ fi
+
+ echo ""
+ echo -e "${CGreen}[Adding Unbound Failsafe... Modifying init-start file]...${CClear}"
+ sleep 1
+
+ # Modify or create init-start to ensure survivability after a router reboot
+ if [ -f /jffs/scripts/init-start ]; then
+
+ if ! grep -q -F "sh /jffs/scripts/vpnmon-r3.sh -uowginitstart" /jffs/scripts/init-start; then
+ echo "sh /jffs/scripts/vpnmon-r3.sh -uowginitstart # Added by vpnmon-r3" >> /jffs/scripts/init-start
+ fi
+
+ else
+ echo "#!/bin/sh" > /jffs/scripts/init-start
+ echo "" >> /jffs/scripts/init-start
+ echo "sh /jffs/scripts/vpnmon-r3.sh -uowginitstart # Added by vpnmon-r3" >> /jffs/scripts/init-start
+ chmod 755 /jffs/scripts/init-start
+ fi
+
+ echo ""
+ echo -e "${CGreen}[Adding Unbound Failsafe... Modifying nat-start file]...${CClear}"
+ sleep 1
+
+ # Modify or create nat-start to ensure survivability after a router reboot
+ if [ -f /jffs/scripts/nat-start ]; then
+
+ if ! grep -q -F "sh /jffs/scripts/vpnmon-r3.sh -uowgnatstart" /jffs/scripts/nat-start; then
+ echo "sh /jffs/scripts/vpnmon-r3.sh -uowgnatstart # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ fi
+
+ else
+ echo "#!/bin/sh" > /jffs/scripts/nat-start
+ echo "" >> /jffs/scripts/nat-start
+ echo "sh /jffs/scripts/vpnmon-r3.sh -uowgnatstart # Added by vpnmon-r3" >> /jffs/scripts/nat-start
+ chmod 755 /jffs/scripts/nat-start
+ fi
+
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Unbound-over-WG was enabled for VPNMON-R3" >> $logfile
+ echo -e "${CClear}"
+ unboundwgclient=$unboundoverwg
+ saveconfig
+
+ echo ""
+ echo "Please consider rebooting your router now if this is your first time or have re-enabled Unbound-over-WG"
+ echo ""
+ sleep 3
+ read -rsp $'Press any key to continue...\n' -n1 key
+ continue
+
+ elif [ "$unboundoverwg" = "e" ]; then
+ echo -e "${CClear}\n[Exiting]"; sleep 2; break
+ fi
+
+ else
+ echo -e "${CClear}\n[Exiting]"; sleep 2; break
+ fi
+ done
+ ;;
+
+ 6)
+ if [ "$unboundclient" != "0" ] || [ "$unboundwgclient" != "0" ]; then
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Show Expanded Unbound IP Information ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to show your full Unbound DNS Resolver IP on-${CClear}"
+ echo -e "${InvGreen} ${CClear} screen, or just an abbreviated color-coded indicator. Showing a full IP may in some${CClear}"
+ echo -e "${InvGreen} ${CClear} cases help with troubleshooting.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, 1 to Enable. (Default = 0)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$unboundshowipdisp${CClear}" ; echo
+ read -p "Please Choose? (Disable = 0, Enable = 1, e=Exit): " newunboundshowip
+ if [ "$newunboundshowip" = "0" ]
+ then
+ unboundshowip=0
+ unboundshowipdisp="Disabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Expanded Unbound IP Information Disabled" >> $logfile
+ saveconfig
+ elif [ "$newunboundshowip" = "1" ]
+ then
+ unboundshowip=1
+ unboundshowipdisp="Enabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Expanded Unbound IP Information Enabled" >> $logfile
+ saveconfig
+ elif [ "$newunboundshowip" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$unboundshowip"
+ unboundshowip="${unboundshowip:=0}"
+ unboundshowipdisp="$([ "$unboundshowip" = "0" ] && echo "Disabled" || echo "Enabled")"
+ [ "$unboundshowip" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Expanded Unbound IP Information Disabled" >> $logfile
+ saveconfig
+ fi
+ fi
+ ;;
+
+ 7)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Refresh Custom Server Lists on -RESET Switch ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to automatically refresh your custom Server${CClear}"
+ echo -e "${InvGreen} ${CClear} Lists specified under the Edit/Run Server List Automation menu. This function will${CClear}"
+ echo -e "${InvGreen} ${CClear} run any defined CURL+JQ statements you have configured and save them back to your${CClear}"
+ echo -e "${InvGreen} ${CClear} Client Slot Server List files that will be used for VPN connections.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, 1 to Enable. (Default = 0)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$refreshserverlistsdisp${CClear}" ; echo
+ read -p "Please Choose? (Disable = 0, Enable = 1, e=Exit): " newRefreshServerList
+ if [ "$newRefreshServerList" = "0" ]
+ then
+ refreshserverlists=0
+ refreshserverlistsdisp="Disabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom Server Lists Disabled on -RESET Switch" >> $logfile
+ saveconfig
+ elif [ "$newRefreshServerList" = "1" ]
+ then
+ refreshserverlists=1
+ refreshserverlistsdisp="Enabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom Server Lists Enabled on -RESET Switch" >> $logfile
+ saveconfig
+ elif [ "$newRefreshServerList" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$refreshserverlists"
+ refreshserverlists="${refreshserverlists:=0}"
+ refreshserverlistsdisp="$([ "$refreshserverlists" = "0" ] && echo "Disabled" || echo "Enabled")"
+ [ "$refreshserverlists" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom Server Lists $refreshserverlistsdisp on -RESET Switch" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ 8)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Provide WAN/Dual WAN Monitoring Functionality ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to monitor your WAN/Dual WAN connection for${CClear}"
+ echo -e "${InvGreen} ${CClear} connectivity issues that may impact your VPN connection. This functionality will${CClear}"
+ echo -e "${InvGreen} ${CClear} determine if your WAN connection is viable, and upon determining that the WAN is${CClear}"
+ echo -e "${InvGreen} ${CClear} down, VPNMON-R3 will kill all VPN connections and continue testing for a valid WAN${CClear}"
+ echo -e "${InvGreen} ${CClear} connection until it can restore your VPN connections.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, 1 to Enable. (Default = 0)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$monitorwandisp${CClear}" ; echo
+ read -p "Please Choose? (Disable = 0, Enable = 1, e=Exit): " newMonitorWAN
+ if [ "$newMonitorWAN" = "0" ]
+ then
+ monitorwan=0
+ monitorwandisp="Disabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WAN Monitoring Disabled" >> $logfile
+ saveconfig
+ elif [ "$newMonitorWAN" = "1" ]
+ then
+ monitorwan=1
+ monitorwandisp="Enabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WAN Monitoring Enabled" >> $logfile
+ saveconfig
+ elif [ "$newMonitorWAN" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$monitorwan"
+ monitorwan="${monitorwan:=0}"
+ monitorwandisp="$([ "$monitorwan" = "0" ] && echo "Disabled" || echo "Enabled")"
+ [ "$monitorwan" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WAN Monitoring $monitorwandisp" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ 9)
+ while true
+ do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Enable/Disable VPN/WG Slot Monitoring and Display ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate whether you want to enable or disable VPN/WG Slots from being${CClear}"
+ echo -e "${InvGreen} ${CClear} monitored and shown on the main VPNMON-R3 UI. This setting is meant for those${CClear}"
+ echo -e "${InvGreen} ${CClear} who are only running VPN or only WG on their router, and do not want to display${CClear}"
+ echo -e "${InvGreen} ${CClear} one or the other to only show relevant info.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to enable/disable monitoring for each.${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+
+ if [ "$useovpn" = "1" ]; then useovpnDisp="${CGreen}Y${CCyan}"; else useovpn=0; useovpnDisp="${CRed}N${CCyan}"; fi
+ if [ "$usewg" = "1" ]; then usewgDisp="${CGreen}Y${CCyan}"; else usewg=0; usewgDisp="${CRed}N${CCyan}"; fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} OpenVPN${CClear} ${CGreen}(1) -${CClear} $useovpnDisp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}Wireguard${CClear} ${CGreen}(2) -${CClear} $usewgDisp${CClear}"
+ echo ""
+ read -p "Please select? (1-2, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1)
+ if [ "$unboundclient" = "0" ]; then
+ if [ "$useovpn" = "0" ]; then
+ useovpn=1
+ useovpnDisp="${CGreen}Y${CCyan}"
+ elif [ "$useovpn" = "1" ]; then
+ useovpn=0; useovpnDisp="${CRed}N${CCyan}"
+ fi
+ else
+ echo -e "${CClear}\n[Unable to disable VPN. Unbound Active on Slot VPN$unboundclient]"; sleep 3
+ fi;;
+ 2)
+ if [ "$usewg" = "0" ]; then
+ usewg=1
+ usewgDisp="${CGreen}Y${CCyan}"
+ elif [ "$usewg" = "1" ]; then
+ usewg=0
+ usewgDisp="${CRed}N${CCyan}"
+ fi;;
+ [Ee])
+ saveconfig
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN/WG Client Slot Monitoring/Display configuration saved" >> $logfile
+ timer="$timerloop"
+ break;;
+ esac
+ done
+
+ ;;
+
+ 10)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Whitelist VPN Server IP Lists in Skynet ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to whitelist your VPN Server IP lists in${CClear}"
+ echo -e "${InvGreen} ${CClear} the Skynet Firewall. This provides for better stability in connecting to your VPN${CClear}"
+ echo -e "${InvGreen} ${CClear} provider, as there have been occasions where the Skynet blacklist will prevent${CClear}"
+ echo -e "${InvGreen} ${CClear} connections to your VPN Servers. This could cause a disruption in being able to${CClear}"
+ echo -e "${InvGreen} ${CClear} maintain a stable VPN connection. Note: Skynet must already be installed and${CClear}"
+ echo -e "${InvGreen} ${CClear} operational for this functionality to work.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, 1 to Enable. (Default = 0)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$updateskynetdisp${CClear}" ; echo
+ read -p "Please Choose? (Disable = 0, Enable = 1, e=Exit): " newUpdateSkyNet
+ if [ "$newUpdateSkyNet" = "1" ]
+ then
+ updateskynet=1
+ updateskynetdisp="Enabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Server IP Skynet Whitelisting Enabled" >> $logfile
+ saveconfig
+ elif [ "$newUpdateSkyNet" = "0" ]
+ then
+ updateskynet=0
+ updateskynetdisp="Disabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Server IP Skynet Whitelisting Disabled" >> $logfile
+ saveconfig
+ elif [ "$newUpdateSkyNet" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$updateskynet"
+ updateskynet="${updateskynet:=0}"
+ updateskynetdisp="$([ "$updateskynet" = "0" ] && echo "Disabled" || echo "Enabled")"
+ [ "$updateskynet" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Server IP Skynet Whitelisting $updateskynetdisp" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ [Ee]) echo -e "${CClear}\n[Exiting]"; sleep 2; break ;;
+
+ 11)
+ amtmevents
+ source "$config"
+ ;;
+
+ 12)
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Reset spdMerlin Interfaces on VPN Reset ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to reset your spdMerlin Interfaces each${CClear}"
+ echo -e "${InvGreen} ${CClear} time VPNMON-R3 resets. This functionality will allow VPNMON-R3 to update spdMerlin${CClear}"
+ echo -e "${InvGreen} ${CClear} whenever a VPN reset occurs. SpdMerlin will then know which interfaces are active${CClear}"
+ echo -e "${InvGreen} ${CClear} in order to run manual or automated speedtests from.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use 0 to Disable, 1 to Enable. (Default = 0)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ echo -e "${CClear}Current: ${CGreen}$rstspdmerlindisp${CClear}" ; echo
+ read -p "Please Choose? (Disable = 0, Enable = 1, e=Exit): " newrstspdmerlin
+ if [ "$newrstspdmerlin" = "0" ]
+ then
+ rstspdmerlin=0
+ rstspdmerlindisp="Disabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: spdMerlin Interface Reset Disabled" >> $logfile
+ saveconfig
+ elif [ "$newrstspdmerlin" = "1" ]
+ then
+ rstspdmerlin=1
+ rstspdmerlindisp="Enabled"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: spdMerlin Interface Reset Enabled" >> $logfile
+ saveconfig
+ elif [ "$newrstspdmerlin" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ else
+ previousValue="$rstspdmerlin"
+ rstspdmerlin="${rstspdmerlin:=0}"
+ rstspdmerlindisp="$([ "$rstspdmerlin" = "0" ] && echo "Disabled" || echo "Enabled")"
+ [ "$rstspdmerlin" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: spdMerlin Interface Reset $monitorwandisp" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ esac
+done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# uowginitstart is a function that initializes the virtual br0 interface when called from init-start
+
+uowginitstart()
+{
+
+ if [ -f "$config" ]
+ then
+ source "$config"
+
+ # Remove added virtual br0 interface if it already exists
+ ifconfig br0:UnboundWG down >/dev/null 2>&1
+
+ # Addvirtual br0 interface
+ ifconfig br0:UnboundWG 10.99.88.77 netmask 255.255.255.255 up >/dev/null 2>&1
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# uowgnatstart is a function that ties the virtual br0 interface to the assigned wgc slot
+
+uowgnatstart()
+{
+
+ if [ -f "$config" ]
+ then
+ source "$config"
+
+ # Remove ip rule if it already exists
+ ip rule del prio 11 >/dev/null 2>&1
+
+ # Add ip rule to tie br0 interface with assigned wgc slot
+ ip rule add from 10.99.88.77 lookup wgc$unboundwgclient prio 11 >/dev/null 2>&1
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vupdate is a function that provides a UI to check for script updates and allows you to install the latest version...
+
+vupdate()
+{
+
+updatecheck # Check for the latest version from source repository
+while true; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 Update Utility ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} This utility allows you to check, download and install updates"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ echo -e "Current Version: ${CGreen}$version${CClear}"
+ echo -e "Updated Version: ${CGreen}$DLversion${CClear}"
+ echo ""
+ if [ "$version" = "$DLversion" ]
+ then
+ echo -e "You are on the latest version! Would you like to download anyways? This will overwrite${CClear}"
+ echo -e "your local copy with the current build.${CClear}"
+ if promptyn "[y/n]: "; then
+ echo ""
+ echo -e "\nDownloading VPNMON-R3 ${CGreen}v$DLversion${CClear}"
+ curl --silent --retry 3 --connect-timeout 3 --max-time 5 --retry-delay 2 --retry-all-errors --fail "https://raw.githubusercontent.com/ViktorJp/VPNMON-R3/main/vpnmon-r3.sh" -o "/jffs/scripts/vpnmon-r3.sh" && chmod 755 "/jffs/scripts/vpnmon-r3.sh"
+ echo ""
+ echo -e "Download successful!${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Successfully downloaded and installed VPNMON-R3 v$DLversion" >> $logfile
+ echo ""
+ read -rsp $'Press any key to restart VPNMON-R3...\n' -n1 key
+ exec /jffs/scripts/vpnmon-r3.sh -setup
+ else
+ echo ""
+ echo ""
+ echo -e "Exiting Update Utility...${CClear}"
+ sleep 1
+ return
+ fi
+ else
+ echo -e "Score! There is a new version out there! Would you like to update?${CClear}"
+ if promptyn "[y/n]: "; then
+ echo ""
+ echo -e "\nDownloading VPNMON-R3 ${CGreen}v$DLversion${CClear}"
+ curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 2 --retry-all-errors --fail "https://raw.githubusercontent.com/ViktorJp/VPNMON-R3/main/vpnmon-r3.sh" -o "/jffs/scripts/vpnmon-r3.sh" && chmod 755 "/jffs/scripts/vpnmon-r3.sh"
+ echo ""
+ echo -e "Download successful!${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Successfully downloaded and installed VPNMON-R3 v$DLversion" >> $logfile
+ echo ""
+ read -rsp $'Press any key to restart VPNMON-R3...\n' -n1 key
+ exec /jffs/scripts/vpnmon-r3.sh -setup
+ else
+ echo ""
+ echo ""
+ echo -e "Exiting Update Utility...${CClear}"
+ sleep 1
+ return
+ fi
+ fi
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# updatecheck is a function that downloads the latest update version file, and compares it with what's currently installed
+
+updatecheck()
+{
+
+ # Download the latest version file from the source repository
+ curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 2 --retry-all-errors --fail "https://raw.githubusercontent.com/ViktorJp/VPNMON-R3/main/version.txt" -o "/jffs/addons/vpnmon-r3.d/version.txt"
+
+ if [ -f $dlverpath ]
+ then
+ # Read in its contents for the current version file
+ DLversion=$(cat $dlverpath)
+
+ # Compare the new version with the old version and log it
+ if [ "$beta" = "1" ]; then # Check if Dev/Beta Mode is enabled and disable notification message
+ UpdateNotify=0
+ elif [ "$DLversion" != "$version" ]; then
+ DLversionPF=$(printf "%-8s" $DLversion)
+ versionPF=$(printf "%-8s" $version)
+ UpdateNotify="${InvYellow} ${InvDkGray}${CWhite} Update available: v$versionPF -> v$DLversionPF ${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: A new update (v$DLversion) is available to download" >> $logfile
+ else
+ UpdateNotify=0
+ fi
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vuninstall is a function that uninstalls and removes all traces of vpnmon-r3 from your router...
+
+vuninstall()
+{
+
+while true; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Uninstall Utility ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} You are about to uninstall VPNMON-R3! This action is irreversible."
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ echo -e "Do you wish to proceed?${CClear}"
+ if promptyn "(y/n): "; then
+ echo ""
+ echo -e "\nAre you sure? Please type 'y' to validate you wish to proceed.${CClear}"
+ if promptyn "(y/n): "; then
+ clear
+ #Remove and uninstall files/directories
+ rm -f -r /jffs/addons/vpnmon-r3.d
+ rm -f /jffs/scripts/vpnmon-r3.sh
+ sed -i -e '/vpnmon-r3.sh/d' /jffs/scripts/services-start
+ cru d RunVPNMONR3reset
+ echo ""
+ echo -e "\nVPNMON-R3 has been uninstalled...${CClear}"
+ echo ""
+ exit 0
+ else
+ echo ""
+ echo -e "\nExiting Uninstall Utility...${CClear}"
+ sleep 1
+ return
+ fi
+ else
+ echo ""
+ echo -e "\nExiting Uninstall Utility...${CClear}"
+ sleep 1
+ return
+ fi
+done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vlogs is a function that calls the nano text editor to view the BACKUPMON log file
+
+vlogs()
+{
+
+export TERM=linux
+nano +999999 --linenumbers $logfile
+timer="$timerloop"
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vpnslots lets you pick which vpn slot numbers are being monitored by vpnmon-r3
+
+vpnslots()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPN/WG Client Slot Monitoring ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate which VPN/WG slots you would like VPNMON-R3 to monitor.${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to enable/disable monitoring for each slot:${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+
+ if [ "$availableslots" = "1 2" ]
+ then
+ if [ "$VPN1" = "1" ]; then VPN1Disp="${CGreen}Y${CCyan}"; else VPN1=0; VPN1Disp="${CRed}N${CCyan}"; fi
+ if [ "$VPN2" = "1" ]; then VPN2Disp="${CGreen}Y${CCyan}"; else VPN2=0; VPN2Disp="${CRed}N${CCyan}"; fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN1${CClear} ${CGreen}(1) -${CClear} $VPN1Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN2${CClear} ${CGreen}(2) -${CClear} $VPN2Disp${CClear}"
+ echo ""
+ read -p "Please select? (1-2, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) if [ "$VPN1" = "0" ]; then VPN1=1; VPN1Disp="${CGreen}Y${CCyan}"; elif [ "$VPN1" = "1" ]; then VPN1=0; VPN1Disp="${CRed}N${CCyan}"; fi;;
+ 2) if [ "$VPN2" = "0" ]; then VPN2=1; VPN2Disp="${CGreen}Y${CCyan}"; elif [ "$VPN2" = "1" ]; then VPN2=0; VPN2Disp="${CRed}N${CCyan}"; fi;;
+ [Ee])
+ { echo 'VPN1='$VPN1
+ echo 'VPN2='$VPN2
+ } > /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Client Slot Monitoring configuration saved" >> $logfile
+ timer="$timerloop"
+ break;;
+ esac
+
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ if [ "$VPN1" = "1" ]; then VPN1Disp="${CGreen}Y${CCyan}"; else VPN1=0; VPN1Disp="${CRed}N${CCyan}"; fi
+ if [ "$VPN2" = "1" ]; then VPN2Disp="${CGreen}Y${CCyan}"; else VPN2=0; VPN2Disp="${CRed}N${CCyan}"; fi
+ if [ "$VPN3" = "1" ]; then VPN3Disp="${CGreen}Y${CCyan}"; else VPN3=0; VPN3Disp="${CRed}N${CCyan}"; fi
+ if [ "$VPN4" = "1" ]; then VPN4Disp="${CGreen}Y${CCyan}"; else VPN4=0; VPN4Disp="${CRed}N${CCyan}"; fi
+ if [ "$VPN5" = "1" ]; then VPN5Disp="${CGreen}Y${CCyan}"; else VPN5=0; VPN5Disp="${CRed}N${CCyan}"; fi
+ if [ "$WG1" = "1" ]; then WG1Disp="${CGreen}Y${CCyan}"; else WG1=0; WG1Disp="${CRed}N${CCyan}"; fi
+ if [ "$WG2" = "1" ]; then WG2Disp="${CGreen}Y${CCyan}"; else WG2=0; WG2Disp="${CRed}N${CCyan}"; fi
+ if [ "$WG3" = "1" ]; then WG3Disp="${CGreen}Y${CCyan}"; else WG3=0; WG3Disp="${CRed}N${CCyan}"; fi
+ if [ "$WG4" = "1" ]; then WG4Disp="${CGreen}Y${CCyan}"; else WG4=0; WG4Disp="${CRed}N${CCyan}"; fi
+ if [ "$WG5" = "1" ]; then WG5Disp="${CGreen}Y${CCyan}"; else WG5=0; WG5Disp="${CRed}N${CCyan}"; fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN1${CClear} ${CGreen}(1) -${CClear} $VPN1Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN2${CClear} ${CGreen}(2) -${CClear} $VPN2Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN3${CClear} ${CGreen}(3) -${CClear} $VPN3Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN4${CClear} ${CGreen}(4) -${CClear} $VPN4Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN5${CClear} ${CGreen}(5) -${CClear} $VPN5Disp${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG1${CClear} ${CGreen}(6) -${CClear} $WG1Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG2${CClear} ${CGreen}(7) -${CClear} $WG2Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG3${CClear} ${CGreen}(8) -${CClear} $WG3Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG4${CClear} ${CGreen}(9) -${CClear} $WG4Disp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG5${CClear} ${CGreen}(0) -${CClear} $WG5Disp${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ read -p "Please select? (1-0, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) if [ "$VPN1" = "0" ]; then VPN1=1; VPN1Disp="${CGreen}Y${CCyan}"; elif [ "$VPN1" = "1" ]; then VPN1=0; VPN1Disp="${CRed}N${CCyan}"; fi;;
+ 2) if [ "$VPN2" = "0" ]; then VPN2=1; VPN2Disp="${CGreen}Y${CCyan}"; elif [ "$VPN2" = "1" ]; then VPN2=0; VPN2Disp="${CRed}N${CCyan}"; fi;;
+ 3) if [ "$VPN3" = "0" ]; then VPN3=1; VPN3Disp="${CGreen}Y${CCyan}"; elif [ "$VPN3" = "1" ]; then VPN3=0; VPN3Disp="${CRed}N${CCyan}"; fi;;
+ 4) if [ "$VPN4" = "0" ]; then VPN4=1; VPN4Disp="${CGreen}Y${CCyan}"; elif [ "$VPN4" = "1" ]; then VPN4=0; VPN4Disp="${CRed}N${CCyan}"; fi;;
+ 5) if [ "$VPN5" = "0" ]; then VPN5=1; VPN5Disp="${CGreen}Y${CCyan}"; elif [ "$VPN5" = "1" ]; then VPN5=0; VPN5Disp="${CRed}N${CCyan}"; fi;;
+ 6) if [ "$WG1" = "0" ]; then WG1=1; WG1Disp="${CGreen}Y${CCyan}"; elif [ "$WG1" = "1" ]; then WG1=0; WG1Disp="${CRed}N${CCyan}"; fi;;
+ 7) if [ "$WG2" = "0" ]; then WG2=1; WG2Disp="${CGreen}Y${CCyan}"; elif [ "$WG2" = "1" ]; then WG2=0; WG2Disp="${CRed}N${CCyan}"; fi;;
+ 8) if [ "$WG3" = "0" ]; then WG3=1; WG3Disp="${CGreen}Y${CCyan}"; elif [ "$WG3" = "1" ]; then WG3=0; WG3Disp="${CRed}N${CCyan}"; fi;;
+ 9) if [ "$WG4" = "0" ]; then WG4=1; WG4Disp="${CGreen}Y${CCyan}"; elif [ "$WG4" = "1" ]; then WG4=0; WG4Disp="${CRed}N${CCyan}"; fi;;
+ 0) if [ "$WG5" = "0" ]; then WG5=1; WG5Disp="${CGreen}Y${CCyan}"; elif [ "$WG5" = "1" ]; then WG5=0; WG5Disp="${CRed}N${CCyan}"; fi;;
+ [Ee])
+ { echo 'VPN1='$VPN1
+ echo 'VPN2='$VPN2
+ echo 'VPN3='$VPN3
+ echo 'VPN4='$VPN4
+ echo 'VPN5='$VPN5
+ echo 'WG1='$WG1
+ echo 'WG2='$WG2
+ echo 'WG3='$WG3
+ echo 'WG4='$WG4
+ echo 'WG5='$WG5
+ } > /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN/WG Client Slot Monitoring configuration saved" >> $logfile
+ timer="$timerloop"
+ break;;
+ esac
+ fi
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# amtmevents lets you pick success or failure amtm email notification selections
+
+amtmevents()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} AMTM Email Notifications ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate if you would like VPNMON-R3 to send you email notifications for WAN${CClear}"
+ echo -e "${InvGreen} ${CClear} or VPN slot failures, or successes on scheduled VPN resets, or both? PLEASE NOTE:${CClear}"
+ echo -e "${InvGreen} ${CClear} This does require that AMTM email has been set up successfully under AMTM -> em${CClear}"
+ echo -e "${InvGreen} ${CClear} (email settings). Once you are able to send and receive test emails from AMTM, you${CClear}"
+ echo -e "${InvGreen} ${CClear} may use this functionality in VPNMON-R3. Additionally, this functionality will${CClear}"
+ echo -e "${InvGreen} ${CClear} download an AMTM email interface library courtesy of @Martinsky, and will be${CClear}"
+ echo -e "${InvGreen} ${CClear} located under a new common shared library folder called: /jffs/addons/shared-libs.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Secondarily, you can choose to rate limit the rate at which emails are sent to${CClear}"
+ echo -e "${InvGreen} ${CClear} your email account per hour. (0=Disabled, 1-9999)${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to enable/disable email event notifications:${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+
+ if [ "$amtmemailsuccess" = "1" ]; then amtmemailsuccessdisp="${CGreen}Y${CCyan}"; else amtmemailsuccess=0; amtmemailsuccessdisp="${CRed}N${CCyan}"; saveconfig; fi
+ if [ "$amtmemailfailure" = "1" ]; then amtmemailfailuredisp="${CGreen}Y${CCyan}"; else amtmemailfailure=0; amtmemailfailuredisp="${CRed}N${CCyan}"; saveconfig; fi
+ if [ "$ratelimit" = "0" ]; then ratelimitdisp="Disabled"; else ratelimitdisp=$ratelimit; fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN Success Event Notifications${CClear} ${CGreen}(1) -${CClear} $amtmemailsuccessdisp${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN Failure Event Notifications${CClear} ${CGreen}(2) -${CClear} $amtmemailfailuredisp${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}Set Email Rate Limit (per hour)${CClear} ${CGreen}(r) - $ratelimitdisp${CClear}"
+ echo ""
+ read -p "Please select? (1-2, r=Set Email Rate Limit, t=Test Email, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) if [ "$amtmemailsuccess" = "0" ]; then amtmemailsuccess=1; amtmemailsuccessdisp="${CGreen}Y${CCyan}"; elif [ "$amtmemailsuccess" = "1" ]; then amtmemailsuccess=0; amtmemailsuccessdisp="${CRed}N${CCyan}"; fi;;
+ 2) if [ "$amtmemailfailure" = "0" ]; then amtmemailfailure=1; amtmemailfailuredisp="${CGreen}Y${CCyan}"; elif [ "$amtmemailfailure" = "1" ]; then amtmemailfailure=0; amtmemailfailuredisp="${CRed}N${CCyan}"; fi;;
+ [Tt])
+ if [ -f "$CUSTOM_EMAIL_LIBFile" ]
+ then
+ . "$CUSTOM_EMAIL_LIBFile"
+
+ if [ -z "${CEM_LIB_VERSION:+xSETx}" ] || \
+ _CheckLibraryUpdates_CEM_ "$CUSTOM_EMAIL_LIBDir" quiet
+ then
+ _DownloadCEMLibraryFile_ "update"
+ fi
+ else
+ _DownloadCEMLibraryFile_ "install"
+ fi
+
+ cemIsFormatHTML=true
+ cemIsVerboseMode=true ## true OR false ##
+ emailBodyTitle="Testing Email Notification"
+ emailSubject="TEST: VPNMON-R3 Email Notification"
+ tmpEMailBodyFile="/tmp/var/tmp/tmpEMailBody_${scriptFileNTag}.$$.TXT"
+
+ {
+ printf "This is a TEST to check & verify if sending email notifications is working well from VPNMON-R3.\n"
+ } > "$tmpEMailBodyFile"
+
+ _SendEMailNotification_ "VPNMON-R3 v$version" "$emailSubject" "$tmpEMailBodyFile" "$emailBodyTitle"
+
+ echo ; echo
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ [Rr])
+ echo ""
+ read -p "Please enter new Email Rate Limit (per hour)? (0=disabled, 1-9999, e=Exit): " newratelimit
+ if [ "$newratelimit" = "e" ]
+ then
+ echo -e "\n[Exiting]"; sleep 2
+ elif echo "$newratelimit" | grep -qE "^(0|[1-9][0-9]{0,3})$" && \
+ [ "$newratelimit" -ge 0 ] && [ "$newratelimit" -le 9999 ]
+ then
+ ratelimit="$newratelimit"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Email Rate Limit entered (per hour): $ratelimit" >> $logfile
+ saveconfig
+ else
+ previousValue="$ratelimit"
+ ratelimit="${ratelimit:=0}"
+ [ "$ratelimit" != "$previousValue" ] && \
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Email Rate Limit entered (per hour): $ratelimit" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ [Ee])
+ saveconfig
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: AMTM Email notification configuration saved" >> $logfile
+ timer="$timerloop"
+ break;;
+ esac
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vpnserverlistmaint lets you pick which vpn slot server list you want to edit/maintain
+
+vpnserverlistmaint()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPN Client Slot Server List Maintenance ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate which VPN Slot Server List you would like to edit/maintain.${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to launch and edit the list with the NANO text editor${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} VPN INSTRUCTIONS: Enter a single column of IP addresses or hostnames, as required by${CClear}"
+ echo -e "${InvGreen} ${CClear} your VPN provider. ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} NANO INSTRUCTIONS: CTRL-O + Enter (save), CTRL-X (exit)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN1${CClear} ${CGreen}(1)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svr1.txt ]; then
+ iplist=$(awk -vORS=, '{ print $1 }' /jffs/addons/vpnmon-r3.d/vr3svr1.txt | sed 's/,$/\n/')
+ echo -en "${InvGreen} ${CClear} Contents: "; printf "%.75s>\n" $iplist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN2${CClear} ${CGreen}(2)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svr2.txt ]; then
+ iplist=$(awk -vORS=, '{ print $1 }' /jffs/addons/vpnmon-r3.d/vr3svr2.txt | sed 's/,$/\n/')
+ echo -en "${InvGreen} ${CClear} Contents: "; printf "%.75s>\n" $iplist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ if [ "$availableslots" = "1 2" ]
+ then
+ echo ""
+ read -p "Please select? (1-2, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr1.txt;;
+ 2) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr2.txt;;
+ [Ee])
+ timer="$timerloop"
+ break;;
+ esac
+ fi
+
+ if [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN3${CClear} ${CGreen}(3)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svr3.txt ]; then
+ iplist=$(awk -vORS=, '{ print $1 }' /jffs/addons/vpnmon-r3.d/vr3svr3.txt | sed 's/,$/\n/')
+ echo -en "${InvGreen} ${CClear} Contents: "; printf "%.75s>\n" $iplist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN4${CClear} ${CGreen}(4)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svr4.txt ]; then
+ iplist=$(awk -vORS=, '{ print $1 }' /jffs/addons/vpnmon-r3.d/vr3svr4.txt | sed 's/,$/\n/')
+ echo -en "${InvGreen} ${CClear} Contents: "; printf "%.75s>\n" $iplist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN5${CClear} ${CGreen}(5)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svr5.txt ]; then
+ iplist=$(awk -vORS=, '{ print $1 }' /jffs/addons/vpnmon-r3.d/vr3svr5.txt | sed 's/,$/\n/')
+ echo -en "${InvGreen} ${CClear} Contents: "; printf "%.75s>\n" $iplist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo ""
+ read -p "Please select? (1-5, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 1) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr1.txt;;
+ 2) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr2.txt;;
+ 3) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr3.txt;;
+ 4) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr4.txt;;
+ 5) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3svr5.txt;;
+ [Ee])
+ timer="$timerloop"
+ break;;
+ esac
+ fi
+
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# wgserverlistmaint lets you pick which wg slot server list you want to edit/maintain
+
+wgserverlistmaint()
+{
+
+if [ "$availableslots" = "1 2" ]
+ then
+ return
+fi
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} WG Client Slot Server List Maintenance ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate which WG Slot Server List you would like to edit/maintain.${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to launch and edit the list with the NANO text editor${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} WG INSTRUCTIONS: Enter a 6-field comma-delimited row of WG Connections${CClear}"
+ echo -e "${InvGreen} ${CClear} Format: ConnectionName,EndpointIP,EndpointPort,PrivateKey,PublicKey,PreSharedKey(Opt)${CClear}"
+ echo -e "${InvGreen} ${CClear} Example: ${CGreen}City WG,143.32.55.23,34334,fasdkaffkasdjfj=,221t949as2323kf=,23fj39fffjdaf=${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} NANO INSTRUCTIONS: CTRL-O + Enter (save), CTRL-X (exit)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}WG1${CClear} ${CGreen}(6)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3wgsvr1.txt ]; then
+ wglist=$(awk -F, '{printf "%s%s", sep, $1; sep=","} END {print ""}' /jffs/addons/vpnmon-r3.d/vr3wgsvr1.txt | awk '{print substr($0, 1, 75) ">"}')
+ echo -en "${InvGreen} ${CClear} Contents: "; echo $wglist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}WG2${CClear} ${CGreen}(7)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3wgsvr2.txt ]; then
+ wglist=$(awk -F, '{printf "%s%s", sep, $1; sep=","} END {print ""}' /jffs/addons/vpnmon-r3.d/vr3wgsvr2.txt | awk '{print substr($0, 1, 75) ">"}')
+ echo -en "${InvGreen} ${CClear} Contents: "; echo $wglist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}WG3${CClear} ${CGreen}(8)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3wgsvr3.txt ]; then
+ wglist=$(awk -F, '{printf "%s%s", sep, $1; sep=","} END {print ""}' /jffs/addons/vpnmon-r3.d/vr3wgsvr3.txt | awk '{print substr($0, 1, 75) ">"}')
+ echo -en "${InvGreen} ${CClear} Contents: "; echo $wglist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}WG4${CClear} ${CGreen}(9)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3wgsvr4.txt ]; then
+ wglist=$(awk -F, '{printf "%s%s", sep, $1; sep=","} END {print ""}' /jffs/addons/vpnmon-r3.d/vr3wgsvr4.txt | awk '{print substr($0, 1, 75) ">"}')
+ echo -en "${InvGreen} ${CClear} Contents: "; echo $wglist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}WG5${CClear} ${CGreen}(0)${CClear}"
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3wgsvr5.txt ]; then
+ wglist=$(awk -F, '{printf "%s%s", sep, $1; sep=","} END {print ""}' /jffs/addons/vpnmon-r3.d/vr3wgsvr5.txt | awk '{print substr($0, 1, 75) ">"}')
+ echo -en "${InvGreen} ${CClear} Contents: "; echo $wglist
+ else
+ echo -e "${InvGreen} ${CClear} Contents: "
+ fi
+ echo ""
+ read -p "Please select? (6-0, e=Exit): " SelectSlot
+ case $SelectSlot in
+ 6) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3wgsvr1.txt;;
+ 7) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3wgsvr2.txt;;
+ 8) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3wgsvr3.txt;;
+ 9) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3wgsvr4.txt;;
+ 0) export TERM=linux; nano +999999 --linenumbers /jffs/addons/vpnmon-r3.d/vr3wgsvr5.txt;;
+ [Ee])
+ timer="$timerloop"
+ break;;
+ esac
+
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# vpnserverlistautomation lets you pick which vpn slot server list automation you want to edit/execute
+
+vpnserverlistautomation()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} WG/VPN Client Slot Server List Automation ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate which VPN Slot Automation Script you would like to edit/execute.${CClear}"
+ echo -e "${InvGreen} ${CClear} Use the corresponding ${CGreen}()${CClear} key to edit or launch your update statements${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} VPN INSTRUCTIONS: Insert CURL statement that outputs a single-column Server IP list${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} WG INSTRUCTIONS: Insert CURL statement that outputs a 6-field comma-separated list${CClear}"
+ echo -e "${InvGreen} ${CClear} Format: ConnectionName,EndpointIP,EndpointPort,PrivateKey,PublicKey,PreSharedKey(Opt)${CClear}"
+ echo -e "${InvGreen} ${CClear} Example: ${CGreen}City WG,143.32.55.23,34334,fasdkaffkasdjfj=,221t949as2323kf=,23fj39fffjdaf=${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN1${CClear} ${CGreen}(e1)${CClear} View/Edit | ${CGreen}(x1)${CClear} Execute | ${CGreen}(s1)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$automation1" ] || [ "$automation1" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ automation1unenc=$(echo "$automation1" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$automation1unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN2${CClear} ${CGreen}(e2)${CClear} View/Edit | ${CGreen}(x2)${CClear} Execute | ${CGreen}(s2)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$automation2" ] || [ "$automation2" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ automation2unenc=$(echo "$automation2" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$automation2unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ if [ "$availableslots" = "1 2" ]; then
+ echo ""
+ read -p "Please select? (e1-e2, x1-x2, s1-s2, e=Exit): " SelectSlot2
+ case $SelectSlot2 in
+ e1)
+ echo ""
+ if [ "$automation1" = "" ] || [ -z "$automation1" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation1" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation1new
+ if [ "$automation1new" = "" ] || [ -z "$automation1new" ]; then
+ automation1=""
+ saveconfig
+ elif [ "$automation1new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation1=`echo $automation1new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 1" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x1)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation1unenc=$(echo "$automation1" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation1unenc"
+ echo ""
+ eval "$automation1unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr1.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 1 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 1" >> $logfile
+ echo ""
+ skynetwhitelist 1
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 1 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s1)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr1.txt "VPNMON-R3 VPN Slot 1 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 1 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 1" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e2)
+ echo ""
+ if [ "$automation2" = "" ] || [ -z "$automation2" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation2" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation2new
+ if [ "$automation2new" = "" ] || [ -z "$automation2new" ]; then
+ automation2=""
+ saveconfig
+ elif [ "$automation2new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation2=`echo $automation2new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 2" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x2)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation2unenc=$(echo "$automation2" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation2unenc"
+ echo ""
+ eval "$automation2unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr2.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 2 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 2" >> $logfile
+ echo ""
+ skynetwhitelist 2
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 2 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s2)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr2.txt "VPNMON-R3 VPN Slot 2 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 2 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 2" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ [Ee])
+ timer="$timerloop"
+ break;;
+ esac
+ fi
+
+ if [ "$availableslots" = "1 2 3 4 5" ]; then
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN3${CClear} ${CGreen}(e3)${CClear} View/Edit | ${CGreen}(x3)${CClear} Execute | ${CGreen}(s3)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$automation3" ] || [ "$automation3" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ automation3unenc=$(echo "$automation3" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$automation3unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN4${CClear} ${CGreen}(e4)${CClear} View/Edit | ${CGreen}(x4)${CClear} Execute | ${CGreen}(s4)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$automation4" ] || [ "$automation4" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ automation4unenc=$(echo "$automation4" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$automation4unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite}VPN5${CClear} ${CGreen}(e5)${CClear} View/Edit | ${CGreen}(x5)${CClear} Execute | ${CGreen}(s5)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$automation5" ] || [ "$automation5" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ automation5unenc=$(echo "$automation5" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$automation5unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+
+ ##-------------------------------------##
+ ## Added by Dan G. [2025-Jul-15] ##
+ ##-------------------------------------##
+
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG1${CClear} ${CGreen}(e6)${CClear} View/Edit | ${CGreen}(x6)${CClear} Execute | ${CGreen}(s6)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$wgautomation1" ] || [ "$wgautomation1" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ wgautomation1unenc=$(echo "$wgautomation1" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$wgautomation1unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG2${CClear} ${CGreen}(e7)${CClear} View/Edit | ${CGreen}(x7)${CClear} Execute | ${CGreen}(s7)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$wgautomation2" ] || [ "$wgautomation2" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ wgautomation2unenc=$(echo "$wgautomation2" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$wgautomation2unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG3${CClear} ${CGreen}(e8)${CClear} View/Edit | ${CGreen}(x8)${CClear} Execute | ${CGreen}(s8)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$wgautomation3" ] || [ "$wgautomation3" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ wgautomation3unenc=$(echo "$wgautomation3" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$wgautomation3unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG4${CClear} ${CGreen}(e9)${CClear} View/Edit | ${CGreen}(x9)${CClear} Execute | ${CGreen}(s9)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$wgautomation4" ] || [ "$wgautomation4" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ wgautomation4unenc=$(echo "$wgautomation4" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$wgautomation4unenc"
+ fi
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} ${InvDkGray}${CWhite} WG5${CClear} ${CGreen}(e0)${CClear} View/Edit | ${CGreen}(x0)${CClear} Execute | ${CGreen}(s0)${CClear} Skynet WL Import${CClear}"
+ if [ -z "$wgautomation5" ] || [ "$wgautomation5" = "" ]; then
+ echo -e "${InvGreen} ${CClear} Contents: "
+ else
+ wgautomation5unenc=$(echo "$wgautomation5" | openssl enc -d -base64 -A)
+ echo -en "${InvGreen} ${CClear} Contents: ${InvDkGray}${CWhite}"; printf "%.75s>\n" "$wgautomation5unenc"
+ fi
+ echo ""
+ read -p "Please select? (e1-e0, x1-x0, s1-s0, e=Exit): " SelectSlot5
+ case $SelectSlot5 in
+ e1)
+ echo ""
+ if [ "$automation1" = "" ] || [ -z "$automation1" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation1" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation1new
+ if [ "$automation1new" = "" ] || [ -z "$automation1new" ]; then
+ automation1=""
+ saveconfig
+ elif [ "$automation1new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation1=`echo $automation1new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 1" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x1)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation1unenc=$(echo "$automation1" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation1unenc"
+ echo ""
+ eval "$automation1unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr1.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 1 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 1" >> $logfile
+ echo ""
+ skynetwhitelist 1
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 1 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s1)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr1.txt "VPNMON-R3 VPN Slot 1 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 1 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 1" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e2)
+ echo ""
+ if [ "$automation2" = "" ] || [ -z "$automation2" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation2" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation2new
+ if [ "$automation2new" = "" ] || [ -z "$automation2new" ]; then
+ automation2=""
+ saveconfig
+ elif [ "$automation2new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation2=`echo $automation2new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 2" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x2)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation2unenc=$(echo "$automation2" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation2unenc"
+ echo ""
+ eval "$automation2unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr2.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 2 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 2" >> $logfile
+ echo ""
+ skynetwhitelist 2
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 2 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s2)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr2.txt "VPNMON-R3 VPN Slot 2 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 2 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 2" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e3)
+ echo ""
+ if [ "$automation3" = "" ] || [ -z "$automation3" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation3" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation3new
+ if [ "$automation3new" = "" ] || [ -z "$automation3new" ]; then
+ automation3=""
+ saveconfig
+ elif [ "$automation3new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation3=`echo $automation3new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 3" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x3)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation3unenc=$(echo "$automation3" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation3unenc"
+ echo ""
+ eval "$automation3unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr3.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 3 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 3" >> $logfile
+ echo ""
+ skynetwhitelist 3
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 3 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s3)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr3.txt "VPNMON-R3 VPN Slot 3 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 3 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 3" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e4)
+ echo ""
+ if [ "$automation4" ="" ] || [ -z "$automation4" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation4" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation4new
+ if [ "$automation4new" = "" ] || [ -z "$automation4new" ]; then
+ automation4=""
+ saveconfig
+ elif [ "$automation4new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation4=`echo $automation4new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 4" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x4)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation4unenc=$(echo "$automation4" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation4unenc"
+ echo ""
+ eval "$automation4unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr4.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 4 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 4" >> $logfile
+ echo ""
+ skynetwhitelist 4
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 4 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s4)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr4.txt "VPNMON-R3 VPN Slot 4 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 4 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 4" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e5)
+ echo ""
+ if [ "$automation5" = "" ] || [ -z "$automation5" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$automation5" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' automation5new
+ if [ "$automation5new" = "" ] || [ -z "$automation5new" ]; then
+ automation5=""
+ saveconfig
+ elif [ "$automation5new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ automation5=`echo $automation5new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom VPN Server List Command entered for VPN Slot 5" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x5)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ automation5unenc=$(echo "$automation5" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $automation5unenc"
+ echo ""
+ eval "$automation5unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr5.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to VPN Client Slot 5 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Server List Command executed for VPN Slot 5" >> $logfile
+ echo ""
+ skynetwhitelist 5
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or VPN Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot 5 yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s5)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr5.txt "VPNMON-R3 VPN Slot 5 Import" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of VPN Slot 5 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for VPN Slot 5" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e6)
+ echo ""
+ if [ "$wgautomation1" = "" ] || [ -z "$wgautomation1" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$wgautomation1" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' wgautomation1new
+ if [ "$wgautomation1new" = "" ] || [ -z "$wgautomation1new" ]; then
+ wgautomation1=""
+ saveconfig
+ elif [ "$wgautomation1new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ wgautomation1=`echo $wgautomation1new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom WG Server List Command entered for WG Slot 1" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x6)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ wgautomation1unenc=$(echo "$wgautomation1" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $wgautomation1unenc"
+ echo ""
+ eval "$wgautomation1unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr1.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to WG Client Slot 1 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Server List Command executed for WG Slot 1" >> $logfile
+ echo ""
+ skynetwhitelist wg1
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or WG Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot 1 yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s6)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr1.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 WG Slot 1 Import" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of WG Slot 1 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for WG Slot 1" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e7)
+ echo ""
+ if [ "$wgautomation2" = "" ] || [ -z "$wgautomation2" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$wgautomation2" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' wgautomation2new
+ if [ "$wgautomation2new" = "" ] || [ -z "$wgautomation2new" ]; then
+ wgautomation2=""
+ saveconfig
+ elif [ "$wgautomation2new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ wgautomation2=`echo $wgautomation2new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom WG Server List Command entered for WG Slot 2" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x7)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ wgautomation2unenc=$(echo "$wgautomation2" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $wgautomation2unenc"
+ echo ""
+ eval "$wgautomation2unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr2.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to WG Client Slot 2 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Server List Command executed for WG Slot 2" >> $logfile
+ echo ""
+ skynetwhitelist wg2
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or WG Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot 2 yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s7)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr2.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 WG Slot 2 Import" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of WG Slot 2 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for WG Slot 2" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e8)
+ echo ""
+ if [ "$wgautomation3" = "" ] || [ -z "$wgautomation3" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$wgautomation3" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' wgautomation3new
+ if [ "$wgautomation3new" = "" ] || [ -z "$wgautomation3new" ]; then
+ wgautomation3=""
+ saveconfig
+ elif [ "$wgautomation3new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ wgautomation3=`echo $wgautomation3new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom WG Server List Command entered for WG Slot 3" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x8)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ wgautomation3unenc=$(echo "$wgautomation3" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $wgautomation3unenc"
+ echo ""
+ eval "$wgautomation3unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr3.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to WG Client Slot 3 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Server List Command executed for WG Slot 3" >> $logfile
+ echo ""
+ skynetwhitelist wg3
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or WG Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot 3 yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s8)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr3.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 WG Slot 3 Import" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of WG Slot 3 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for WG Slot 3" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e9)
+ echo ""
+ if [ "$wgautomation4" = "" ] || [ -z "$wgautomation4" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$wgautomation4" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' wgautomation4new
+ if [ "$wgautomation4new" = "" ] || [ -z "$wgautomation4new" ]; then
+ wgautomation4=""
+ saveconfig
+ elif [ "$wgautomation4new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ wgautomation4=`echo $wgautomation4new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom WG Server List Command entered for WG Slot 4" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x9)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ wgautomation4unenc=$(echo "$wgautomation4" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $wgautomation4unenc"
+ echo ""
+ eval "$wgautomation4unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr4.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to WG Client Slot 4 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Server List Command executed for WG Slot 4" >> $logfile
+ echo ""
+ skynetwhitelist wg4
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or WG Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot 4 yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s9)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr4.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 WG Slot 4 Import" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of WG Slot 4 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for WG Slot 4" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ e0)
+ echo ""
+ if [ "$wgautomation5" = "" ] || [ -z "$wgautomation5" ]; then
+ echo -e "${CClear}Old Script: "
+ echo ""
+ else
+ echo -en "${CClear}Old Script: "; echo "$wgautomation5" | openssl enc -d -base64 -A
+ echo ""
+ fi
+ read -rp 'Enter New Script (e=Exit): ' wgautomation5new
+ if [ "$wgautomation5new" = "" ] || [ -z "$wgautomation5new" ]; then
+ wgautomation5=""
+ saveconfig
+ elif [ "$wgautomation5new" = "e" ]; then
+ echo ""; echo -e "${CGreen}[Exiting]${CClear}"; sleep 1
+ else
+ wgautomation5=`echo $wgautomation5new | openssl enc -base64 -A`
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Custom WG Server List Command entered for WG Slot 5" >> $logfile
+ saveconfig
+ fi
+ ;;
+
+ x0)
+ echo ""
+ echo -e "${CGreen}[Executing Script]${CClear}"
+ wgautomation5unenc=$(echo "$wgautomation5" | openssl enc -d -base64 -A)
+ echo -e "${CClear}Running: $wgautomation5unenc"
+ echo ""
+ eval "$wgautomation5unenc" > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ #Determine how many server entries are in each of the vpn slot alternate server files
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt ]; then
+ dlcnt=$(cat /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt | wc -l) >/dev/null 2>&1
+ if [ $dlcnt -lt 1 ]; then
+ dlcnt=0
+ elif [ -z $dlcnt ]; then
+ dlcnt=0
+ fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr5.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Saved to WG Client Slot 5 Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Server List Command executed for WG Slot 5" >> $logfile
+ echo ""
+ skynetwhitelist wg5
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Please check Query Language or WG Service API may be down]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot 5 yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ fi
+ ;;
+
+ s0)
+ echo ""
+ echo -e "${CGreen}[Executing Skynet Whitelist Import]${CClear}"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr5.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 WG Slot 5 Import" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo ""
+ echo -e "${CGreen}[Contents of WG Slot 5 Imported]${CClear}"
+ echo ""
+ echo -e "${CGreen}[Execution Complete]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Skynet Whitelist imported for WG Slot 5" >> $logfile
+ echo ""
+ read -rsp $'Press any key to acknowledge...\n' -n1 key
+ ;;
+
+ [Ee])
+ timer="$timerloop"
+ break;;
+
+ esac
+ fi
+
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# timerloopconfig lets you configure how long you want the timer cycle to last between vpn connection checks
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Nov-02] ##
+##----------------------------------------##
+timerloopconfig()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Timer Loop Configuration / Recovery Timeout Opportunities ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate how long the timer cycle should take between Connectivity checks,${CClear}"
+ echo -e "${InvGreen} ${CClear} as well as the number of Recovery Timeout Opportunities the loop should complete${CClear}"
+ echo -e "${InvGreen} ${CClear} before issuing a connection reset.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Recovery Timeout Opportunities are simply the number of chances the script will${CClear}"
+ echo -e "${InvGreen} ${CClear} give the connection to recover on its own before intervening. With this value${CClear}"
+ echo -e "${InvGreen} ${CClear} defaulting to 1x, if connectivity issues occur within the default 60 second Timer${CClear}"
+ echo -e "${InvGreen} ${CClear} Loop, the connectivity will be reset after those 60 seconds."
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Example: 60 Second Timer Loops with 3x Recovery Timeouts would reset the connection${CClear}"
+ echo -e "${InvGreen} ${CClear} after 3 minutes."
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} (Defaults: Timer Loop = 60 seconds | Recovery Timeouts = 1x)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Current: Timer Loop = ${CGreen}$timerloop sec ${CClear}| Recovery Timeouts: ${CGreen}${recover}x${CClear}"
+ echo
+ read -p "Please enter new Timer Loop value in seconds [10-999] (e=Exit): " newTimerLoop
+ if [ -z "$newTimerLoop" ] || echo "$newTimerLoop" | grep -qE "^(e|E)$"
+ then
+ if echo "$timerloop" | grep -qE "^([1-9][0-9]{0,2})$" && \
+ [ "$timerloop" -ge 10 ] && [ "$timerloop" -le 999 ]
+ then
+ timer="$timerloop"
+ printf "\n${CClear}[Exiting]\n"
+ sleep 1 ; break
+ else
+ printf "\n${CRed}*ERROR*: Please enter a valid number between 10 and 999.${CClear}\n"
+ sleep 3
+ fi
+ elif echo "$newTimerLoop" | grep -qE "^([1-9][0-9]{0,2})$" && \
+ [ "$newTimerLoop" -ge 10 ] && [ "$newTimerLoop" -le 999 ]
+ then
+ timerloop="$newTimerLoop"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Timer Loop configuration saved" >> $logfile
+ saveconfig
+ timer="$timerloop"
+ printf "\n${CClear}[OK]\n"
+ sleep 1
+ else
+ printf "\n${CRed}*ERROR*: Please enter a valid number between 10 and 999.${CClear}\n"
+ sleep 3
+ fi
+
+ echo ""
+ read -p "Please enter new Recovery Timeout value [1-9] (e=Exit): " newRecoveryTimeout
+ if [ -z "$newRecoveryTimeout" ] || echo "$newRecoveryTimeout" | grep -qE "^(e|E)$"
+ then
+ if echo "$recover" | grep -qE "^([1-9])$" && \
+ [ "$recover" -ge 1 ] && [ "$recover" -le 9 ]
+ then
+ printf "\n${CClear}[Exiting]\n"
+ sleep 1 ; break
+ else
+ printf "\n${CRed}*ERROR*: Please enter a valid number between 1 and 9.${CClear}\n"
+ sleep 3
+ fi
+ elif echo "$newRecoveryTimeout" | grep -qE "^([1-9])$" && \
+ [ "$newRecoveryTimeout" -ge 1 ] && [ "$newRecoveryTimeout" -le 9 ]
+ then
+ recover="$newRecoveryTimeout"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New Recovery Timeout Opportunity configuration saved" >> $logfile
+ saveconfig
+ printf "\n${CClear}[OK]\n"
+ sleep 1 ; break
+ else
+ printf "\n${CRed}*ERROR*: Please enter a valid number between 1 and 9.${CClear}\n"
+ sleep 3
+ fi
+done
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# maxping lets you configure how high the vpn tunnel ping will get before it's reset
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-05] ##
+##----------------------------------------##
+maxping()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Maximum Ping Before Reset ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate how high the PING can be across your VPN tunnel before resetting the${CClear}"
+ echo -e "${InvGreen} ${CClear} connection in favor of a different server with a lower PING? A connection with a${CClear}"
+ echo -e "${InvGreen} ${CClear} lower PING may provide better network performance and less latency.${CClear}"
+ echo -e "${InvGreen} ${CClear} (Default = 500 milliseconds, Disabled = 0)${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Current: ${CGreen}$pingreset ms${CClear}"
+ echo
+ read -p "Please enter numeric value (0-999)? (0=Disabled, e=Exit): " newPingReset
+ if echo "$newPingReset" | grep -qE "^(0|[1-9][0-9]{0,2})$" && \
+ [ "$newPingReset" -ge 0 ] && [ "$newPingReset" -le 999 ]
+ then
+ pingreset="$newPingReset"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: PING Reset Configuration saved" >> $logfile
+ saveconfig
+ elif [ -z "$newPingReset" ] || echo "$newPingReset" | grep -qE "^(E|e)$"
+ then
+ echo ; echo -e "${CClear}[Exiting]"
+ timer="$timerloop"
+ sleep 2
+ break
+ else
+ echo
+ echo -e "${CClear}[Please enter value between 0 and 999, e=Exit]"
+ sleep 3
+ fi
+done
+}
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Oct-06] ##
+##-------------------------------------##
+_ValidateCronJobHour_()
+{
+ if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi
+ if echo "$1" | grep -qE "^(0|[1-9][0-9]?)$" && \
+ [ "$1" -ge 0 ] && [ "$1" -lt 24 ]
+ then return 0 ; else return 1 ; fi
+}
+
+_ValidateCronJobMinute_()
+{
+ if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi
+ if echo "$1" | grep -qE "^(0|[1-9][0-9]?)$" && \
+ [ "$1" -ge 0 ] && [ "$1" -lt 60 ]
+ then return 0 ; else return 1 ; fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# schedulevpnreset lets you enable and set a time for a scheduled daily vpn reset
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-06] ##
+##----------------------------------------##
+schedulevpnreset()
+{
+
+while true
+do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPN Reset Scheduler ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to enable and schedule a daily VPN Reset CRON"
+ echo -e "${InvGreen} ${CClear} job. This will reset each monitored VPN connection. (Default = Disabled)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ if [ "$schedule" = "0" ]
+ then
+ echo -e "${InvGreen} ${CClear} Current: ${CRed}Disabled${CClear}"
+ elif [ "$schedule" = "1" ]
+ then
+ schedhrs="$(awk "BEGIN {printf \"%02.f\",${schedulehrs}}")"
+ schedmin="$(awk "BEGIN {printf \"%02.f\",${schedulemin}}")"
+ schedtime="${CGreen}$schedhrs:$schedmin${CClear}"
+ echo -e "${InvGreen} ${CClear} Current: ${CGreen}Enabled, Daily @ $schedtime${CClear}"
+ fi
+ echo
+ read -p 'Schedule Daily Reset? (0=No, 1=Yes, e=Exit): ' newSchedule
+ if [ -z "$newSchedule" ] ; then newSchedule="${schedule:=0}" ; fi
+
+ if [ "$newSchedule" = "0" ]
+ then
+ schedule=0
+ if [ -f /jffs/scripts/services-start ]
+ then
+ sed -i -e '/vpnmon-r3.sh/d' /jffs/scripts/services-start
+ cru d RunVPNMONR3reset
+ schedulehrs=1
+ schedulemin=0
+ echo ""
+ echo -e "${CGreen}[Modifiying SERVICES-START file]..."
+ sleep 2
+ echo ""
+ echo -e "${CGreen}[Modifying CRON jobs]..."
+ sleep 2
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Reset Schedule Disabled" >> $logfile
+ saveconfig
+ timer="$timerloop"
+ break
+ fi
+
+ elif [ "$newSchedule" = "1" ]
+ then
+ schedule=1
+ echo
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPN Reset Scheduler ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below what time you would like to schedule a daily VPN Reset CRON"
+ echo -e "${InvGreen} ${CClear} job. (Default = 1 hr, 0 min = 01:00 = 1:00am)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo
+ read -p 'Schedule HOURS [0-23]?: ' newScheduleHrs
+ if [ -z "$newScheduleHrs" ]
+ then
+ if _ValidateCronJobHour_ "$schedulehrs"
+ then scheduleHrsOK=true
+ else scheduleHrsOK=false
+ fi
+ elif _ValidateCronJobHour_ "$newScheduleHrs"
+ then
+ scheduleHrsOK=true
+ schedulehrs="$newScheduleHrs"
+ else
+ scheduleHrsOK=false
+ schedulehrs="${schedulehrs:=1}"
+ printf "${CRed}*ERROR*: INVALID Entry.${CClear}\n\n"
+ fi
+ read -p 'Schedule MINUTES [0-59]?: ' newScheduleMins
+ if [ -z "$newScheduleMins" ]
+ then
+ if _ValidateCronJobMinute_ "$schedulemin"
+ then scheduleMinsOK=true
+ else scheduleMinsOK=false
+ fi
+ elif _ValidateCronJobMinute_ "$newScheduleMins"
+ then
+ scheduleMinsOK=true
+ schedulemin="$newScheduleMins"
+ else
+ scheduleMinsOK=false
+ schedulemin="${schedulemin:=0}"
+ printf "${CRed}*ERROR*: INVALID Entry.${CClear}\n"
+ fi
+ if ! "$scheduleHrsOK" || ! "$scheduleMinsOK"
+ then
+ doResetSave=false
+ if ! "$scheduleHrsOK" && ! _ValidateCronJobHour_ "$schedulehrs"
+ then schedulehrs=1 ; doResetSave=true
+ fi
+ if ! "$scheduleMinsOK" && ! _ValidateCronJobMinute_ "$schedulemin"
+ then schedulemin=0 ; doResetSave=true
+ fi
+ if "$doResetSave"
+ then
+ schedule=0
+ saveconfig
+ printf "\n${CRed}INVALID input found. Resetting values.${CClear}\n\n"
+ else
+ printf "\n${CRed}INVALID input found. No changes made.${CClear}\n\n"
+ fi
+ echo -e "${CClear}[Exiting]"
+ timer="$timerloop"
+ sleep 3
+ break
+ fi
+ echo
+ echo -e "${CGreen}[Modifying SERVICES-START file]..."
+ sleep 2
+
+ if [ -f /jffs/scripts/services-start ]
+ then
+ if ! grep -q -F "sh /jffs/scripts/vpnmon-r3.sh -reset" /jffs/scripts/services-start
+ then
+ echo 'cru a RunVPNMONR3reset "'"$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"'"' >> /jffs/scripts/services-start
+ cru a RunVPNMONR3reset "$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"
+ else
+ #delete and re-add if it already exists in case there's a time change
+ sed -i -e '/vpnmon-r3.sh/d' /jffs/scripts/services-start
+ cru d RunVPNMONR3reset
+ echo 'cru a RunVPNMONR3reset "'"$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"'"' >> /jffs/scripts/services-start
+ cru a RunVPNMONR3reset "$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"
+ fi
+ else
+ echo 'cru a RunVPNMONR3reset "'"$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"'"' >> /jffs/scripts/services-start
+ chmod 755 /jffs/scripts/services-start
+ cru a RunVPNMONR3reset "$schedulemin $schedulehrs * * * sh /jffs/scripts/vpnmon-r3.sh -reset"
+ fi
+
+ echo
+ echo -e "${CGreen}[Modifying CRON jobs]..."
+ sleep 2
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Reset Schedule Enabled" >> $logfile
+ saveconfig
+ timer="$timerloop"
+ break
+
+ elif [ "$newSchedule" = "e" ]
+ then
+ echo ; echo -e "${CClear}[Exiting]"
+ timer="$timerloop"
+ sleep 2
+ break
+ else
+ schedule="${schedule:=0}"
+ schedulehrs="${schedulehrs:=1}"
+ schedulemin="${schedulemin:=0}"
+ saveconfig
+ fi
+
+done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# autostart lets you enable the ability for vpnmon-r3 to autostart after a router reboot
+
+autostart()
+{
+
+while true; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Reboot Protection ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Please indicate below if you would like to enable VPNMON-R3 to autostart after a"
+ echo -e "${InvGreen} ${CClear} router reboot. This will ensure continued, uninterrupted VPN connection monitoring."
+ echo -e "${InvGreen} ${CClear} (Default = Disabled)"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ if [ "$autostart" = "0" ]
+ then
+ echo -e "${InvGreen} ${CClear} Current: ${CRed}Disabled${CClear}"
+ elif [ "$autostart" = "1" ]
+ then
+ echo -e "${InvGreen} ${CClear} Current: ${CGreen}Enabled${CClear}"
+ fi
+ echo
+ read -p 'Enable Reboot Protection? (0=No, 1=Yes, e=Exit): ' newAutoStart
+ # Use default value on enter keypress or invalid input #
+ if [ -z "$newAutoStart" ] ; then newAutoStart="${autostart:=0}" ; fi
+
+ if [ "$newAutoStart" = "0" ]
+ then
+ autostart=0
+ if [ -f /jffs/scripts/post-mount ]
+ then
+ sed -i -e '/vpnmon-r3.sh/d' /jffs/scripts/post-mount
+ echo ""
+ echo -e "${CGreen}[Modifying POST-MOUNT file]..."
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Reboot Protection Disabled" >> $logfile
+ saveconfig
+ sleep 2
+ timer="$timerloop"
+ break
+ fi
+
+ elif [ "$newAutoStart" = "1" ]
+ then
+ autostart=1
+ if [ -f /jffs/scripts/post-mount ]
+ then
+ if ! grep -q -F "(sleep 30 && /jffs/scripts/vpnmon-r3.sh -screen) & # Added by vpnmon-r3" /jffs/scripts/post-mount
+ then
+ echo "(sleep 30 && /jffs/scripts/vpnmon-r3.sh -screen) & # Added by vpnmon-r3" >> /jffs/scripts/post-mount
+ echo
+ echo -e "${CGreen}[Modifying POST-MOUNT file]..."
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Reboot Protection Enabled" >> $logfile
+ saveconfig
+ sleep 2
+ timer="$timerloop"
+ break
+ else
+ saveconfig
+ sleep 1
+ fi
+
+ else
+ echo "#!/bin/sh" > /jffs/scripts/post-mount
+ echo "" >> /jffs/scripts/post-mount
+ echo "(sleep 30 && /jffs/scripts/vpnmon-r3.sh -screen) & # Added by vpnmon-r3" >> /jffs/scripts/post-mount
+ chmod 755 /jffs/scripts/post-mount
+ echo
+ echo -e "${CGreen}[Modifying POST-MOUNT file]..."
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Reboot Protection Enabled" >> $logfile
+ saveconfig
+ sleep 2
+ timer="$timerloop"
+ break
+ fi
+
+ elif [ "$newAutoStart" = "e" ]
+ then
+ echo ; echo -e "${CClear}[Exiting]"
+ timer="$timerloop"
+ sleep 2
+ break
+ else
+ autostart="${autostart:=0}"
+ saveconfig
+ fi
+
+done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# trimlogs will cut down log size (in rows) based on custom value
+
+trimlogs()
+{
+ if [ "$logsize" -gt 0 ]
+ then
+ currlogsize="$(wc -l $logfile | awk '{ print $1 }')" # Determine the number of rows in the log
+
+ if [ "$currlogsize" -gt "$logsize" ] # If it's bigger than the max allowed, tail/trim it!
+ then
+ echo "$(tail -$logsize $logfile)" > $logfile
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Trimmed the log file down to $logsize lines" >> $logfile
+ fi
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# saveconfig saves the vpnmon-r3.cfg file after every major change, and applies that to the script on the fly
+
+saveconfig()
+{
+ { echo 'availableslots="'"$availableslots"'"'
+ echo 'PINGHOST="'"$PINGHOST"'"'
+ echo 'logsize='$logsize
+ echo 'timerloop='$timerloop
+ echo 'recovery='$recovery
+ echo 'schedule='$schedule
+ echo 'schedulehrs='$schedulehrs
+ echo 'schedulemin='$schedulemin
+ echo 'autostart='$autostart
+ echo 'pingreset='$pingreset
+ echo 'automation1="'"$automation1"'"'
+ echo 'automation2="'"$automation2"'"'
+ echo 'automation3="'"$automation3"'"'
+ echo 'automation4="'"$automation4"'"'
+ echo 'automation5="'"$automation5"'"'
+ echo 'wgautomation1="'"$wgautomation1"'"'
+ echo 'wgautomation2="'"$wgautomation2"'"'
+ echo 'wgautomation3="'"$wgautomation3"'"'
+ echo 'wgautomation4="'"$wgautomation4"'"'
+ echo 'wgautomation5="'"$wgautomation5"'"'
+ echo 'refreshserverlists='$refreshserverlists
+ echo 'unboundclient='$unboundclient
+ echo 'unboundwgclient='$unboundwgclient
+ echo 'unboundshowip='$unboundshowip
+ echo 'monitorwan='$monitorwan
+ echo 'useovpn='$useovpn
+ echo 'usewg='$usewg
+ echo 'updateskynet='$updateskynet
+ echo 'amtmemailsuccess='$amtmemailsuccess
+ echo 'amtmemailfailure='$amtmemailfailure
+ echo 'rstspdmerlin='$rstspdmerlin
+ echo 'ratelimit='$ratelimit
+ } > "$config"
+
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: New vpnmon-r3.cfg File Saved" >> $logfile
+
+ if [ -f "$config" ]
+ then
+ source "$config"
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# VPN_GetClientState was created by @Martinski in many thanks to trying to eliminate unknown operand errors due to null
+# vpn_clientX_state values
+
+_VPN_GetClientState_()
+{
+ if [ $# -lt 1 ] || [ -z "$1" ] || ! echo "$1" | grep -qE "^[1-5]$"
+ then echo "**ERROR**" ; return 1 ; fi
+
+ local nvramVal="$($timeoutcmd$timeoutsec nvram get "vpn_client${1}_state")"
+ if [ -z "$nvramVal" ] || ! echo "$nvramVal" | grep -qE "^[+-]?[0-9]$"
+ then echo "0" ; else echo "$nvramVal" ; fi
+ return 0
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# WG_GetClientState is based off _VPN_GetClientState_
+
+_WG_GetClientState_()
+{
+ if [ $# -lt 1 ] || [ -z "$1" ] || ! echo "$1" | grep -qE "^[1-5]$"
+ then echo "**ERROR**" ; return 1 ; fi
+
+ # Inspiration from ZebMcKayHan's WGC Watchdog Script
+ last_handshake=$(wg show wgc$1 latest-handshakes | awk '{print $2}') >/dev/null 2>&1
+
+ if [ -z $last_handshake ]
+ then
+ WGnvramVal=0 #disconnected
+ else
+ WGnvramVal=2 #connected
+ fi
+
+ #local WGnvramVal="$($timeoutcmd$timeoutsec nvram get "wgc${1}_enable")"
+ if [ -z "$WGnvramVal" ] || ! echo "$WGnvramVal" | grep -qE "^[+-]?[0-9]$"
+ then echo "0" ; else echo "$WGnvramVal" ; fi
+ return 0
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+
+########################################################################
+# AMTM Email Notification Functionality generously donated by @Martinski!
+#
+# Creation Date: 2020-Jun-11 [Martinski W.]
+# Last Modified: 2024-Feb-07 [Martinski W.]
+# Modified for VPNMON-R3 Purposes [Viktor Jaep]
+########################################################################
+
+#-----------------------------------------------------------#
+_DownloadCEMLibraryFile_()
+{
+ local msgStr retCode
+ case "$1" in
+ update) msgStr="Updating" ;;
+ install) msgStr="Installing" ;;
+ *) return 1 ;;
+ esac
+
+ printf "\33[2K\r"
+ printf "${CGreen}\r[INFO: ${msgStr} the shared AMTM email library script file to support email notifications...]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: ${msgStr} the shared AMTM email library script file to support email notifications..." >> $logfile
+
+ mkdir -m 755 -p "$CUSTOM_EMAIL_LIBDir"
+ curl -kLSs --retry 3 --retry-delay 5 --retry-connrefused \
+ "${CEM_LIB_URL}/$CUSTOM_EMAIL_LIBName" -o "$CUSTOM_EMAIL_LIBFile"
+ curlCode="$?"
+
+ if [ "$curlCode" -eq 0 ] && [ -f "$CUSTOM_EMAIL_LIBFile" ]
+ then
+ retCode=0
+ chmod 755 "$CUSTOM_EMAIL_LIBFile"
+ . "$CUSTOM_EMAIL_LIBFile"
+ #printf "\nDone.\n"
+ else
+ retCode=1
+ printf "\33[2K\r"
+ printf "${CRed}\r[ERROR: Unable to download the shared library script file ($CUSTOM_EMAIL_LIBName).]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - **ERROR**: Unable to download the shared AMTM email library script file [$CUSTOM_EMAIL_LIBName]." >> $logfile
+ fi
+ return "$retCode"
+}
+
+#-----------------------------------------------------------#
+# ARG1: The email name/alias to be used as "FROM_NAME"
+# ARG2: The email Subject string.
+# ARG3: Full path of file containing the email Body text.
+# ARG4: The email Body Title string [OPTIONAL].
+#-----------------------------------------------------------#
+_SendEMailNotification_()
+{
+ if [ -z "${amtmIsEMailConfigFileEnabled:+xSETx}" ]
+ then
+ printf "\33[2K\r"
+ printf "${CRed}\r[ERROR: Email library script ($CUSTOM_EMAIL_LIBFile) *NOT* FOUND.]${CClear}"
+ sleep 5
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - **ERROR**: Email library script [$CUSTOM_EMAIL_LIBFile] *NOT* FOUND." >> $logfile
+ return 1
+ fi
+
+ if [ $# -lt 3 ] || [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
+ then
+ printf "\33[2K\r"
+ printf "${CRed}\r[ERROR: INSUFFICIENT email parameters]${CClear}"
+ sleep 5
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - **ERROR**: INSUFFICIENT email parameters." >> $logfile
+ return 1
+ fi
+ local retCode emailBodyTitleStr=""
+
+ [ $# -gt 3 ] && [ -n "$4" ] && emailBodyTitleStr="$4"
+
+ FROM_NAME="$1"
+ _SendEMailNotification_CEM_ "$2" "-F=$3" "$emailBodyTitleStr"
+ retCode="$?"
+
+ if [ "$retCode" -eq 0 ]
+ then
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Email notification was sent successfully ($2)]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Email notification was sent successfully [$2]" >> $logfile
+ sleep 5
+ else
+ printf "\33[2K\r"
+ printf "${CRed}\r[ERROR: Failure to send email notification (Error Code: $retCode - $2).]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - **ERROR**: Failure to send email notification [$2]" >> $logfile
+ sleep 5
+ fi
+
+ return "$retCode"
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# sendmessage is a function that sends an AMTM email based on activity within VPNMON-R3
+# $1 = Success/Failure 0/1
+# $2 = Component
+# $3 = VPN Slot
+
+sendmessage()
+{
+
+ #If AMTM email functionality is disabled, return back to the function call
+ if [ "$amtmemailsuccess" = "0" ] && [ "$amtmemailfailure" = "0" ]; then
+ return
+ fi
+
+ #Load, install or update the shared AMTM Email integration library
+ if [ -f "$CUSTOM_EMAIL_LIBFile" ]
+ then
+ . "$CUSTOM_EMAIL_LIBFile"
+
+ if [ -z "${CEM_LIB_VERSION:+xSETx}" ] || \
+ _CheckLibraryUpdates_CEM_ "$CUSTOM_EMAIL_LIBDir" quiet
+ then
+ _DownloadCEMLibraryFile_ "update"
+ fi
+ else
+ _DownloadCEMLibraryFile_ "install"
+ fi
+
+ cemIsFormatHTML=true
+ cemIsVerboseMode=false
+ tmpEMailBodyFile="/tmp/var/tmp/tmpEMailBody_${scriptFileNTag}.$$.TXT"
+
+ ratelimiter
+ emaillimit="$?"
+ if [ "$emaillimit" -eq 0 ]
+ then
+
+ #Pick the scenario and send email
+ if [ "$1" = "1" ] && [ "$amtmemailfailure" = "1" ]; then
+ if [ "$2" = "Recovering from WAN Down" ]; then
+ emailSubject="ALERT: Router Recovering from WAN Down"
+ emailBodyTitle="ALERT: Router Recovering from WAN Down"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "ALERT: VPNMON-R3 is currently recovering from a WAN Down Situation!\n"
+ printf "Router has detected a WAN Link/Modem and waited 300 seconds for general network.\n"
+ printf "connectivity to stabilize before re-establishing VPN connectivity.\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Slot In Error State" ]; then
+ emailSubject="FAILURE: VPN Slot $3 in Error State"
+ emailBodyTitle="FAILURE: VPN Slot $3 in Error State"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "FAILURE: VPNMON-R3 has detected that VPN Slot $3 is in an error state. VPN Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Tunnel Disconnected" ]; then
+ emailSubject="FAILURE: VPN Slot $3 has Disconnected"
+ emailBodyTitle="FAILURE: VPN Slot $3 has Disconnected"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "FAILURE: VPNMON-R3 has detected that VPN Slot $3 has disconnected. VPN Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Slot Is Non-Responsive" ]; then
+ emailSubject="FAILURE: VPN Slot $3 is Non-Responsive"
+ emailBodyTitle="FAILURE: VPN Slot $3 is Non-Responsive"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "FAILURE: VPNMON-R3 has detected that VPN Slot $3 is non-responsive. VPN Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Slot Exceeded Max Ping" ]; then
+ emailSubject="WARNING: VPN Slot $3 Exceeded Max Ping"
+ emailBodyTitle="WARNING: VPN Slot $3 Exceeded Max Ping"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that VPN Slot $3 exceeded max ping. VPN Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Slot Not Synced With Unbound" ]; then
+ emailSubject="WARNING: VPN Slot $3 Not Synced with Unbound"
+ emailBodyTitle="WARNING: VPN Slot $3 Not Synced with Unbound"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that VPN Slot $3 is not synced with Unbound. VPN Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Slot Not Synced With Unbound" ]; then
+ emailSubject="WARNING: WG Slot $3 Not Synced with Unbound"
+ emailBodyTitle="WARNING: WG Slot $3 Not Synced with Unbound"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that WG Slot $3 is not synced with Unbound. WG Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ ##-------------------------------------##
+ ## Modified by Dan G. [2025-Jul-16] ##
+ ##-------------------------------------##
+ elif [ "$2" = "VPN Server List Query Yielded 0 Rows" ]; then
+ emailSubject="WARNING: VPN Slot $3 Server List Query Yielded 0 Rows"
+ emailBodyTitle="WARNING: VPN Slot $3 Server List Query Yielded 0 Rows"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that the Custom Server List Query for VPN Slot $3 yielded 0 results.\n"
+ printf "This may be due to an error in the query, or the VPN provider API service may be down or unreachable."
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Server List Query Yielded 0 Rows" ]; then
+ emailSubject="WARNING: WG Slot $3 Server List Query Yielded 0 Rows"
+ emailBodyTitle="WARNING: WG Slot $3 Server List Query Yielded 0 Rows"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that the Custom Server List Query for WG Slot $3 yielded 0 results.\n"
+ printf "This may be due to an error in the query, or the VPN provider API service may be down or unreachable."
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Slot Exceeded Max Ping" ]; then
+ emailSubject="WARNING: WG Slot $3 Exceeded Max Ping"
+ emailBodyTitle="WARNING: WG Slot $3 Exceeded Max Ping"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that WG Slot $3 exceeded max ping. WG Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Handshake Exceeded" ]; then
+ emailSubject="WARNING: WG Slot $3 Exceeded Handshake"
+ emailBodyTitle="WARNING: WG Slot $3 Exceeded Handshake"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that WG Slot $3 exceeded a 200s handshake. WG Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Tunnel Disconnected" ]; then
+ emailSubject="WARNING: WG Slot $3 Tunnel Disconnected"
+ emailBodyTitle="WARNING: WG Slot $3 Tunnel Disconnected"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that WG Slot $3 tunnel disconnected. WG Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Slot Is Non-Responsive" ]; then
+ emailSubject="WARNING: WG Slot $3 is Non-Responsive"
+ emailBodyTitle="WARNING: WG Slot $3 is Non-Responsive"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "WARNING: VPNMON-R3 has detected that WG Slot $3 is not responding. WG Slot $3 has been reset.\n"
+ printf "Please check your network environment and configuration if this error continues to persist."
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ fi
+ _SendEMailNotification_ "VPNMON-R3 v$version" "$emailSubject" "$tmpEMailBodyFile" "$emailBodyTitle"
+ fi
+
+ if [ "$1" = "0" ] && [ "$amtmemailsuccess" = "1" ]; then
+ if [ "$2" = "VPN Connection Scheduled Reset" ]; then
+ emailSubject="SUCCESS: VPN Slot $3 Manual/Scheduled Reset"
+ emailBodyTitle="SUCCESS: VPN Slot $3 Manual/Scheduled Reset"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 completed a successful manual/scheduled reset on VPN Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Reset" ]; then
+ emailSubject="SUCCESS: VPN Slot $3 Manual Reset"
+ emailBodyTitle="SUCCESS: VPN Slot $3 Manual Reset"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 completed a successful manual reset on VPN Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "VPN Killed" ]; then
+ emailSubject="SUCCESS: VPN Slot $3 Manually Stopped & Unmonitored"
+ emailBodyTitle="SUCCESS: VPN Slot $3 Manually Stopped & Unmonitored"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 successfully manually stopped and unmonitored VPN Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ ##-------------------------------------##
+ ## Added by Dan G. [2025-Jul-16] ##
+ ##-------------------------------------##
+ elif [ "$2" = "WG Connection Scheduled Reset" ]; then
+ emailSubject="SUCCESS: WG Slot $3 Manual/Scheduled Reset"
+ emailBodyTitle="SUCCESS: WG Slot $3 Manual/Scheduled Reset"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 completed a successful manual/scheduled reset on WG Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Reset" ]; then
+ emailSubject="SUCCESS: WG Slot $3 Manual Reset"
+ emailBodyTitle="SUCCESS: WG Slot $3 Manual Reset"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 completed a successful manual reset on WG Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ elif [ "$2" = "WG Killed" ]; then
+ emailSubject="SUCCESS: WG Slot $3 Manually Stopped & Unmonitored"
+ emailBodyTitle="SUCCESS: WG Slot $3 Manually Stopped & Unmonitored"
+ {
+ printf "Date/Time: $(date +'%b %d %Y %X')\n"
+ printf "Asus Router Model: ${ROUTERMODEL}\n"
+ printf "Firmware/Build Number: ${FWBUILD}\n"
+ printf "\n"
+ printf "SUCCESS: VPNMON-R3 successfully manually stopped and unmonitored WG Slot $3\n"
+ printf "\n"
+ } > "$tmpEMailBodyFile"
+ fi
+ _SendEMailNotification_ "VPNMON-R3 v$version" "$emailSubject" "$tmpEMailBodyFile" "$emailBodyTitle"
+ fi
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Function to keep track of emails sent, and determine if they need to be rate-limited
+ratelimiter()
+{
+
+#if rate limiting is disabled, exit right away
+if [ "$ratelimit" = "0" ]; then
+ return 0
+fi
+
+#Make sure log file exists
+touch "$vr3emails"
+
+#check current time and 1h into the past
+current_time=$(date +%s)
+cutoff_time=$((current_time - 3600))
+
+#create a temp file where current data will get moved over into that is less than 1hr old
+vr3emailstemp="${vr3emails}.tmp"
+awk -v cutoff="$cutoff_time" '$1 > cutoff' "$vr3emails" > "$vr3emailstemp"
+
+#check to see how many emails have been sent in the last hour
+recent_email_count=$(wc -l < "$vr3emailstemp" | tr -d ' ')
+
+printf "\33[2K\r"
+printf "${CGreen}\r[Checking email rate limit... $recent_email_count/$ratelimit emails sent within the last hour]"
+sleep 2
+
+#logic to determine if rate limit has been hit
+if [ "$recent_email_count" -ge "$ratelimit" ]
+ then
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Rate limit exceeded. Emails will be prevented from sending]"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Email Rate limit exceeded ($ratelimit). Emails will be prevented from sending." >> $logfile
+ sleep 2
+ mv "$vr3emailstemp" "$vr3emails"
+ return 1
+ else
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Rate within limits. Proceeding to send email]"
+ sleep 1
+ echo "$current_time" >> "$vr3emailstemp"
+ mv "$vr3emailstemp" "$vr3emails"
+ return 0
+fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Testing to see if VPNMON-R3 external reset is currently running, and if so, hold off until it finishes
+lockcheck()
+{
+
+ while [ -f "$lockfile" ]; do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} External VPN Reset Currently In-Progress ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} VPNMON-R3 is currently performing an external scheduled reset of the VPN through${CClear}"
+ echo -e "${InvGreen} ${CClear} the means of the '-reset' commandline option, or scheduled CRON job.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} [Retrying to resume normal operations every 15 seconds]${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ spinner 15
+ lockactive=1
+ done
+
+ if [ "$lockactive" = "1" ]; then
+ timerreset=1
+ lockactive=0
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Initiate a VPN restart - $1 = slot number
+
+restartvpn()
+{
+
+ echo -e "${CGreen}\nMessages: ${CClear}"
+ echo ""
+
+ #Check the current connection state of vpn slot
+ currvpnstate="$(_VPN_GetClientState_ "$1")"
+
+ if [ "$currvpnstate" -ne 0 ]; then
+ printf "${CGreen}\r[Stopping VPN Client $1]"
+ service stop_vpnclient$1 >/dev/null 2>&1
+ sleep 20
+ if [ "$currvpnstate" = "-1" ]; then
+ nvram set vpn_client$1_state=0
+ fi
+ printf "\33[2K\r"
+ fi
+
+ #Determine how many server entries are in the assigned vpn slot alternate servers file
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3svr$1.txt" ]
+ then
+ servers=$(cat "/jffs/addons/vpnmon-r3.d/vr3svr$1.txt" | wc -l) >/dev/null 2>&1
+ if [ -z "$servers" ] || [ "$servers" -eq 0 ]
+ then
+ #Restart the same server currently allocated to that vpn slot
+ currvpnhost=$($timeoutcmd$timeoutsec nvram get vpn_client$1_addr)
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting VPN Client $1]"
+ service start_vpnclient$1 >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN$1 Connection Restarted - Current Server: $currvpnhost" >> $logfile
+ resettimer $1 "VPN"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting VPN$1 Settle]"
+ sleep 10
+ else
+ #Pick a random server from the alternate servers file, populate in vpn client slot, and restart
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Selecting Random Entry]"
+ RANDOM=$(awk 'BEGIN {srand(); print int(32768 * rand())}')
+ R_LINE=$(( RANDOM % servers + 1 ))
+ RNDVPNIP=$(sed -n "${R_LINE}p" /jffs/addons/vpnmon-r3.d/vr3svr$1.txt)
+ nvram set vpn_client"$1"_addr="$RNDVPNIP"
+ nvram set vpn_client"$1"_desc="VPN$1 - $RNDVPNIP added by VPNMON-R3"
+ sleep 2
+ #Restart the new server currently allocated to that vpn slot
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting VPN Client $1]"
+ service start_vpnclient$1 >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN$1 Connection Restarted - New Server: $RNDVPNIP" >> $logfile
+ resettimer $1 "VPN"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting VPN$1 Settle]"
+ sleep 10
+ fi
+ else
+ #Restart the same server currently allocated to that vpn slot
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting VPN Client $1]"
+ currvpnhost="$($timeoutcmd$timeoutsec nvram get vpn_client$1_addr)"
+ service start_vpnclient$1 >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN$1 Connection Restarted - Current Server: $currvpnhost" >> $logfile
+ resettimer $1 "VPN"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting VPN$1 Settle]"
+ sleep 10
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Initiate a WG restart - $1 = slot number
+
+restartwg()
+{
+
+ echo -e "${CGreen}\nMessages: ${CClear}"
+ echo ""
+
+ #Check the current connection state of vpn slot
+ currwgstate="$(_WG_GetClientState_ $1)"
+
+ if [ "$currwgstate" -ne 0 ]; then
+ printf "${CGreen}\r[Stopping WG Client $1]"
+ service "stop_wgc $1" >/dev/null 2>&1
+ sleep 20
+ printf "\33[2K\r"
+ fi
+
+ #Determine how many server entries are in the assigned vpn slot alternate servers file
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3wgsvr$1.txt" ]
+ then
+ servers=$(cat "/jffs/addons/vpnmon-r3.d/vr3wgsvr$1.txt" | wc -l) >/dev/null 2>&1
+ if [ -z "$servers" ] || [ "$servers" -eq 0 ]
+ then
+ #Restart the same server currently allocated to that wg slot
+ currwghost="$($timeoutcmd$timeoutsec nvram get wgc$1_ep_addr)"
+ currwghostname="$($timeoutcmd$timeoutsec nvram get wgc$1_desc)"
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting WG Client $1]"
+ service "start_wgc $1" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WGC$1 Connection Restarted - Current Server: $currwghostname | $currwghost" >> $logfile
+ resettimer $1 "WG"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting WGC$1 Settle]"
+ sleep 10
+ else
+ #Pick a random server from the alternate servers file, populate in wg client slot, and restart
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Selecting Random Entry]"
+ RANDOM=$(awk 'BEGIN {srand(); print int(32768 * rand())}')
+ R_LINE=$(( RANDOM % servers + 1 ))
+
+ #---------WG-specific nvram values
+
+ WGLINE=$(sed -n "${R_LINE}p" /jffs/addons/vpnmon-r3.d/vr3wgsvr$1.txt)
+ wgdescription=$(echo "$WGLINE" | cut -d ',' -f 1)
+ endpointip=$(echo "$WGLINE" | cut -d ',' -f 2)
+ endpointport=$(echo "$WGLINE" | cut -d ',' -f 3)
+ privatekey=$(echo "$WGLINE" | cut -d ',' -f 4)
+ publickey=$(echo "$WGLINE" | cut -d ',' -f 5)
+ presharedkey=$(echo "$WGLINE" | cut -d ',' -f 6) #Optional, required by AirVPN
+ nvram set wgc"$1"_desc="$wgdescription"
+ nvram set wgc"$1"_ep_addr="$endpointip"
+ nvram set wgc"$1"_ep_addr_r="$endpointip"
+ nvram set wgc"$1"_ep_port="$endpointport"
+ nvram set wgc"$1"_priv="${privatekey}"
+ nvram set wgc"$1"_ppub="${publickey}"
+ nvram set wgc"$1"_psk="${presharedkey}" #Optional, required by AirVPN
+ sleep 2
+
+ #---------WG-specific nvram values
+
+ #Restart the new server currently allocated to that wg slot
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting WG Client $1]"
+ service "start_wgc $1" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WGC$1 Connection Restarted - New Server: $wgdescription | $endpointip" >> $logfile
+ resettimer $1 "WG"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting WGC$1 Settle]"
+ sleep 10
+ fi
+ else
+ #Restart the same server currently allocated to that wg slot
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Starting WG Client $1]"
+ currwghost="$($timeoutcmd$timeoutsec nvram get wgc$1_ep_addr)"
+ service "start_wgc $1" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WGC$1 Connection Restarted - Current Server: $currwghost" >> $logfile
+ resettimer $1 "WG"
+ sleep 10
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Letting WGC$1 Settle]"
+ sleep 10
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Separating off the vpnrouting service restart
+
+restartrouting()
+{
+
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Restarting VPN Routing]"
+ service restart_vpnrouting0 >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Director Routing Service Restarted" >> $logfile
+ sleep 5
+ printf "\33[2K\r"
+ trimlogs
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Optionally reset spdMerlin interfaces
+resetspdmerlin()
+{
+
+ if [ "$rstspdmerlin" = "1" ]
+ then
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Reset spdMerlin Interfaces]"
+ /jffs/scripts/spdmerlin reset_interfaces force >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: spdMerlin Interfaces Reset" >> $logfile
+ sleep 5
+ printf "\33[2K\r"
+ fi
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Kill a vpn connnection, and unmonitor it - $1 = slot number
+
+killunmonvpn()
+{
+
+ # Stop the service
+ echo -e "${CGreen}\nMessages: ${CClear}"
+ echo ""
+ printf "${CGreen}\r[Stopping VPN Client $1]"
+ service stop_vpnclient$1 >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN$1 has been stopped and no longer being monitored" >> $logfile
+ sleep 15
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Unmonitoring VPN Client $1]"
+
+ # Write the VPN client file back with the correct monitoring configuration
+ sed -i "s/^VPN$1=.*/VPN$1=0/" "/jffs/addons/vpnmon-r3.d/vr3clients.txt"
+ sleep 5
+
+ # Restart VPN Director Routing Services
+ restartrouting
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Kill a wg connnection, and unmonitor it - $1 = slot number
+
+killunmonwg()
+{
+
+ # Stop the service
+ echo -e "${CGreen}\nMessages: ${CClear}"
+ echo ""
+ printf "${CGreen}\r[Stopping WG Client $1]"
+ service "stop_wgc $1" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WGC$1 has been stopped and no longer being monitored" >> $logfile
+ sleep 15
+ printf "\33[2K\r"
+ printf "${CGreen}\r[Unmonitoring WG Client $1]"
+
+ # Write the VPN client file back with the correct monitoring configuration
+ sed -i "s/^WG$1=.*/WG$1=0/" "/jffs/addons/vpnmon-r3.d/vr3clients.txt"
+ sleep 5
+
+ # Restart VPN Director Routing Services
+ restartrouting
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Whitelist Server Slot IP lists in Skynet - $1 = VPN Slot
+
+skynetwhitelist()
+{
+ if [ "$updateskynet" = "1" ]
+ then
+ ##-------------------------------------##
+ ## Modified by Dan G. [2025-Jul-15] ##
+ ##-------------------------------------##
+ if echo "$1" | grep -q "wg"; then
+ slotnum=$(echo "$1" | tr -cd '0-9')
+ printf "${CGreen}\r[Whitelisting WG Server Slot $slotnum List in the Skynet Firewall]${CClear}\n"
+ awk -F',' '{print $2}' /jffs/addons/vpnmon-r3.d/vr3wgsvr${slotnum}.txt > /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svrtmp.txt "VPNMON-R3 - WG Server Slot $slotnum Whitelist" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: WG Server Slot $slotnum List has been whitelisted in Skynet" >> $logfile
+ else
+ printf "${CGreen}\r[Whitelisting VPN Server Slot $1 List in the Skynet Firewall]${CClear}\n"
+ firewall import whitelist /jffs/addons/vpnmon-r3.d/vr3svr$1.txt "VPNMON-R3 - VPN Server Slot $1 Whitelist" >/dev/null 2>&1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Server Slot $1 List has been whitelisted in Skynet" >> $logfile
+ fi
+ sleep 5
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Reset the VPN connection timer
+
+resettimer()
+{
+
+ # Create initial vr3timers.txt file if it does not exist
+ if [ ! -f /jffs/addons/vpnmon-r3.d/vr3timers.txt ]; then
+
+ if [ "$availableslots" = "1 2" ]; then
+ { echo 'VPNTIMER1=0'
+ echo 'VPNTIMER2=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3timers.txt
+
+ elif [ "$availableslots" = "1 2 3 4 5" ]; then
+ { echo 'VPNTIMER1=0'
+ echo 'VPNTIMER2=0'
+ echo 'VPNTIMER3=0'
+ echo 'VPNTIMER4=0'
+ echo 'VPNTIMER5=0'
+ echo 'WGTIMER1=0'
+ echo 'WGTIMER2=0'
+ echo 'WGTIMER3=0'
+ echo 'WGTIMER4=0'
+ echo 'WGTIMER5=0'
+ } > /jffs/addons/vpnmon-r3.d/vr3timers.txt
+
+ fi
+ fi
+
+ if [ "$2" = "VPN" ]; then
+ sed -i "s/^VPNTIMER$1=.*/VPNTIMER$1=$(date +%s)/" "/jffs/addons/vpnmon-r3.d/vr3timers.txt"
+ elif [ "$2" = "WG" ]; then
+ sed -i "s/^WGTIMER$1=.*/WGTIMER$1=$(date +%s)/" "/jffs/addons/vpnmon-r3.d/vr3timers.txt"
+ fi
+
+ source /jffs/addons/vpnmon-r3.d/vr3timers.txt
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Reset the managed VPN connections
+
+vreset()
+{
+ # Grab the VPNMON-R3 config file and read it in
+ if [ -f "$config" ]
+ then
+ source "$config"
+ else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 config file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+ fi
+
+ # Grab the monitored slots file and read it in
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3clients.txt ]
+ then
+ source /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 VPN Client Monitoring file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+ fi
+
+ # Create a rudimentary lockfile so that VPNMON-R3 doesn't interfere during the reset
+ echo -n > $lockfile
+
+ slot=0
+ for slot in $availableslots #loop through the 2/5 vpn slots
+ do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 - v$version | $(date) ${CClear}\n"
+ echo -e "${CGreen}[VPN Connection Reset Commencing]"
+ echo ""
+ echo -e "${CGreen}[Checking VPN Slot $slot]"
+ echo ""
+ sleep 2
+
+ #determine if the slot is monitored and reset it
+ if [ "$((VPN$slot))" = "1" ]
+ then
+ if [ "$refreshserverlists" -eq 1 ]
+ then
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3svr$slot.txt" ]
+ then
+ echo -e "${CGreen}[Executing Custom Server List Script for VPN Slot $slot]${CClear}"
+ slottmp="automation${slot}"
+ eval slottmp="\$${slottmp}"
+ if [ -z "$slottmp" ]
+ then
+ echo ""
+ echo -e "${CGreen}[Custom VPN Client Server Query not found for VPN Slot $slot]${CClear}"
+ else
+ automationunenc="$(echo "$slottmp" | openssl enc -d -base64 -A)"
+ echo ""
+ echo -e "${CClear}Running: $automationunenc"
+ echo ""
+
+ eval "$automationunenc" > "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt"
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" ]
+ then
+ dlcnt=$(cat "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" | wc -l) >/dev/null 2>&1
+ if [ -z "$dlcnt" ] || [ "$dlcnt" -lt 1 ]
+ then dlcnt=0 ; fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3svr$slot.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom VPN Client Server List Query Executed for VPN Slot $slot ($dlcnt rows)" >> $logfile
+ sleep 3
+ echo ""
+ skynetwhitelist $slot
+ echo ""
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List Query for VPN Slot $slot yielded 0 rows -- Query may be invalid or VPN API service may be down" >> $logfile
+ sendmessage 1 "VPN Server List Query Yielded 0 Rows" $slot
+ sleep 3
+ echo ""
+ fi
+ fi
+ else
+ echo ""
+ echo -e "${CRed}[Custom VPN Client Server List File not found for VPN Slot $slot]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom VPN Client Server List File not found for VPN Slot $slot" >> $logfile
+ sleep 3
+ fi
+ fi
+
+ restartvpn $slot
+ sendmessage 0 "VPN Connection Scheduled Reset" $slot
+
+ fi
+ done
+
+ slot=0
+ for slot in $availableslots #loop through the 5 wg slots
+ do
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 - v$version | $(date) ${CClear}\n"
+ echo -e "${CGreen}[WG Connection Reset Commencing]"
+ echo ""
+ echo -e "${CGreen}[Checking WG Slot $slot]"
+ echo ""
+ sleep 2
+
+ #determine if the slot is monitored and reset it
+ if [ "$((WG$slot))" = "1" ]
+ then
+ if [ "$refreshserverlists" -eq 1 ]
+ then
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3wgsvr$slot.txt" ]
+ then
+ echo -e "${CGreen}[Executing Custom WG Server List Script for WG Slot $slot]${CClear}"
+ slottmp="wgautomation${slot}"
+ eval slottmp="\$${slottmp}"
+ if [ -z "$slottmp" ]
+ then
+ echo ""
+ echo -e "${CGreen}[Custom WG Client Server Query not found for WG Slot $slot]${CClear}"
+ else
+ wgautomationunenc="$(echo "$slottmp" | openssl enc -d -base64 -A)"
+ echo ""
+ echo -e "${CClear}Running: $wgautomationunenc"
+ echo ""
+
+ eval "$wgautomationunenc" > "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt"
+ if [ -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" ]
+ then
+ dlcnt=$(cat "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" | wc -l) >/dev/null 2>&1
+ if [ -z "$dlcnt" ] || [ "$dlcnt" -lt 1 ]
+ then dlcnt=0 ; fi
+ else
+ dlcnt=0
+ fi
+
+ if [ "$dlcnt" -gt 1 ]
+ then
+ cp "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" "/jffs/addons/vpnmon-r3.d/vr3wgsvr$slot.txt" >/dev/null 2>&1
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: Custom WG Client Server List Query Executed for WG Slot $slot ($dlcnt rows)" >> $logfile
+ sleep 3
+ echo ""
+ skynetwhitelist wg$slot
+ echo ""
+ else
+ rm -f "/jffs/addons/vpnmon-r3.d/vr3svrtmp.txt" >/dev/null 2>&1
+ echo -e "${CGreen}[$dlcnt Rows Retrieved From Source - Preserving Original Server List]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List Query for WG Slot $slot yielded 0 rows -- Query may be invalid or WG API service may be down" >> $logfile
+ sendmessage 1 "WG Server List Query Yielded 0 Rows" $slot
+ sleep 3
+ echo ""
+ fi
+ fi
+ else
+ echo ""
+ echo -e "${CRed}[Custom WG Client Server List File not found for WG Slot $slot]${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: Custom WG Client Server List File not found for WG Slot $slot" >> $logfile
+ sleep 3
+ fi
+ fi
+ restartwg $slot
+ sendmessage 0 "WG Connection Scheduled Reset" $slot
+
+ fi
+ done
+
+ restartrouting
+ resetspdmerlin
+
+ # Clean up lockfile
+ rm -f $lockfile >/dev/null 2>&1
+
+ echo -e "\n${CClear}"
+ exit 0
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-18] ##
+##----------------------------------------##
+# Find the VPN IP
+getvpnip()
+{
+ ubsync=""
+ TUN="tun1$1"
+
+ icanhazvpnip="$($timeoutcmd$timeoutsec nvram get vpn_client$1_rip)"
+ if [ -z "$icanhazvpnip" ] || [ "$icanhazvpnip" = "unknown" ]
+ then
+ # Grab the public IP of the VPN Connection #
+ icanhazvpnip="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$TUN" --request GET --url https://ipv4.icanhazip.com"
+ icanhazvpnip="$(eval $icanhazvpnip)"
+ if [ -z "$icanhazvpnip" ] || echo "$icanhazvpnip" | grep -qoE 'Internet|traffic|Error|error' ; then icanhazvpnip="0.0.0.0" ; fi
+ fi
+
+ if [ -z "$icanhazvpnip" ]
+ then
+ vpnip="000.000.000.000"
+ return
+ else
+ vpnip="$(printf '%15s' "$icanhazvpnip")"
+ fi
+
+ if [ "$unboundclient" -ne 0 ] && [ "$unboundclient" -eq "$1" ]
+ then
+ if [ "$ResolverTimer" -eq 1 ]; then
+ ResolverTimer=0
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CYellow}-?[UB]${CClear}"
+ else
+ ubsync="${CYellow}-?[UB:Resolving]${CClear}"
+ fi
+ else
+ # Huge thanks to @SomewhereOverTheRainbow for his expertise in troublshooting and coming up with this DNS Resolver methodology!
+ DNSResolver="$({ unbound-control flush whoami.akamai.net >/dev/null 2>&1; } && dig whoami.akamai.net +short @"$(netstat -nlp 2>/dev/null | awk '/.*(unbound){1}.*/{split($4, ip_addr, ":");if(substr($4,11) !~ /.*953.*/)print ip_addr[1];if(substr($4,11) !~ /.*953.*/)exit}')" -p "$(netstat -nlp 2>/dev/null | awk '/.*(unbound){1}.*/{if(substr($4,11) !~ /.*953.*/)print substr($4,11);if(substr($4,11) !~ /.*953.*/)exit}')" 2>/dev/null)"
+
+ if [ -z "$DNSResolver" ]
+ then
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CRed}-X[UB]${CClear}"
+ else
+ ubsync="${CRed}-X[UB:$DNSResolver]${CClear}"
+ fi
+ # rudimentary check to make sure value coming back is in the format of an IP address... Don't care if it's more than 255.
+ elif expr "$DNSResolver" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null
+ then
+ # If the DNS resolver and public VPN IP address don't match in our Unbound scenario, reset!
+ if [ "$DNSResolver" != "$icanhazvpnip" ]
+ then
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CRed}-X[UB]${CClear}"
+ else
+ ubsync="${CRed}-X[UB:$DNSResolver]${CClear}"
+ fi
+ ResolverTimer=1
+ unboundreset=$1
+ else
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CGreen}->[UB]${CClear}"
+ else
+ ubsync="${CGreen}->[UB:$DNSResolver]${CClear}"
+ fi
+ fi
+ else
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CYellow}-?[UB]${CClear}"
+ else
+ ubsync="${CYellow}-?[UB:$DNSResolver]${CClear}"
+ fi
+ fi
+ fi
+ else
+ ubsync=""
+ fi
+
+ # Insert bogus IP if screenshotmode is on #
+ if [ "$screenshotmode" = "1" ]; then
+ vpnip="$(printf '%15s' "12.34.56.78")"
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+##-----------------------------------------------------------------------------------------##
+## Modified by ViktorJp [2025-Jul-06], origial getvpnip modded by Martinski. [2024-Oct-18] ##
+##-----------------------------------------------------------------------------------------##
+# Find the WG IP
+getwgip()
+{
+ ubsync=""
+ TUN="wgc$1"
+
+ # Added ping workaround for site2site scenarios based on suggestion from @ZebMcKayhan
+ TUN_IP=$($timeoutcmd$timeoutsec nvram get "$TUN"_addr | cut -d '/' -f1)
+ ip rule add from $TUN_IP lookup $TUN prio 10 >/dev/null 2>&1
+
+ icanhazwgip="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$TUN" --request GET --url https://ipv4.icanhazip.com"
+ icanhazwgip="$(eval $icanhazwgip)"
+ if [ -z "$icanhazwgip" ] || echo "$icanhazwgip" | grep -qoE 'Internet|traffic|Error|error' ; then icanhazwgip="0.0.0.0" ; fi
+
+ if [ -z "$icanhazwgip" ]
+ then
+ wgip="000.000.000.000"
+ return
+ else
+ wgip="$(printf '%15s' "$icanhazwgip")"
+ fi
+
+ if [ "$unboundwgclient" -ne 0 ] && [ "$unboundwgclient" -eq "$1" ]
+ then
+ if [ "$ResolverTimer" -eq 1 ]; then
+ ResolverTimer=0
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CYellow}-?[UB]${CClear}"
+ else
+ ubsync="${CYellow}-?[UB:Resolving]${CClear}"
+ fi
+ else
+ # Huge thanks to @SomewhereOverTheRainbow for his expertise in troublshooting and coming up with this DNS Resolver methodology!
+ DNSResolver="$({ unbound-control flush whoami.akamai.net >/dev/null 2>&1; } && dig whoami.akamai.net +short @"$(netstat -nlp 2>/dev/null | awk '/.*(unbound){1}.*/{split($4, ip_addr, ":");if(substr($4,11) !~ /.*953.*/)print ip_addr[1];if(substr($4,11) !~ /.*953.*/)exit}')" -p "$(netstat -nlp 2>/dev/null | awk '/.*(unbound){1}.*/{if(substr($4,11) !~ /.*953.*/)print substr($4,11);if(substr($4,11) !~ /.*953.*/)exit}')" 2>/dev/null)"
+
+ if [ -z "$DNSResolver" ]
+ then
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CRed}-X[UB]${CClear}"
+ else
+ ubsync="${CRed}-X[UB:$DNSResolver]${CClear}"
+ fi
+ # rudimentary check to make sure value coming back is in the format of an IP address... Don't care if it's more than 255.
+ elif expr "$DNSResolver" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null
+ then
+ # If the DNS resolver and public VPN IP address don't match in our Unbound scenario, reset!
+ if [ "$DNSResolver" != "$icanhazwgip" ]
+ then
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CRed}-X[UB]${CClear}"
+ else
+ ubsync="${CRed}-X[UB:$DNSResolver]${CClear}"
+ fi
+ ResolverTimer=1
+ unboundreset=$1
+ else
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CGreen}->[UB]${CClear}"
+ else
+ ubsync="${CGreen}->[UB:$DNSResolver]${CClear}"
+ fi
+ fi
+ else
+ if [ "$unboundshowip" -eq 0 ]; then
+ ubsync="${CYellow}-?[UB]${CClear}"
+ else
+ ubsync="${CYellow}-?[UB:$DNSResolver]${CClear}"
+ fi
+ fi
+ fi
+ else
+ ubsync=""
+ fi
+
+ # Added based on suggestion from @ZebMcKayhan
+ ip rule del prio 10 >/dev/null 2>&1
+
+ # Insert bogus IP if screenshotmode is on #
+ if [ "$screenshotmode" = "1" ]; then
+ wgip="$(printf '%15s' "12.34.56.78")"
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-18] ##
+##----------------------------------------##
+# Find and remember the VPN city so it doesn't have to make successive API lookups
+getvpncity()
+{
+ if [ "$icanhazvpnip" = "0.0.0.0" ]; then
+ vpncity="Undetermined"
+ return
+ fi
+
+ if [ "$1" = "1" ]
+ then
+ lastvpnip1="$icanhazvpnip"
+ if [ "$lastvpnip1" != "$oldvpnip1" ]
+ then
+ vpncity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazvpnip | jq --raw-output .city"
+ vpncity="$(eval $vpncity)"
+ if [ -z "$vpncity" ] || echo "$vpncity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then vpncity="Undetermined" ; fi
+ citychange="${CGreen}- NEW ${CClear}"
+ vpncity1="$vpncity"
+ fi
+ vpncity="$vpncity1"
+ oldvpnip1="$lastvpnip1"
+ elif [ "$1" = "2" ]
+ then
+ lastvpnip2="$icanhazvpnip"
+ if [ "$lastvpnip2" != "$oldvpnip2" ]
+ then
+ vpncity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazvpnip | jq --raw-output .city"
+ vpncity="$(eval $vpncity)"
+ if [ -z "$vpncity" ] || echo "$vpncity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then vpncity="Undetermined" ; fi
+ citychange="${CGreen}- NEW ${CClear}"
+ vpncity2="$vpncity"
+ fi
+ vpncity="$vpncity2"
+ oldvpnip2="$lastvpnip2"
+ elif [ "$1" = "3" ]
+ then
+ lastvpnip3="$icanhazvpnip"
+ if [ "$lastvpnip3" != "$oldvpnip3" ]
+ then
+ vpncity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazvpnip | jq --raw-output .city"
+ vpncity="$(eval $vpncity)"
+ if [ -z "$vpncity" ] || echo "$vpncity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then vpncity="Undetermined" ; fi
+ citychange="${CGreen}- NEW ${CClear}"
+ vpncity3="$vpncity"
+ fi
+ vpncity="$vpncity3"
+ oldvpnip3="$lastvpnip3"
+ elif [ "$1" = "4" ]
+ then
+ lastvpnip4="$icanhazvpnip"
+ if [ "$lastvpnip4" != "$oldvpnip4" ]
+ then
+ vpncity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazvpnip | jq --raw-output .city"
+ vpncity="$(eval $vpncity)"
+ if [ -z "$vpncity" ] || echo "$vpncity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then vpncity="Undetermined" ; fi
+ citychange="${CGreen}- NEW ${CClear}"
+ vpncity4="$vpncity"
+ fi
+ vpncity="$vpncity4"
+ oldvpnip4="$lastvpnip4"
+ elif [ "$1" = "5" ]
+ then
+ lastvpnip5="$icanhazvpnip"
+ if [ "$lastvpnip5" != "$oldvpnip5" ]
+ then
+ vpncity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazvpnip | jq --raw-output .city"
+ vpncity="$(eval $vpncity)"
+ if [ -z "$vpncity" ] || echo "$vpncity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then vpncity="Undetermined" ; fi
+ citychange="${CGreen}- NEW ${CClear}"
+ vpncity5="$vpncity"
+ fi
+ vpncity="$vpncity5"
+ oldvpnip5="$lastvpnip5"
+ fi
+
+ # Insert bogus City if screenshotmode is on
+ if [ "$screenshotmode" = "1" ]; then
+ vpncity="Gotham City"
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+##------------------------------------------------------------------------------------------------##
+## Modified by ViktorJp [2025-Jul-06], Original getvpncity() modded bt Martinski W. [2024-Oct-18] ##
+##------------------------------------------------------------------------------------------------##
+# Find and remember the WG city so it doesn't have to make successive API lookups
+getwgcity()
+{
+ if [ "$icanhazwgip" = "0.0.0.0" ]; then
+ wgcity="Undetermined"
+ return
+ fi
+
+ # Added ping workaround for site2site scenarios based on suggestion from @ZebMcKayhan
+ TUN_IP=$($timeoutcmd$timeoutsec nvram get "$TUN"_addr | cut -d '/' -f1)
+ ip rule add from $TUN_IP lookup $TUN prio 10 >/dev/null 2>&1
+
+ if [ "$1" = "1" ]
+ then
+ lastwgip1="$icanhazwgip"
+ if [ "$lastwgip1" != "$oldwgip1" ]
+ then
+ wgcity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazwgip | jq --raw-output .city"
+ wgcity="$(eval $wgcity)"
+ if [ -z "$wgcity" ] || echo "$wgcity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then wgcity="Undetermined" ; fi
+ wgcitychange="${CGreen}- NEW ${CClear}"
+ wgcity1="$wgcity"
+ fi
+ wgcity="$wgcity1"
+ oldwgip1="$lastwgip1"
+ elif [ "$1" = "2" ]
+ then
+ lastwgip2="$icanhazwgip"
+ if [ "$lastwgip2" != "$oldwgip2" ]
+ then
+ wgcity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazwgip | jq --raw-output .city"
+ wgcity="$(eval $wgcity)"
+ if [ -z "$wgcity" ] || echo "$wgcity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then wgcity="Undetermined" ; fi
+ wgcitychange="${CGreen}- NEW ${CClear}"
+ wgcity2="$wgcity"
+ fi
+ wgcity="$wgcity2"
+ oldwgip2="$lastwgip2"
+ elif [ "$1" = "3" ]
+ then
+ lastwgip3="$icanhazwgip"
+ if [ "$lastwgip3" != "$oldwgip3" ]
+ then
+ wgcity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazwgip | jq --raw-output .city"
+ wgcity="$(eval $wgcity)"
+ if [ -z "$wgcity" ] || echo "$wgcity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then wgcity="Undetermined" ; fi
+ wgcitychange="${CGreen}- NEW ${CClear}"
+ wgcity3="$wgcity"
+ fi
+ wgcity="$wgcity3"
+ oldwgip3="$lastwgip3"
+ elif [ "$1" = "4" ]
+ then
+ lastwgip4="$icanhazwgip"
+ if [ "$lastwgip4" != "$oldwgip4" ]
+ then
+ wgcity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazwgip | jq --raw-output .city"
+ wgcity="$(eval $wgcity)"
+ if [ -z "$wgcity" ] || echo "$wgcity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then wgcity="Undetermined" ; fi
+ wgcitychange="${CGreen}- NEW ${CClear}"
+ wgcity4="$wgcity"
+ fi
+ wgcity="$wgcity4"
+ oldwgip4="$lastwgip4"
+ elif [ "$1" = "5" ]
+ then
+ lastwgip5="$icanhazwgip"
+ if [ "$lastwgip5" != "$oldwgip5" ]
+ then
+ wgcity="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$icanhazwgip | jq --raw-output .city"
+ wgcity="$(eval $wgcity)"
+ if [ -z "$wgcity" ] || echo "$wgcity" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then wgcity="Undetermined" ; fi
+ wgcitychange="${CGreen}- NEW ${CClear}"
+ wgcity5="$wgcity"
+ fi
+ wgcity="$wgcity5"
+ oldwgip5="$lastwgip5"
+ fi
+
+ # Added based on suggestion from @ZebMcKayhan
+ ip rule del prio 10 >/dev/null 2>&1
+
+ # Insert bogus City if screenshotmode is on
+ if [ "$screenshotmode" = "1" ]; then
+ wgcity="Gotham City"
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Check health of the vpn connection using PING and CURL
+
+checkvpn()
+{
+ CNT=0
+ TRIES=3
+ TUN="tun1$1"
+
+ while [ "$CNT" -lt "$TRIES" ]; do # Loop through number of tries
+ ping -I $TUN -q -c 1 -W 2 $PINGHOST > /dev/null 2>&1 # First try pings
+ RC=$?
+ # Grab the public IP of the VPN Connection #
+ ICANHAZIP="$(curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$TUN" --request GET --url https://ipv4.icanhazip.com)"
+ IC=$?
+ if [ "$RC" -eq 0 ] && [ "$IC" -eq 0 ]; then # If both ping/curl come back successful, then proceed
+ vpnping=$(ping -I $TUN -c 1 -W 2 $PINGHOST | awk -F'time=| ms' 'NF==3{print $(NF-1)}' | sort -rn) > /dev/null 2>&1
+ VP=$?
+ if [ "$VP" -eq 0 ]; then
+ vpnhealth="${CGreen}[ OK ]${CClear}"
+ vpnindicator="${InvGreen} ${CClear}"
+ vrcnt=0
+ else
+ vpnping=0
+ vpnhealth="${CYellow}[UNKN]${CClear}"
+ vpnindicator="${InvYellow} ${CClear}"
+ fi
+ printf "\33[2K\r"
+ break
+ else
+ CNT="$((CNT+1))"
+ printf "\33[2K\r"
+ printf "\r${InvDkGray} ${CWhite} VPN$1${CClear} [Attempt $CNT]"
+ sleep 1 # Giving the VPN a chance to recover a certain number of times
+
+ if [ "$CNT" -eq "$TRIES" ];then # But if it fails, report back that we have an issue requiring a VPN reset
+ printf "\33[2K\r"
+ vpnping=0
+ vpnhealth="${CRed}[FAIL]${CClear}"
+ vpnindicator="${InvRed} ${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$1 failed to respond" >> $logfile
+
+ vrcnt="$((vrcnt+1))"
+ if [ "$vrcnt" -ge 10 ]; then
+ monitored="${CRed}[!]${CClear}"
+ else
+ monitored="${CRed}[$vrcnt]${CClear}"
+ fi
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$1 attempt $vrcnt of $recover to allow connection to recover" >> $logfile
+ if [ "$vrcnt" -eq "$recover" ]; then
+ if [ "$((VPN$1))" = "1" ]; then
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$1 failed to respond after $recover attempt(s)" >> $logfile
+ resetvpn=$1
+ fi
+ fi
+ fi
+ fi
+ done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Check health of the WG connection using PING and CURL
+
+checkwg()
+{
+ CNT=0
+ TRIES=3
+ TUN="wgc$1"
+
+ # Added ping workaround for site2site scenarios based on suggestion from @ZebMcKayhan
+ TUN_IP=$($timeoutcmd$timeoutsec nvram get "$TUN"_addr | cut -d '/' -f1)
+ ip rule add from $TUN_IP lookup $TUN prio 10 >/dev/null 2>&1
+
+ while [ "$CNT" -lt "$TRIES" ]; do # Loop through number of tries
+ ping -I $TUN -q -c 1 -W 2 $PINGHOST > /dev/null 2>&1 # First try pings
+ RC=$?
+ # Grab the public IP of the VPN Connection #
+ ICANHAZIP="$(curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$TUN" --request GET --url https://ipv4.icanhazip.com)"
+ IC=$?
+ if [ "$RC" -eq 0 ] && [ "$IC" -eq 0 ]; then # If both ping/curl come back successful, then proceed
+ wgping=$(ping -I $TUN -c 1 -W 2 $PINGHOST | awk -F'time=| ms' 'NF==3{print $(NF-1)}' | sort -rn) > /dev/null 2>&1
+ VP=$?
+ if [ "$VP" -eq 0 ]; then
+ wghealth="${CGreen}[ OK ]${CClear}"
+ wgindicator="${InvGreen} ${CClear}"
+ wrcnt=0
+ else
+ wgping=0
+ wghealth="${CYellow}[UNKN]${CClear}"
+ wgindicator="${InvYellow} ${CClear}"
+ fi
+ printf "\33[2K\r"
+ break
+ else
+ CNT="$((CNT+1))"
+ printf "\33[2K\r"
+ printf "\r${InvDkGray} ${CWhite} WGC$1${CClear} [Attempt $CNT]"
+ sleep 1 # Giving the VPN a chance to recover a certain number of times
+
+ if [ "$CNT" -eq "$TRIES" ]; then # But if it fails, report back that we have an issue requiring a VPN reset
+ printf "\33[2K\r"
+ wgping=0
+ wghealth="${CRed}[FAIL]${CClear}"
+ wgindicator="${InvRed} ${CClear}"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$1 failed to respond" >> $logfile
+
+ wrcnt="$((wrcnt+1))"
+ if [ "$wrcnt" -ge 10 ]; then
+ wgmonitored="${CRed}[!]${CClear}"
+ else
+ wgmonitored="${CRed}[$wrcnt]${CClear}"
+ fi
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$1 attempt $wrcnt of $recover to allow connection to recover" >> $logfile
+ if [ "$wrcnt" -eq "$recover" ]; then
+ if [ "$((WG$1))" = "1" ]; then
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$1 failed to respond after $recover attempt(s)" >> $logfile
+ resetwg=$1
+ fi
+ fi
+ fi
+ fi
+ done
+
+ # Added based on suggestion from @ZebMcKayhan
+ ip rule del prio 10 >/dev/null 2>&1
+
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+
+# Checkwan is a function that checks the viability of the current WAN connection and will loop until the WAN connection is restored.
+checkwan()
+{
+ # Using Google's DNS server as default to test for WAN connectivity over verified SSL Handshake
+ wandownbreakertrip=0
+ testssl="$PING_HOST_Deflt"
+
+ printf "\33[2K\r"
+ printf "\r${InvYellow} ${CClear} [Checking WAN Connectivity]..."
+
+ #Run main checkwan loop
+ while true
+ do
+ # Check the actual WAN State from NVRAM before running connectivity test, or insert itself into loop after failing an SSL handshake test
+ if [ "$($timeoutcmd$timeoutsec nvram get wan0_state_t)" -eq 2 ] || [ "$($timeoutcmd$timeoutsec nvram get wan1_state_t)" -eq 2 ]
+ then
+ # Test the active WAN connection using 443 and verifying a handshake... if this fails, then the WAN connection is most likely down... or Google is down ;)
+ if ($timeoutcmd$timeoutlng nc -w3 $testssl 443 >/dev/null 2>&1 && echo | $timeoutcmd$timeoutlng openssl s_client -connect $testssl:443 >/dev/null 2>&1 | awk 'handshake && $1 == "Verification" { if ($2=="OK") exit; exit 1 } $1 $2 == "SSLhandshake" { handshake = 1 }' >/dev/null 2>&1)
+ ##OFF##if ($timeoutcmd$timeoutlng nc -w1 $testssl 443 >/dev/null 2>&1 && echo | $timeoutcmd$timeoutlng openssl s_client -connect $testssl:443 >/dev/null 2>&1 | awk '$1 == "SSL" && $2 == "handshake" { handshake = 1 } handshake && $1 == "Verification:" { ok = $2; exit } END { exit ok != "OK" }' >/dev/null 2>&1)
+ then
+ printf "\r${InvGreen} ${CClear} [Checking WAN Connectivity]...ACTIVE"
+ sleep 1
+ printf "\33[2K\r"
+ return
+ else
+ wandownbreakertrip=1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: WAN Connectivity Issue Detected" >> $logfile
+ fi
+ else
+ wandownbreakertrip=1
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: WAN Connectivity Issue Detected" >> $logfile
+ fi
+
+ if [ "$wandownbreakertrip" = "1" ]
+ then
+ # The WAN is most likely down, and keep looping through until NVRAM reports that it's back up
+ while [ "$wandownbreakertrip" = "1" ]
+ do
+ if [ "$availableslots" = "1 2" ]
+ then
+ state1="$(_VPN_GetClientState_ 1)"
+ state2="$(_VPN_GetClientState_ 2)"
+ printf "\r${InvGreen} ${CClear} [Confirming VPN Clients Disconnected]... 1:$state1 2:$state2 "
+ sleep 3
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ state1="$(_VPN_GetClientState_ 1)"
+ state2="$(_VPN_GetClientState_ 2)"
+ state3="$(_VPN_GetClientState_ 3)"
+ state4="$(_VPN_GetClientState_ 4)"
+ state5="$(_VPN_GetClientState_ 5)"
+ printf "\r${InvGreen} ${CClear} [Confirming VPN Clients Disconnected]... 1:$state1 2:$state2 3:$state3 4:$state4 5:$state5 "
+ sleep 3
+ fi
+
+ # Preemptively kill all the VPN Clients incase they're trying to reconnect on their own
+ for slot in $availableslots
+ do
+ if [ $((state$slot)) -ne 0 ]; then
+ printf "\r${InvGreen} ${CClear} [Retrying Kill Command on VPN$slot Client Connection]... "
+ service stop_vpnclient$slot >/dev/null 2>&1
+ sleep 3
+ fi
+ done
+
+ # Check the wireguard side and bring those down as well
+ if [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ wgstate1="$(_WG_GetClientState_ 1)"
+ wgstate2="$(_WG_GetClientState_ 2)"
+ wgstate3="$(_WG_GetClientState_ 3)"
+ wgstate4="$(_WG_GetClientState_ 4)"
+ wgstate5="$(_WG_GetClientState_ 5)"
+ printf "\r${InvGreen} ${CClear} [Confirming WG Clients Disconnected]... 1:$wgstate1 2:$wgstate2 3:$wgstate3 4:$wgstate4 5:$wgstate5 "
+ sleep 3
+ fi
+
+ # Preemptively kill all the WG Clients incase they're trying to reconnect on their own
+ for slot in $availableslots
+ do
+ if [ $((wgstate$slot)) -ne 0 ]; then
+ printf "\r${InvGreen} ${CClear} [Retrying Kill Command on WGC$slot Client Connection]... "
+ service "stop_wgc $slot" >/dev/null 2>&1
+ sleep 3
+ fi
+ done
+
+ # Continue to test for WAN connectivity while in this loop. If it comes back up, break out of the loop and reset VPN
+ if [ "$($timeoutcmd$timeoutsec nvram get wan0_state_t)" -ne 2 ] && [ "$($timeoutcmd$timeoutsec nvram get wan1_state_t)" -ne 2 ]
+ then
+ # Continue to loop and retest the WAN every 15 seconds
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: WAN DOWN" >> $logfile
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Router is Currently Experiencing a WAN Down Situation ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Router is unable to provide a stable WAN connection. Please reboot your modem,${CClear}"
+ echo -e "${InvGreen} ${CClear} check with your ISP, or perform general internet connectivity troubleshooting${CClear}"
+ echo -e "${InvGreen} ${CClear} in order to re-establish a stable VPN connection.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} [Retrying to resume normal operations every 60 seconds]${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ spinner 60
+ wandownbreakertrip=1
+ else
+ wandownbreakertrip=2
+ break
+ fi
+ done
+ fi
+
+ # If the WAN was down, and now it has just reset, then run a VPN Reset, and try to establish a new VPN connection
+ if [ "$wandownbreakertrip" = "2" ]
+ then
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WAN Link Detected -- Trying to reconnect/Reset VPN" >> $logfile
+ wandownbreakertrip=0
+ clear
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 is currently recovering from a WAN Down Situation ${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} Router has detected a WAN Link/Modem and waiting 300 seconds for general network${CClear}"
+ echo -e "${InvGreen} ${CClear} connectivity to stabilize before re-establishing VPN/WG connectivity.${CClear}"
+ echo -e "${InvGreen} ${CClear}"
+ echo -e "${InvGreen} ${CClear} [Retrying to resume normal operations in 300 seconds...Please stand by!]${CClear}"
+ echo -e "${InvGreen} ${CClear}${CDkGray}---------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ spinner 300
+ #sendmessage 1 "Recovering from WAN Down" - this doesn't work when the internet is down
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ done
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-18] ##
+##----------------------------------------##
+# wancheck is a function that checks each wan connection to see if its active, and performs a ping and a city lookup...
+wancheck()
+{
+ WANIF="$1"
+ WANIFNAME="$(get_wan_setting ifname)"
+ DUALWANMODE="$($timeoutcmd$timeoutsec nvram get wans_mode)"
+
+ # Uptime calc #
+ uptimeStr="$(awk '{printf("%dd %02dh:%02dm\n",($1/60/60/24),($1/60/60%24),($1/60%60),($1%60))}' /proc/uptime)"
+
+ # If WAN 0 or 1 is connected, then proceed, else display that it's inactive
+ if [ "$WANIF" = "0" ]
+ then
+ if [ "$($timeoutcmd$timeoutsec nvram get wan0_state_t)" -eq 2 ]
+ then
+ # Call the get_wan_setting function courtesy of @dave14305 and using this interface name to ping and get a city name from
+ WAN0IFNAME="$(get_wan_setting0 ifname)"
+
+ # Ping through the WAN interface #
+ if [ "$WANIFNAME" = "$WAN0IFNAME" ] || [ "$DUALWANMODE" = "lb" ]
+ then
+ WAN0PING="$(ping -I "$WAN0IFNAME" -c 1 "$PINGHOST" 2>/dev/null | awk -F'[/=]' 'END{print $5}')"
+ ## No need to do left-padding with zeros for alignment ##
+ [ -n "${WAN0PING:+xSETx}" ] && WAN0PING="$(printf "[%8.3f]" "$WAN0PING")"
+ else
+ WAN0PING="[FAILOVER]"
+ fi
+
+ # On the rare occasion where it's unable to get the Ping time, show ERROR #
+ if [ -z "$WAN0PING" ] ; then WAN0PING="${CRed}[PING ERR]${CClear}" ; fi
+
+ # Get the public IP of the WAN, determine the city from it, and display it on screen #
+ if [ -z "${WAN0IP:+xSETx}" ]
+ then
+ WAN0IP="$(curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$WAN0IFNAME" --request GET --url https://ipv4.icanhazip.com)"
+ WAN0CITY="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$WAN0IP | jq --raw-output .city"
+ WAN0CITY="$(eval $WAN0CITY)"
+ if [ -z "$WAN0CITY" ] || echo "$WAN0CITY" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then WAN0CITY="$WAN0IP" ; fi
+ WAN0IP="$(printf '%15s' "$WAN0IP")"
+ fi
+
+ # Insert bogus IP and City if screenshotmode is on
+ if [ "$screenshotmode" = "1" ]
+ then
+ WAN0CITY="Metropolis"
+ WAN0IP="$(printf '%15s' "11.22.33.44")"
+ fi
+
+ if [ "$WAN0PING" = "[FAILOVER]" ]
+ then
+ echo -en "${InvGreen} ${InvDkGray}${CWhite} WAN0${CClear} | ${CGreen}[X]${CClear} | "
+ printf "%-6s" "$WAN0IFNAME"
+ echo -e " | ${CGreen}[ OK ]${CClear} | Failover | $WAN0IP | $WAN0PING | $WAN0CITY: $uptimeStr"
+ else
+ echo -en "${InvGreen} ${InvDkGray}${CWhite} WAN0${CClear} | ${CGreen}[X]${CClear} | "
+ printf "%-6s" "$WAN0IFNAME"
+ echo -e " | ${CGreen}[ OK ]${CClear} | Active | $WAN0IP | $WAN0PING | $WAN0CITY: $uptimeStr"
+ fi
+ else
+ echo -e "${InvDkGray}${CWhite} WAN0${CClear} | ${CGreen}[X]${CClear} | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a ]${CClear} | Inactive | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a]${CClear}"
+ fi
+ fi
+
+ if [ "$WANIF" = "1" ]
+ then
+ if [ "$($timeoutcmd$timeoutsec nvram get wan1_state_t)" -eq 2 ]
+ then
+ # Call the get_wan_setting function courtesy of @dave14305 and using this interface name to ping and get a city name from
+ WAN1IFNAME="$(get_wan_setting1 ifname)"
+
+ # Ping through the WAN interface #
+ if [ "$WANIFNAME" = "$WAN1IFNAME" ] || [ "$DUALWANMODE" = "lb" ]
+ then
+ WAN1PING="$(ping -I "$WAN1IFNAME" -c 1 "$PINGHOST" 2>/dev/null | awk -F'[/=]' 'END{print $5}')"
+ ## No need to do left-padding with zeros for alignment ##
+ [ -n "${WAN1PING:+xSETx}" ] && WAN1PING="$(printf "[%8.3f]" "$WAN1PING")"
+ else
+ WAN1PING="[FAILOVER]"
+ fi
+
+ # On the rare occasion where it's unable to get the Ping time, show ERROR #
+ if [ -z "$WAN1PING" ] ; then WAN1PING="${CRed}[PING ERR]${CClear}" ; fi
+
+ # Get the public IP of the WAN, determine the city from it, and display it on screen #
+ if [ -z "${WAN1IP:+xSETx}" ]
+ then
+ WAN1IP="$(curl --silent --retry 3 --retry-delay 2 --retry-all-errors --fail --interface "$WAN1IFNAME" --request GET --url https://ipv4.icanhazip.com)"
+ WAN1CITY="curl --silent --retry 3 --retry-delay 2 --retry-all-errors --request GET --url http://ip-api.com/json/$WAN1IP | jq --raw-output .city"
+ WAN1CITY="$(eval $WAN1CITY)"
+ if [ -z "$WAN1CITY" ] || echo "$WAN1CITY" | grep -qoE '\b(error.*:.*True.*|Undefined)\b' ; then WAN1CITY="$WAN1IP" ; fi
+ WAN1IP="$(printf '%15s' "$WAN1IP")"
+ fi
+
+ if [ "$WAN1PING" = "[FAILOVER]" ]
+ then
+ echo -en "${InvGreen} ${InvDkGray}${CWhite} WAN1${CClear} | ${CGreen}[X]${CClear} | "
+ printf "%-6s" "$WAN1IFNAME"
+ echo -e " | ${CGreen}[ OK ]${CClear} | Failover | $WAN1IP | $WAN1PING | $WAN1CITY: $uptimeStr"
+ else
+ echo -en "${InvGreen} ${InvDkGray}${CWhite} WAN1${CClear} | ${CGreen}[X]${CClear} | "
+ printf "%-6s" "$WAN1IFNAME"
+ echo -e " | ${CGreen}[ OK ]${CClear} | Active | $WAN1IP | $WAN1PING | $WAN1CITY: $uptimeStr"
+ fi
+ else
+ echo -e "${InvDkGray}${CWhite} WAN1${CClear} | ${CGreen}[X]${CClear} | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a ]${CClear} | Inactive | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a]${CClear} | ${CDkGray}[n/a]${CClear}"
+ fi
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+
+# This function was "borrowed" graciously from @dave14305 from his FlexQoS script to determine the active WAN connection.
+# Thanks much for your troubleshooting help as we tackled how to best derive the active WAN interface, Dave!
+
+get_wan_setting()
+{
+ local varname varval
+ varname="${1}"
+ prefixes="wan0_ wan1_"
+
+ if [ "$($timeoutcmd$timeoutsec nvram get wans_mode)" = "lb" ] ; then
+ for prefix in $prefixes; do
+ state="$($timeoutcmd$timeoutsec nvram get "${prefix}"state_t)"
+ sbstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"sbstate_t)"
+ auxstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"auxstate_t)"
+
+ # is_wan_connect()
+ [ "${state}" = "2" ] || continue
+ [ "${sbstate}" = "0" ] || continue
+ [ "${auxstate}" = "0" ] || [ "${auxstate}" = "2" ] || continue
+
+ # get_wan_ifname()
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ done
+ else
+ for prefix in $prefixes; do
+ primary="$($timeoutcmd$timeoutsec nvram get "${prefix}"primary)"
+ [ "${primary}" = "1" ] && break
+ done
+
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ fi
+ printf "%s" "${varval}"
+}
+
+# Separated these out to get the ifname for a dual-wan/failover situation where both WAN connections are on
+get_wan_setting0()
+{
+ local varname varval
+ varname="${1}"
+ prefixes="wan0_"
+
+ if [ "$($timeoutcmd$timeoutsec nvram get wans_mode)" = "lb" ] ; then
+ for prefix in $prefixes; do
+ state="$($timeoutcmd$timeoutsec nvram get "${prefix}"state_t)"
+ sbstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"sbstate_t)"
+ auxstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"auxstate_t)"
+
+ # is_wan_connect()
+ [ "${state}" = "2" ] || continue
+ [ "${sbstate}" = "0" ] || continue
+ [ "${auxstate}" = "0" ] || [ "${auxstate}" = "2" ] || continue
+
+ # get_wan_ifname()
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ done
+ else
+ for prefix in $prefixes; do
+ primary="$($timeoutcmd$timeoutsec nvram get "${prefix}"primary)"
+ [ "${primary}" = "1" ] && break
+ done
+
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ fi
+ printf "%s" "${varval}"
+}
+
+# Separated these out to get the ifname for a dual-wan/failover situation where both WAN connections are on
+get_wan_setting1()
+{
+ local varname varval
+ varname="${1}"
+ prefixes="wan1_"
+
+ if [ "$($timeoutcmd$timeoutsec nvram get wans_mode)" = "lb" ] ; then
+ for prefix in $prefixes; do
+ state="$($timeoutcmd$timeoutsec nvram get "${prefix}"state_t)"
+ sbstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"sbstate_t)"
+ auxstate="$($timeoutcmd$timeoutsec nvram get "${prefix}"auxstate_t)"
+
+ # is_wan_connect()
+ [ "${state}" = "2" ] || continue
+ [ "${sbstate}" = "0" ] || continue
+ [ "${auxstate}" = "0" ] || [ "${auxstate}" = "2" ] || continue
+
+ # get_wan_ifname()
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ done
+ else
+ for prefix in $prefixes; do
+ primary="$($timeoutcmd$timeoutsec nvram get "${prefix}"primary)"
+ [ "${primary}" = "1" ] && break
+ done
+
+ proto="$($timeoutcmd$timeoutsec nvram get "${prefix}"proto)"
+ if [ "${proto}" = "pppoe" ] || [ "${proto}" = "pptp" ] || [ "${proto}" = "l2tp" ] ; then
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}"pppoe_"${varname}")"
+ else
+ varval="$($timeoutcmd$timeoutsec nvram get "${prefix}""${varname}")"
+ fi
+ fi
+ printf "%s" "${varval}"
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# This function displays the operations menu
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Oct-05] ##
+##----------------------------------------##
+displayopsmenu()
+{
+ #scheduler colors and indicators
+ if [ "$schedule" = "0" ]
+ then
+ schedtime="${CDkGray}01:00${CClear}"
+ elif [ "$schedule" = "1" ]
+ then
+ schedhrs="$(printf "%02d" "$schedulehrs")"
+ schedmin="$(printf "%02d" "$schedulemin")"
+ schedtime="${CGreen}$schedhrs:$schedmin${CClear}"
+ fi
+
+ #autostart colors and indicators
+ if [ "$autostart" = "0" ]; then
+ rebootprot="${CDkGray}Disabled${CClear}"
+ elif [ "$autostart" = "1" ]; then
+ rebootprot="${CGreen}Enabled${CClear}"
+ fi
+
+ if [ "$logsize" -eq 0 ]; then
+ logSizeStr="${CDkGray}n/a${CClear}"
+ else
+ logSizeStr="${CGreen}${logsize}${CClear}"
+ fi
+
+ if [ -z "$timerloop" ]; then
+ timerLoopStr="${CDkGray}n/a${CClear}"
+ else
+ timerLoopStr="${CGreen}$timerloop sec${CClear}"
+ fi
+
+ if [ "$pingreset" -eq 0 ]; then
+ pingResetStr="${CDkGray}Disabled${CClear}"
+ else
+ pingResetStr="${CGreen}$pingreset ms${CClear}"
+ fi
+
+ if [ "$amtmemailsuccess" = "0" ] && [ "$amtmemailfailure" = "0" ]; then
+ amtmdisp="${CDkGray}Disabled "
+ elif [ "$amtmemailsuccess" = "1" ] && [ "$amtmemailfailure" = "0" ]; then
+ amtmdisp="${CGreen}Success "
+ elif [ "$amtmemailsuccess" = "0" ] && [ "$amtmemailfailure" = "1" ]; then
+ amtmdisp="${CGreen}Failure "
+ elif [ "$amtmemailsuccess" = "1" ] && [ "$amtmemailfailure" = "1" ]; then
+ amtmdisp="${CGreen}Success, Failure"
+ else
+ amtmdisp="${CDkGray}Disabled "
+ fi
+
+ rldisp=""
+ if [ "$amtmemailsuccess" = "1" ] || [ "$amtmemailfailure" = "1" ]
+ then
+ if [ "$ratelimit" = "0" ]; then
+ rldisp="| ${CRed}RL"
+ else
+ rldisp="| RL: ${CGreen}$ratelimit/h"
+ fi
+ fi
+
+ recoverdisp="${CClear}Recovery: ${CGreen}${recover}x${CClear}"
+
+ #display operations menu
+ if [ "$availableslots" = "1 2" ]
+ then
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Operations Menu ${CClear}"
+ echo -e "${InvGreen} ${CClear} Reset/Reconnect VPN 1:${CGreen}(1)${CClear} 2:${CGreen}(2)${CClear} ${InvGreen} ${CClear} ${CGreen}(C)${CClear}onfiguration Menu / Main Setup Menu $rldisp${CClear}"
+ echo -e "${InvGreen} ${CClear} Stop/Unmonitor VPN 1:${CGreen}(!)${CClear} 2:${CGreen}(@)${CClear} ${InvGreen} ${CClear} ${CGreen}(R)${CClear}eset VPN/WG CRON Time Scheduler: $schedtime"
+ echo -e "${InvGreen} ${CClear} Enable/Disable ${CGreen}(M)${CClear}onitored VPN Slots ${InvGreen} ${CClear} ${CGreen}(L)${CClear}og Viewer / Trim Log Size (rows): $logSizeStr"
+ echo -e "${InvGreen} ${CClear} Update/Maintain ${CGreen}(V)${CClear}PN Server Lists ${InvGreen} ${CClear} ${CGreen}(A)${CClear}utostart VPNMON-R3 on Reboot: $rebootprot"
+ echo -e "${InvGreen} ${CClear} Edit/R${CGreen}(U)${CClear}n Server List Automation ${InvGreen} ${CClear} ${CGreen}(T)${CClear}imer Loop Check Interval: $timerLoopStr | $recoverdisp"
+ echo -e "${InvGreen} ${CClear} AMTM Email Not${CGreen}(I)${CClear}fications: $amtmdisp ${InvGreen} ${CClear} ${CGreen}(P)${CClear}ing Maximum Before Reset in ms: $pingResetStr"
+ echo -e "${InvGreen} ${CClear}${CDkGray}--------------------------------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ elif [ "$availableslots" = "1 2 3 4 5" ]
+ then
+ echo -e "${InvGreen} ${InvDkGray}${CWhite} Operations Menu ${CClear}"
+ echo -e "${InvGreen} ${CClear} Reset/Reconnect VPN 1:${CGreen}(1)${CClear} 2:${CGreen}(2)${CClear} 3:${CGreen}(3)${CClear} 4:${CGreen}(4)${CClear} 5:${CGreen}(5)${CClear} ${InvGreen} ${CClear} ${CGreen}(C)${CClear}onfiguration Menu / Main Setup Menu $rldisp${CClear}"
+ echo -e "${InvGreen} ${CClear} Stop/Unmonitor VPN 1:${CGreen}(!)${CClear} 2:${CGreen}(@)${CClear} 3:${CGreen}(#)${CClear} 4:${CGreen}($)${CClear} 5:${CGreen}(%)${CClear} ${InvGreen} ${CClear} ${CGreen}(R)${CClear}eset VPN/WG CRON Time Scheduler: $schedtime"
+ echo -e "${InvGreen} ${CClear} Reset/Reconnect WG 1:${CGreen}(6)${CClear} 2:${CGreen}(7)${CClear} 3:${CGreen}(8)${CClear} 4:${CGreen}(9)${CClear} 5:${CGreen}(0)${CClear} ${InvGreen} ${CClear} ${CGreen}(L)${CClear}og Viewer / Trim Log Size (rows): $logSizeStr"
+ echo -e "${InvGreen} ${CClear} Stop/Unmonitor WG 1:${CGreen}(^)${CClear} 2:${CGreen}(&)${CClear} 3:${CGreen}(-)${CClear} 4:${CGreen}(+)${CClear} 5:${CGreen}(=)${CClear} ${InvGreen} ${CClear} ${CGreen}(A)${CClear}utostart VPNMON-R3 on Reboot: $rebootprot"
+ echo -e "${InvGreen} ${CClear} Enable/Disable ${CGreen}(M)${CClear}onitored VPN/WG Slots ${InvGreen} ${CClear} ${CGreen}(T)${CClear}imer Loop Check Interval: $timerLoopStr | $recoverdisp"
+ echo -e "${InvGreen} ${CClear} Update/Maintain ${CGreen}(V)${CClear}PN/${CGreen}(W)${CClear}G Server Lists ${InvGreen} ${CClear} ${CGreen}(P)${CClear}ing Maximum Before Reset in ms: $pingResetStr"
+ echo -e "${InvGreen} ${CClear} Edit/R${CGreen}(U)${CClear}n Server List Automation ${InvGreen} ${CClear} AMTM Email Not${CGreen}(I)${CClear}fications: $amtmdisp"
+ echo -e "${InvGreen} ${CClear}${CDkGray}--------------------------------------------------------------------------------------------------------------${CClear}"
+ echo ""
+ fi
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+# Begin VPNMON-R2 Main Loop
+# -------------------------------------------------------------------------------------------------------------------------
+
+#DEBUG=; set -x # uncomment/comment to enable/disable debug mode
+#{ # uncomment/comment to enable/disable debug mode
+
+# Create the necessary folder/file structure for VPNMON-R3 under /jffs/addons
+if [ ! -d "/jffs/addons/vpnmon-r3.d" ]; then
+ mkdir -p "/jffs/addons/vpnmon-r3.d"
+fi
+
+# Check for and add an alias for VPNMON-R3
+if ! grep -F "sh /jffs/scripts/vpnmon-r3.sh" /jffs/configs/profile.add >/dev/null 2>/dev/null; then
+ echo "alias vpnmon-r3=\"sh /jffs/scripts/vpnmon-r3.sh\" # added by vpnmon-r3" >> /jffs/configs/profile.add
+fi
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Oct-05] ##
+##-------------------------------------##
+_SetUpTimeoutCmdVars_
+_SetLAN_HostName_
+
+##-------------------------------------##
+## Added by Martinski W. [2024-Nov-04] ##
+##-------------------------------------##
+ROUTERMODEL="$($timeoutcmd$timeoutsec nvram get odmpid)"
+[ -z "$ROUTERMODEL" ] && ROUTERMODEL="$($timeoutcmd$timeoutsec nvram get productid)"
+FWVER="$($timeoutcmd$timeoutsec nvram get firmver | tr -d '.')"
+BUILDNO="$($timeoutcmd$timeoutsec nvram get buildno)"
+EXTENDNO="$($timeoutcmd$timeoutsec nvram get extendno)"
+if [ -z "$EXTENDNO" ]; then EXTENDNO=0; fi
+FWBUILD="${FWVER}.${BUILDNO}_${EXTENDNO}"
+
+# Check for updates
+updatecheck
+
+# Check and see if any commandline option is being used
+if [ $# -eq 0 ] || [ -z "$1" ]
+then
+ clear
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ exit 0
+fi
+
+# Check and see if an invalid commandline option is being used
+if [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "-setup" ] || [ "$1" = "-reset" ] || [ "$1" = "-bw" ] || [ "$1" = "-noswitch" ] || [ "$1" = "-screen" ] || [ "$1" = "-now" ] || [ "$1" = "-uowginitstart" ] || [ "$1" = "-uowgnatstart" ]
+then
+ clear
+else
+ clear
+ echo ""
+ echo "VPNMON-R3 v$version"
+ echo ""
+ echo "Exiting due to invalid commandline options!"
+ echo "(run 'vpnmon-r3 -h' for help)"
+ echo ""
+ echo -e "${CClear}"
+ exit 0
+fi
+
+# Check to see if the help option is being called
+if [ "$1" = "-h" ] || [ "$1" = "-help" ]
+then
+ clear
+ echo ""
+ echo "VPNMON-R3 v$version Commandline Option Usage:"
+ echo ""
+ echo "vpnmon-r3 -h | -help"
+ echo "vpnmon-r3 -setup"
+ echo "vpnmon-r3 -reset"
+ echo "vpnmon-r3 -bw"
+ echo "vpnmon-r3 -screen"
+ echo "vpnmon-r3 -screen -now"
+ echo ""
+ echo " -h | -help (this output)"
+ echo " -setup (displays the setup menu)"
+ echo " -reset (resets vpn connections and exits)"
+ echo " -bw (runs vpnmon-r3 in monochrome mode)"
+ echo " -screen (runs vpnmon-r3 in screen background)"
+ echo " -screen -now (runs vpnmon-r3 in screen background immediately)"
+ echo ""
+ echo -e "${CClear}"
+ exit 0
+fi
+
+# Check to see if the Unbound-over-WG init-start action is being called
+if [ "$1" = "-uowginitstart" ]
+then
+ uowginitstart
+ exit 0
+fi
+
+# Check to see if the Unbound-over-WG nat-start action is being called
+if [ "$1" = "-uowgnatstart" ]
+then
+ uowgnatstart
+ exit 0
+fi
+
+# Check to see if a second command is being passed to remove color
+if [ "$1" = "-bw" ] || { [ $# -gt 1 ] && [ "$2" = "-bw" ] ; }
+then
+ blackwhite
+fi
+
+# Check to see if the -now parameter is being called to bypass the screen timer
+if [ $# -gt 1 ] && [ "$2" = "-now" ]
+then
+ bypassscreentimer=1
+fi
+
+# Check to see if the setup option is being called
+if [ "$1" = "-setup" ]
+then
+ logoNM
+ vsetup
+ exit 0
+fi
+
+# Check to see if the reset option is being called
+if [ "$1" = "-reset" ]
+then
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - INFO: VPN Reset initiated through -RESET switch" >> $logfile
+ vreset
+fi
+
+# Check to see if the screen option is being called and run operations normally using the screen utility
+if [ "$1" = "-screen" ]
+then
+ screen -wipe >/dev/null 2>&1 # Kill any dead screen sessions
+ sleep 1
+ ScreenSess=$(screen -ls | grep "vpnmon-r3" | awk '{print $1}' | cut -d . -f 1)
+ if [ -z $ScreenSess ]; then
+ if [ "$bypassscreentimer" = "1" ]; then
+ screen -dmS "vpnmon-r3" $apppath -noswitch
+ sleep 1
+ screen -r vpnmon-r3
+ else
+ clear
+ echo -e "${CClear}Executing ${CGreen}VPNMON-R3 v$version${CClear} using the SCREEN utility..."
+ echo ""
+ echo -e "${CClear}IMPORTANT:"
+ echo -e "${CClear}In order to keep VPNMON-R3 running in the background,"
+ echo -e "${CClear}properly exit the SCREEN session by using: ${CGreen}CTRL-A + D${CClear}"
+ echo ""
+ screen -dmS "vpnmon-r3" $apppath -noswitch
+ sleep 5
+ screen -r vpnmon-r3
+ exit 0
+ fi
+ else
+ if [ "$bypassscreentimer" = "1" ]; then
+ sleep 1
+ else
+ clear
+ echo -e "${CClear}Connecting to existing ${CGreen}VPNMON-R3 v$version${CClear} SCREEN session...${CClear}"
+ echo ""
+ echo -e "${CClear}IMPORTANT:${CClear}"
+ echo -e "${CClear}In order to keep VPNMON-R3 running in the background,${CClear}"
+ echo -e "${CClear}properly exit the SCREEN session by using: ${CGreen}CTRL-A + D${CClear}"
+ echo ""
+ echo -e "${CClear}Switching to the SCREEN session in T-5 sec...${CClear}"
+ echo -e "${CClear}"
+ spinner 5
+ fi
+ fi
+ screen -dr $ScreenSess
+ exit 0
+fi
+
+# Check to see if the noswitch option is being called
+if [ "$1" = "-noswitch" ]
+then
+ clear #last switch before the main program starts
+ firstrun=1
+
+ # Clean up lockfile
+ rm -f $lockfile >/dev/null 2>&1
+
+ if [ ! -f "$config" ] && [ ! -f "/opt/bin/timeout" ] && [ ! -f "/opt/sbin/screen" ] && [ ! -f "/opt/bin/jq" ]
+ then
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3 -setup' first.${CClear}"
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 is not configured. Please run the setup/configuration utility" >> $logfile
+ exit 0
+ fi
+fi
+
+ubsync=""
+firstDataCollection=true
+
+##----------------------------------------##
+## Modified by Martinski W. [2024-Nov-02] ##
+##----------------------------------------##
+while true
+do
+ _SetUpTimeoutCmdVars_
+ _SetLAN_HostName_
+
+ # Grab the VPNMON-R3 config file and read it in
+ if [ -f "$config" ]
+ then
+ source "$config"
+ else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 config file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+ fi
+
+ # Grab the monitored slots file and read it in
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3clients.txt ]
+ then
+ source /jffs/addons/vpnmon-r3.d/vr3clients.txt
+ else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 VPN Client Monitoring file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+ fi
+
+ createconfigs
+
+ # Grab the monitored slots file and read it in
+ if [ -f /jffs/addons/vpnmon-r3.d/vr3timers.txt ]
+ then
+ source /jffs/addons/vpnmon-r3.d/vr3timers.txt
+ else
+ clear
+ echo -e "${CRed}ERROR: VPNMON-R3 is not configured. Please run 'vpnmon-r3.sh -setup' first."
+ echo ""
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - ERROR: VPNMON-R3 VPN Timer Monitoring file not found. Please run the setup/configuration utility" >> $logfile
+ echo -e "${CClear}"
+ exit 1
+ fi
+
+ #Set variables
+ resetvpn=0
+ resetwg=0
+
+ #Check to see if a reset is currently underway
+ lockcheck
+
+ clear #display the header
+
+ if [ "$hideoptions" = "0" ] && [ "$hideoptions" != "$prevHideOpts" ]
+ then
+ timerreset=0
+ displayopsmenu
+ else
+ timerreset=0
+ fi
+ prevHideOpts="$hideoptions"
+
+ tzone="$(date +%Z)"
+ tzonechars="${#tzone}"
+
+ if [ "$tzonechars" = "1" ]; then tzspaces=" ";
+ elif [ "$tzonechars" = "2" ]; then tzspaces=" ";
+ elif [ "$tzonechars" = "3" ]; then tzspaces=" ";
+ elif [ "$tzonechars" = "4" ]; then tzspaces=" ";
+ elif [ "$tzonechars" = "5" ]; then tzspaces=" "; fi
+
+ #Display VPNMON-R3 client header
+ echo -en "${InvGreen} ${InvDkGray}${CWhite} VPNMON-R3 - v"
+ printf "%-8s" $version
+ echo -e " ${CGreen}(S)${CWhite}how/${CGreen}(H)${CWhite}ide Operations Menu ${InvDkGray} $tzspaces$(date) ${CClear}"
+
+ #Display VPNMON-R2 Found Warning
+ if [ -f /jffs/scripts/vpnmon-r2.sh ]; then
+ echo -e "${InvYellow} ${InvRed}${CWhite} VPNMON-R2 Install Detected. Support and availability for R2 is being sunset. Press (X) for Uninstall Menu. ${CClear}"
+ fi
+
+ #Display VPNMON-R3 Update Notifications
+ if [ "$UpdateNotify" != "0" ]; then echo -e "$UpdateNotify\n"; else echo -e "${CClear}"; fi
+
+ #If WAN Monitoring is enabled, test WAN connection and show the following grid
+ if [ "$monitorwan" = "1" ] && [ "$firstrun" = "1" ]
+ then
+ #Check to see if the WAN is up
+ checkwan
+ firstrun=0
+ fi
+
+ if [ "$monitorwan" = "1" ] && [ "$firstrun" = "0" ]
+ then
+ #Display WAN ports grid
+ echo -e "${CClear} Port | Mon | IFace | Health | WAN State | Public WAN IP | Ping-->WAN | City Exit / Uptime"
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+
+ #Cycle through the WANCheck connection function to display ping/city info
+ wans=0
+ for wans in 0 1
+ do
+ wancheck "$wans"
+ done
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+ echo ""
+ fi
+
+ if [ "$useovpn" = "1" ]
+ then
+ echo -e "${InvDkGray} OpenVPN ${CClear}"
+ echo ""
+ #Display VPN client slot grid
+ if [ "$unboundclient" != "0" ]; then
+ echo -e " Slot | Mon | Svrs | Health | VPN State | Public VPN IP | Ping-->VPN | City Exit / Time Connected / UB"
+ else
+ echo -e " Slot | Mon | Svrs | Health | VPN State | Public VPN IP | Ping-->VPN | City Exit / Time Connected"
+ fi
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+
+ if "$firstDataCollection" ; then printf "\r\033[0K${InvYellow} ${CClear} Please wait..." ; sleep 1 ; fi
+
+ i=0
+ for i in $availableslots #loop through the VPN slots
+ do
+ #Set variables
+ citychange=""
+
+ #determine if the slot is monitored#
+ if [ "$((VPN$i))" = "1" ]; then
+ monitored="${CGreen}[X]${CClear}"
+ else
+ monitored="[ ]"
+ fi
+
+ #determine the vpn state, and if connected, get vpn IP and city
+ vpnstate="$(_VPN_GetClientState_ "$i")"
+
+ if [ "$vpnstate" = "0" ]
+ then
+ vpnstate="Disconnected"
+ vpnhealth="${CDkGray}[n/a ]${CClear}"
+ vpnindicator="${InvDkGray} ${CClear}"
+ vpnip=" ${CDkGray}[n/a]${CClear}"
+ vpncity="${CDkGray}[n/a]${CClear}"
+ svrping=" ${CDkGray}[n/a]${CClear}"
+ elif [ "$vpnstate" = "-1" ]
+ then
+ vpnstate="Error State "
+ vpnhealth="${CDkGray}[n/a ]${CClear}"
+ vpnindicator="${InvDkGray} ${CClear}"
+ vpnip="${CDkGray} [n/a]${CClear}"
+ vpncity="${CDkGray}[n/a]${CClear}"
+ svrping=" ${CDkGray}[n/a]${CClear}"
+ elif [ "$vpnstate" = "1" ]
+ then
+ vpnstate="Connecting "
+ vpnhealth="${CDkGray}[n/a ]${CClear}"
+ vpnindicator="${InvYellow} ${CClear}"
+ vpnip=" ${CDkGray}[n/a]${CClear}"
+ vpncity="${CDkGray}[n/a]${CClear}"
+ svrping=" ${CDkGray}[n/a]${CClear}"
+ elif [ "$vpnstate" = "2" ]
+ then
+ vpnstate="Connected "
+ checkvpn "$i"
+ getvpnip "$i"
+ getvpncity "$i"
+ if [ -z "$vpnping" ]
+ then
+ svrping="${CRed}[PING ERR]${CClear}"
+ vpnhealth="${CYellow}[UNKN]${CClear}"
+ vpnindicator="${InvYellow} ${CClear}"
+ else
+ ## No need to do left-padding with zeros for alignment ##
+ svrping="$(printf "[%8.3f]" "$vpnping")"
+ fi
+ else
+ vpnstate="Unknown "
+ vpnhealth="${CDkGray}[n/a ]${CClear}"
+ vpnindicator="${InvDkGray} ${CClear}"
+ vpnip=" ${CDkGray}[n/a]${CClear}"
+ vpncity="${CDkGray}[n/a]${CClear}"
+ svrping=" ${CDkGray}[n/a]${CClear}"
+ fi
+
+ #Determine how many server entries are in each of the vpn slot alternate server files#
+ if [ -s "/jffs/addons/vpnmon-r3.d/vr3svr$i.txt" ]
+ then
+ servercnt="$(cat "/jffs/addons/vpnmon-r3.d/vr3svr$i.txt" | wc -l)"
+ if [ -z "$servercnt" ] || [ "$servercnt" -lt 1 ]
+ then
+ servercnt="${CRed}[0000]${CClear}"
+ else
+ ## No need to do left-padding with zeros for alignment ##
+ servercnt="$(printf "[%4d]" "$servercnt")"
+ fi
+ else
+ servercnt="${CRed}[0000]${CClear}"
+ fi
+
+ #Calculate connected time for current VPN slot
+ if [ $((VPNTIMER$i)) = "0" ] || [ "$((VPN$i))" = "0" ]
+ then
+ sincelastreset=""
+ else
+ currtime=$(date +%s)
+ timediff=$((currtime-VPNTIMER$i))
+ sincelastreset=$(printf ': %dd %02dh:%02dm\n' $(($timediff/86400)) $(($timediff%86400/3600)) $(($timediff%3600/60)))
+ fi
+
+ if "$firstDataCollection" ; then printf "\r\033[0K" ; firstDataCollection=false ; fi
+
+ # Print the results of all data gathered sofar #
+ echo -e "$vpnindicator${InvDkGray}${CWhite} VPN$i${CClear} | $monitored | $servercnt | $vpnhealth | $vpnstate | $vpnip | $svrping | $vpncity$sincelastreset $citychange$ubsync"
+
+ #if a vpn is monitored and disconnected, try to restart it
+ if [ "$((VPN$i))" = "1" ] && [ "$vpnstate" = "Disconnected" ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$i has disconnected" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #Display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ done
+ printf "\33[2K\r"
+
+ restartvpn $i
+ sendmessage 1 "VPN Tunnel Disconnected" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+
+ #if a vpn is monitored and in error state, try to restart it
+ if [ "$((VPN$i))" = "1" ] && [ "$vpnstate" = "Error State " ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$i is in an error state and being reconnected" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ #sleep 1
+ done
+ printf "\33[2K\r"
+
+ restartvpn $i
+ sendmessage 1 "VPN Slot In Error State" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+
+ #if a vpn is monitored and not responsive, try to restart it
+ if [ "$((VPN$i))" = "1" ] && [ "$resetvpn" != "0" ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$i is non-responsive and being reconnected" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ #sleep 1
+ done
+ printf "\33[2K\r"
+
+ restartvpn $resetvpn
+ sendmessage 1 "VPN Slot Is Non-Responsive" $resetvpn
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+
+ if [ "$((VPN$i))" = "1" ]; then
+ # if a vpn connection ping is greater than a certain amount, restart it
+ maxsvrping=$(awk "BEGIN {printf \"%3.0f\", ${vpnping}}") >/dev/null 2>&1
+ MP=$?
+ if [ $MP -ne 0 ]; then
+ if [ -z "$maxsvrping" ] || [ "$maxsvrping" = "" ]; then
+ maxsvrping="Null"
+ fi
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: Invalid VPN PING information received. Contents: $maxsvrping" >> $logfile
+ maxsvrping=0
+ fi
+ else
+ maxsvrping=0
+ fi
+
+ if [ "$pingreset" -gt 0 ]
+ then
+ if [ "$maxsvrping" -ge "$pingreset" ]
+ then
+ echo ""
+ printf "\33[2K\r"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$i PING exceeds max allowed ($pingreset ms)" >> $logfile
+ printf "${CGreen}\r[Maximum PING Exceeded]"
+ sleep 3
+ printf "\33[2K\r"
+
+ #display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ #sleep 1
+ done
+ printf "\33[2K\r"
+
+ restartvpn $i
+ sendmessage 1 "VPN Slot Exceeded Max Ping" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ fi
+
+ #Reset variables
+ ubsync=""
+ sincelastreset=""
+
+ done
+
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+ echo ""
+ fi
+
+#-----------------Wireguard
+
+ if [ "$availableslots" = "1 2 3 4 5" ] && [ "$usewg" = "1" ]; then
+
+ echo -e "${InvDkGray} Wireguard ${CClear}"
+ echo ""
+
+ #Display WG client slot grid
+ if [ "$unboundwgclient" != "0" ]; then
+ echo -e " Slot | Mon | Svrs | Health | WG State | Public WG IP | Ping--->WG | City Exit / Time Connected / UB"
+ else
+ echo -e " Slot | Mon | Svrs | Health | WG State | Public WG IP | Ping--->WG | City Exit / Time Connected"
+ fi
+
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+
+ i=0
+ for i in $availableslots #loop through the VPN slots
+ do
+ #Set variables
+ wgcitychange=""
+
+ #determine if the slot is monitored#
+ if [ "$((WG$i))" = "1" ]; then
+ wgmonitored="${CGreen}[X]${CClear}"
+ else
+ wgmonitored="[ ]"
+ fi
+
+ #determine the vpn state, and if connected, get vpn IP and city
+ wgstate="$(_WG_GetClientState_ "$i")"
+
+ if [ "$wgstate" = "0" ]
+ then
+ wgstate="Disconnected"
+ wghealth="${CDkGray}[n/a ]${CClear}"
+ wgindicator="${InvDkGray} ${CClear}"
+ wgip=" ${CDkGray}[n/a]${CClear}"
+ wgcity="${CDkGray}[n/a]${CClear}"
+ wgsvrping=" ${CDkGray}[n/a]${CClear}"
+ elif [ "$wgstate" = "2" ]
+ then
+ wgstate="Connected "
+ checkwg "$i"
+ getwgip "$i"
+ getwgcity "$i"
+ if [ -z "$wgping" ]
+ then
+ wgsvrping="${CRed}[PING ERR]${CClear}"
+ wghealth="${CYellow}[UNKN]${CClear}"
+ wgindicator="${InvYellow} ${CClear}"
+ else
+ ## No need to do left-padding with zeros for alignment ##
+ wgsvrping="$(printf "[%8.3f]" "$wgping")"
+ fi
+ else
+ wgstate="Unknown "
+ wghealth="${CDkGray}[n/a ]${CClear}"
+ wgindicator="${InvDkGray} ${CClear}"
+ wgip=" ${CDkGray}[n/a]${CClear}"
+ wgcity="${CDkGray}[n/a]${CClear}"
+ wgsvrping=" ${CDkGray}[n/a]${CClear}"
+ fi
+
+ #Determine how many server entries are in each of the vpn slot alternate server files#
+ if [ -s "/jffs/addons/vpnmon-r3.d/vr3wgsvr$i.txt" ]
+ then
+ wgservercnt="$(cat "/jffs/addons/vpnmon-r3.d/vr3wgsvr$i.txt" | wc -l)"
+ if [ -z "$wgservercnt" ] || [ "$wgservercnt" -lt 1 ]
+ then
+ wgservercnt="${CRed}[0000]${CClear}"
+ else
+ ## No need to do left-padding with zeros for alignment ##
+ wgservercnt="$(printf "[%4d]" "$wgservercnt")"
+ fi
+ else
+ wgservercnt="${CRed}[0000]${CClear}"
+ fi
+
+ #Calculate connected time for current VPN slot
+ if [ $((WGTIMER$i)) = "0" ] || [ "$((WG$i))" = "0" ]
+ then
+ wgsincelastreset=""
+ else
+ wgcurrtime=$(date +%s)
+ wgtimediff=$((wgcurrtime-WGTIMER$i))
+ wgsincelastreset=$(printf ': %dd %02dh:%02dm\n' $(($wgtimediff/86400)) $(($wgtimediff%86400/3600)) $(($wgtimediff%3600/60)))
+ fi
+
+ #if "$firstDataCollection" ; then printf "\r\033[0K" ; firstDataCollection=false ; fi
+
+ # Print the results of all data gathered sofar #
+ echo -e "$wgindicator${InvDkGray}${CWhite} WG$i${CClear} | $wgmonitored | $wgservercnt | $wghealth | $wgstate | $wgip | $wgsvrping | $wgcity$wgsincelastreset $wgcitychange$ubsync"
+
+ #if a wg connection is monitored and disconnected, try to restart it
+ if [ "$((WG$i))" = "1" ] && [ "$wgstate" = "Disconnected" ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$i has disconnected" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #Display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ done
+ printf "\33[2K\r"
+
+ restartwg $i
+ sendmessage 1 "WG Tunnel Disconnected" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+
+ #if the wg handshake exceeds 200s, try to restart it
+ # Inspiration from ZebMcKayHan's WGC Watchdog Script
+ if [ "$((WG$i))" = "1" ] && [ "$wgstate" = "Connected" ]
+ then
+ last_handshake=$(wg show wgc$i latest-handshakes | awk '{print $2}') >/dev/null 2>&1
+ if [ ! -z $last_handshake ]
+ then
+ idle_seconds=$((`date +%s`-${last_handshake}))
+ if [ "$idle_seconds" -gt "200" ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$i handshake exceeded 200s" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #Display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ done
+ printf "\33[2K\r"
+
+ restartwg $i
+ sendmessage 1 "WG Handshake Exceeded" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ fi
+ fi
+
+ if [ "$((WG$i))" = "1" ]; then
+ # if a wg connection ping is greater than a certain amount, restart it
+ maxsvrping=$(awk "BEGIN {printf \"%3.0f\", ${wgping}}") >/dev/null 2>&1
+ MP=$?
+ if [ $MP -ne 0 ]; then
+ if [ -z "$maxsvrping" ] || [ "$maxsvrping" = "" ]; then
+ maxsvrping="Null"
+ fi
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: Invalid WG PING information received. Contents: $maxsvrping" >> $logfile
+ maxsvrping=0
+ fi
+ else
+ maxsvrping=0
+ fi
+
+ if [ "$pingreset" -gt 0 ]
+ then
+ if [ "$maxsvrping" -ge "$pingreset" ]
+ then
+ echo ""
+ printf "\33[2K\r"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$i PING exceeds max allowed ($pingreset ms)" >> $logfile
+ printf "${CGreen}\r[Maximum PING Exceeded]"
+ sleep 3
+ printf "\33[2K\r"
+
+ #display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ #sleep 1
+ done
+ printf "\33[2K\r"
+
+ restartwg $i
+ sendmessage 1 "WG Slot Exceeded Max Ping" $i
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ fi
+
+ #if a wg is monitored and not responsive, try to restart it
+ if [ "$((WG$i))" = "1" ] && [ "$resetwg" != "0" ]
+ then #reconnect
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$i is non-responsive and being reconnected" >> $logfile
+ echo ""
+ printf "\33[2K\r"
+
+ #display a standard timer#
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ #sleep 1
+ done
+ printf "\33[2K\r"
+
+ restartwg $resetwg
+ sendmessage 1 "WG Slot Is Non-Responsive" $resetwg
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+
+ #Reset variables
+ wgsincelastreset=""
+
+ done
+
+ echo -e "-------|-----|--------|--------|--------------|-----------------|------------|---------------------------------"
+ echo ""
+
+ #-----------------
+ fi
+
+ #display a standard timer#
+ timer=0
+ lastTimerSec=0
+ updateTimer=true
+
+ while [ "$timer" -lt "$timerloop" ]
+ do
+ if "$updateTimer"
+ then
+ updateTimer=false
+ timer="$((timer+1))"
+ lastTimerSec="$(date +%s)"
+ fi
+ preparebar 46 "|"
+ progressbaroverride "$timer" "$timerloop" "" "s" "Standard"
+ lockcheck #Check to see if a reset is currently underway
+ if [ "$timerreset" = "1" ]; then timer="$timerloop" ; fi
+
+ ## Prevent repeatedly fast key presses from updating the timer ##
+ [ "$(date +%s)" -gt "$lastTimerSec" ] && updateTimer=true
+ done
+
+ #Check to see if a reset is currently underway
+ lockcheck
+ prevHideOpts=X
+
+ #if Unbound is active and out of sync, try to restart it
+ if [ "$unboundclient" != "0" ] && [ "$ResolverTimer" = "1" ]
+ then
+
+ if [ "$useovpn" = "1" ]
+ then
+ printf "\33[2K\r"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: VPN$unboundreset is out of sync with Unbound DNS Resolver" >> $logfile
+ printf "${CGreen}\r[Unbound is out of sync]"
+ sleep 3
+ printf "\33[2K\r"
+
+ #display a standard timer
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ done
+ printf "\33[2K\r"
+
+ restartvpn $unboundreset
+ sendmessage 1 "VPN Slot Not Synced With Unbound" $unboundreset
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ fi
+
+ if [ "$unboundwgclient" != "0" ] && [ "$ResolverTimer" = "1" ]
+ then
+ if [ "$usewg" = "1" ]
+ then
+ printf "\33[2K\r"
+ echo -e "$(date +'%b %d %Y %X') $(_GetLAN_HostName_) VPNMON-R3[$$] - WARNING: WGC$unboundreset is out of sync with Unbound DNS Resolver" >> $logfile
+ printf "${CGreen}\r[Unbound is out of sync]"
+ sleep 3
+ printf "\33[2K\r"
+
+ #display a standard timer
+ timer=0
+ while [ $timer -ne 5 ]
+ do
+ timer="$((timer+1))"
+ preparebar 46 "|"
+ progressbarpause $timer 5 "" "s" "Standard"
+ done
+ printf "\33[2K\r"
+
+ restartwg $unboundreset
+ sendmessage 1 "WG Slot Not Synced With Unbound" $unboundreset
+ restartrouting
+ resetspdmerlin
+ exec sh /jffs/scripts/vpnmon-r3.sh -noswitch
+ fi
+ fi
+
+ #Check to see if the WAN is up
+ if [ "$monitorwan" = "1" ] && [ "$bypasswancheck" = "0" ]; then
+ checkwan
+ fi
+
+ firstrun=0
+
+done
+echo -e "${CClear}"
+exit 0
+
+#} #2>&1 | tee $LOG | logger -t $(basename $0)[$$] # uncomment/comment to enable/disable debug mode
diff --git a/vpnmon-r3.sh b/vpnmon-r3.sh
index ed47949..2178cd1 100644
--- a/vpnmon-r3.sh
+++ b/vpnmon-r3.sh
@@ -1,20 +1,20 @@
#!/bin/sh
-# VPNMON-R3 v1.6.1 (VPNMON-R3.SH) is an all-in-one script that is optimized to maintain multiple VPN connections and is
+# VPNMON-R3 v1.6.2 (VPNMON-R3.SH) is an all-in-one script that is optimized to maintain multiple VPN connections and is
# able to provide for the capabilities to randomly reconnect using a specified server list containing the servers of your
# choice. Special care has been taken to ensure that only the VPN connections you want to have monitored are tended to.
# This script will check the health of up to 5 VPN connections on a regular interval to see if monitored VPN conenctions
# are connected, and sends a ping to a host of your choice through each active connection. If it finds that a connection
# has been lost, it will execute a series of commands that will kill that single VPN client, and randomly picks one of
# your specified servers to reconnect to for each VPN client.
-# Last Modified: 2025-Aug-23
+# Last Modified: 2025-Aug-24
##########################################################################################
#Preferred standard router binaries path
export PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"
#Static Variables - please do not change
-version="1.6.1" # Version tracker
+version="1.6.2" # Version tracker
beta=0 # Beta switch
screenshotmode=0 # Switch to present bogus info for screenshots
apppath="/jffs/scripts/vpnmon-r3.sh" # Static path to the app
@@ -6297,6 +6297,7 @@ do
do
#Set variables
citychange=""
+ ubsync=""
#determine if the slot is monitored#
if [ "$((VPN$i))" = "1" ]; then
@@ -6536,6 +6537,7 @@ do
do
#Set variables
wgcitychange=""
+ ubsync=""
#determine if the slot is monitored#
if [ "$((WG$i))" = "1" ]; then