├── version.txt ├── Unbound ├── openvpn-event ├── nat-start └── unbound_DNS_via_OVPN.sh ├── event.txt ├── DNSMonitor ├── changelog.txt └── merlin-dns-monitor.sh ├── enhancements.txt ├── README.md ├── LICENSE ├── archive └── vpnmon-r2-1.3.sh └── changelog.txt /version.txt: -------------------------------------------------------------------------------- 1 | 2.65 2 | -------------------------------------------------------------------------------- /Unbound/openvpn-event: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | [ "${dev:0:4}" = 'tun1' ] && vpn_id=${dev:4:1} && [ "$script_type" = 'route-up' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh $vpn_id start & 4 | [ "${dev:0:4}" = 'tun1' ] && vpn_id=${dev:4:1} && [ "$script_type" = 'route-pre-down' ] && /jffs/addons/unbound/unbound_DNS_via_OVPN.sh $vpn_id stop & 5 | -------------------------------------------------------------------------------- /event.txt: -------------------------------------------------------------------------------- 1 | NORMAL 2 | 3 | # Valid options for remotely controlling your VPN connection or router resets are as follows. Command MUST be entered on line 1. 4 | # 5 | # RESET -- This will cause VPNMON-R2 to intiate a VPN connection reset 6 | # REBOOT -- This will cause VPNMON-R2 to intiate a reboot of your router 7 | # NORMAL -- This will allow VPNMON-R2 to continue normal operations 8 | -------------------------------------------------------------------------------- /DNSMonitor/changelog.txt: -------------------------------------------------------------------------------- 1 | I have reposted this great tool here for safekeeping after @eibgrad stopped participating in the forums, and stopped updating 2 | his scripts. The DNS monitor tool is an invaluable script to help diagnose current DNS traffic behavior on your Merlin Asus 3 | router, especially when getting VPNMON-R2 configured using Unbound over VPN. 4 | 5 | v1.4.3 (Oct 7, 2023) 6 | - Modified a few egrep commands, and changed to grep -E as this command may have been controverted. 7 | 8 | v1.4.2 9 | - Original Script as left by @eibgrad 10 | -------------------------------------------------------------------------------- /Unbound/nat-start: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sleep 10 # During the boot process nat-start may run multiple times so this is required 4 | 5 | # Ensure duplicate rules are not created 6 | for VPN_ID in 0 1 2 3 4 5 7 | do 8 | ip rule del prio 999$VPN_ID 2>/dev/null 9 | done 10 | 11 | # Create the RPDB rules 12 | ip rule add from 0/0 fwmark "0x8000/0x8000" table main prio 9990 # WAN fwmark 13 | ip rule add from 0/0 fwmark "0x7000/0x7000" table ovpnc4 prio 9991 # VPN 4 fwmark 14 | ip rule add from 0/0 fwmark "0x3000/0x3000" table ovpnc5 prio 9992 # VPN 5 fwmark 15 | ip rule add from 0/0 fwmark "0x1000/0x1000" table ovpnc1 prio 9993 # VPN 1 fwmark 16 | ip rule add from 0/0 fwmark "0x2000/0x2000" table ovpnc2 prio 9994 # VPN 2 fwmark 17 | ip rule add from 0/0 fwmark "0x4000/0x4000" table ovpnc3 prio 9995 # VPN 3 fwmark 18 | -------------------------------------------------------------------------------- /Unbound/unbound_DNS_via_OVPN.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | VER="v1.01" 3 | 4 | # v1.00 12 Oct 2021 Martineau Hack from @Swinson original see http://www.snbforums.com/threads/unbound-dns-vpn-client-w-policy-rules.67370/post-653427 5 | 6 | 7 | Check_Tun_Con() { 8 | ping -c1 -w1 -I tun1$VPN_ID 9.9.9.9 9 | } 10 | Delete_Rules() { 11 | iptables-save | grep "unbound_rule" | sed 's/^-A/iptables -t mangle -D/' | while read CMD;do $CMD;done 12 | } 13 | Add_Rules(){ 14 | Delete_Rules 15 | iptables -t mangle -A OUTPUT -d "${wan0_dns##*.*.*.* }"/32 -p udp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_WAN 16 | iptables -t mangle -A OUTPUT -d "${wan0_dns%% *.*.*.*}"/32 -p udp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_WAN 17 | iptables -t mangle -A OUTPUT -d "${wan0_dns##*.*.*.* }"/32 -p tcp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_WAN 18 | iptables -t mangle -A OUTPUT -d "${wan0_dns%% *.*.*.*}"/32 -p tcp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_WAN 19 | iptables -t mangle -A OUTPUT -p tcp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_VPN 20 | iptables -t mangle -A OUTPUT -p udp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_VPN 21 | } 22 | Call_unbound_manager() { 23 | /jffs/addons/unbound/unbound_manager.sh vpn="$1" 24 | } 25 | Poll_Tun() { 26 | timer=$1 27 | [ "$timer" == "0" ] && Post_log "Error Timeout" && exit 1 || sleep 2 28 | Check_Tun_Con && Add_Rules && Call_unbound_manager "$VPN_ID" || Poll_Tun "$((timer-1))" 29 | } 30 | Post_log() { 31 | $(logger -st "($(basename "$0"))" $$ "$@") 32 | } 33 | 34 | #=============================================================Main============================================================== 35 | Main() { true; } # Syntax that is Atom Shellchecker compatible! 36 | 37 | modprobe xt_comment # v1.01 38 | 39 | [ -z "$2" ] && Post_log "Script request Invalid e.g. Usage: $(basename "$0") 1 start" && exit 1 || Post_log "Starting Script Execution $@" 40 | 41 | VPN_ID=$1 # The desired VPN instance (1 to 5) 42 | 43 | [ -z $(echo "$VPN_ID" | grep -E "^[1-5]$") ] && { Post_log "Invalid VPN client '$VPN_ID' - use 1-5 e.g. $(basename "$0") 1 start"; exit 1; } # v1.01 44 | 45 | [ -z "$3" ] && MAX_WAIT=150 || MAX_WAIT=$3 # Maximum wait time for tunnel is x 2secs i.e. MAX_WAIT=5 is total 10 secs 46 | 47 | 48 | # nat-start must contain see https://github.com/RMerl/asuswrt-merlin.ng/wiki/Policy-based-Port-routing-(manual-method)#installation 49 | TAG_MARK_WAN="0x8000/0x8000" 50 | # VPN 1 use 0x1000; VPN 2 use 0x2000 etc. 51 | case $VPN_ID in 52 | 1|2) TAG_MARK_VPN="0x${VPN_ID}000/0x${VPN_ID}000";; 53 | 3) TAG_MARK_VPN="0x4000/0x4000";; 54 | 4) TAG_MARK_VPN="0x7000/0x7000";; 55 | 5) TAG_MARK_VPN="0x3000/0x3000";; 56 | esac 57 | 58 | wan0_dns="$(nvram get wan0_dns)" 59 | 60 | iptables -t mangle -A OUTPUT -p udp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_VPN 61 | iptables -t mangle -A OUTPUT -d "${wan0_dns##*.*.*.* }"/32 -p udp --dport 53 -m comment --comment unbound_rule -j MARK --set-mark $TAG_MARK_WAN 62 | 63 | Delete_Rules 64 | 65 | case "$2" in 66 | start) 67 | Poll_Tun "$MAX_WAIT" "$VPN_ID" && Post_log "Ending Script Execution" && exit 0;; 68 | stop) 69 | Call_unbound_manager "disable" && Post_log "Ending Script Execution" && exit 0;; 70 | *) 71 | Post_log "Script Arg '' Invalid - e.g. $(basename "$0") 3 start" && exit 1;; 72 | esac 73 | -------------------------------------------------------------------------------- /enhancements.txt: -------------------------------------------------------------------------------- 1 | Future Enhancements (Planned) 2 | ----------------------------- 3 | 4 | To-Do: 5 | ------ 6 | * Look into more granular city/feature control of VPN slots that won't participate in superrandom 7 | * Scheduling the start & stop screening i.e. auto cron list management (@salvo) 8 | * Look at connecting the next vpn tunnel before the 1st one disconnects to make it more seamless - @eleVator 9 | 10 | 11 | Completed: 12 | ---------- 13 | * Look into Unbound support, to launch the VPN=# Unbound command when the tunnel/slot changes. 14 | * Autostart script in the post-mount file 15 | * Look at providing some external means of forcing a reset through a file on a remote server. 16 | * Update NordVPN API with more optimized versions. 17 | * Add AirVPN as another supported VPN Provider along with VPN stats and superrandom capabilities. 18 | * Implement a rudimentary killswitch so when VPN drops, or script is running with VPN off, killswitch = ON (@ComputerSteve) 19 | * Implement a failover switch to handling incoming WAN configuration changes from Ranger802004's WAN_Failover script 20 | * Allow for the update menu to (F)orce download an existing version, even if versions match. 21 | * Include a halt-type of command that goes into pause mode, and kills all vpn connections, when resumed, resumes killed vpn slot 22 | * Include another menu option "Allow VPN Connection on WAN1?". This would prevent vpnmon-r2 from making a vpn connection if WAN1 became active. 23 | * Add detected ping value, which VPN tunel has been reseted and what was WAN link ping to logging file (@salvo) 24 | Tue Oct 18 10:19:45 CEST 2022 - VPNMON-R2 ----------> WARNING: AVG PING across VPN tunnel > 100 ms - Executing VPN Reset 25 | * include more info on why "Lowest Ping" switched to a different client (@salvo) 26 | Tue Oct 18 13:59:55 CEST 2022 - VPNMON-R2 ----------> WARNING: Switching to faster VPN2 Client - Executing VPN Reset 27 | * Suggest to name the connection which failed i.e. WAN or VPNX (@salvo) 28 | Wed Oct 19 10:22:07 CEST 2022 - VPNMON-R2 ----------> ERROR: Connection failed - Executing VPN Reset 29 | * round robin vpn slots 30 | * Restart script after config changes are made so you don't have to exit & restart 31 | * Include stats row: method of slot selection, # of tries, # of pings before reset, ms ping reset 32 | * Look into using the Nordvpn Recommended servers option 33 | * After executing vpnmon-r2 -screen, execute the screen window instead of dropping back to a prompt with instructions. 34 | * Add the screen -wipe command 35 | * Only kill the number of VPN slots that are actually configured per VPNMON-R2 config. 36 | * WeVPN integration 37 | * Other VPN providers that offer API solutions to easier integrate between them and vpnmon-r2, starting with NordVPN 38 | - Surfshark VPN integration (completed) 39 | - Perfect privacy VPN integration (completed) 40 | * Utilize the ping value going across the tunnel as a parameter to intiate a reset with - thanks @JAX1337 (completed) 41 | * Log purging methodology (Thinking of purging log file 1x/week or 1x/month on a certain weekday or day of the month 42 | based on user input/preference) (completed) 43 | * Other possible stats to display: 44 | - Snapshot of current upload/download bandwidth amounts going over VPN pipe (if this is even available) (completed) 45 | * Integrate VPNON functionality within VPNMON-R2 itself, as in being able to call a vpn reset function within VPNMON-R2 46 | and performing the same function as what VPNON does. 47 | 48 | Ideas or Discussion 49 | ------------------- 50 | If you have any ideas or requests, please don't hesitate to mention them here in the forums for further discussion: 51 | https://www.snbforums.com/threads/release-vpnmon-r2-v1-1-a-script-that-monitors-your-vpn-connection.76748/ 52 | -------------------------------------------------------------------------------- /DNSMonitor/merlin-dns-monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # name: merlin-dns-monitor.sh 4 | # version: 1.4.2, 26-apr-2022, by eibgrad 5 | # version: 1.4.3, 07-oct-2023, by Viktor Jaep 6 | # purpose: monitor what dns servers are active and where routed 7 | # type(s): n/a (will autostart immediately upon download) 8 | # href: https://tinyurl.com/2p8fn7xu 9 | # installation: 10 | # 1. ssh to router and copy/paste the following command: 11 | # curl -kLs bit.ly/merlin-installer|tr -d '\r'|sh -s AGNF8cC8 12 | # 2. modify script w/ your preferred options using nano editor: 13 | # nano /tmp/merlin-dns-monitor.sh 14 | # 15 | # note: script is NOT persistent across a reboot, since it's stored in /tmp 16 | # upon download and immediately executed 17 | 18 | SCRIPTS_DIR='/tmp' 19 | SCRIPT="$SCRIPTS_DIR/merlin-dns-monitor.sh" 20 | 21 | mkdir -p $SCRIPTS_DIR 22 | 23 | # ------------------------------ BEGIN OPTIONS ------------------------------- # 24 | 25 | # how often (in secs) to update display (min 3, max 30) 26 | INTERVAL=6 27 | 28 | # uncomment/comment to enable/disable logging of Do53 connections over WAN 29 | #LOGGING= 30 | 31 | # ------------------------------- END OPTIONS -------------------------------- # 32 | 33 | # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- # 34 | 35 | cat << 'EOF' > $SCRIPT 36 | #!/bin/sh 37 | 38 | BNAME="$(basename $0 .sh)" 39 | 40 | WAN_CHECK_DOMAIN="$(nvram get dns_probe_host)" 41 | HOSTS_FILE='/etc/hosts' 42 | 43 | # display color attributes 44 | RED='\033[0;31m' 45 | YELLOW='\033[0;33m' 46 | GREEN='\033[0;32m' 47 | 48 | # display monochrome attributes 49 | NORMAL='\033[0m' 50 | BOLD='\033[1m' 51 | ITALIC='\033[3m' 52 | UNDERLINE='\033[4m' 53 | 54 | # display command menu attributes (color and monochrome) 55 | CMENU='\033[7;36m' # reverse + cyan 56 | MMENU='\033[7m' # reverse only 57 | 58 | # display reset attribute 59 | RS='\033[0m' 60 | 61 | # display update interval boundaries 62 | MIN_INTERVAL=3 63 | MAX_INTERVAL=30 64 | 65 | # work files 66 | HEAD="/tmp/tmp.$$.$BNAME.head" 67 | BODY="/tmp/tmp.$$.$BNAME.body" 68 | DATA="/tmp/tmp.$$.$BNAME.data" 69 | LOG="/tmp/tmp.$$.$BNAME.log"; > $LOG 70 | 71 | # function max_val( val1 val2 ) 72 | max_val() { echo $(($1 < $2 ? $2 : $1)); } 73 | 74 | # function min_val( val1 val2 ) 75 | min_val() { echo $(($1 > $2 ? $2 : $1)); } 76 | 77 | # function wan_check_enabled() 78 | wan_check_enabled() { 79 | ! grep -q " $WAN_CHECK_DOMAIN # $BNAME$" "$HOSTS_FILE" 80 | } 81 | 82 | # function toggle_wan_check() 83 | toggle_wan_check() { 84 | [ "$WAN_CHECK_DOMAIN" ] || return 1 85 | 86 | if wan_check_enabled; then 87 | local ip="$(nslookup $WAN_CHECK_DOMAIN | \ 88 | awk '/^Name:/,0 {if (/^Addr[^:]*: [0-9]{1,3}\./) print $3}')" 89 | 90 | if [ "$ip" ]; then 91 | echo "$ip $WAN_CHECK_DOMAIN # $BNAME" >> $HOSTS_FILE 92 | else 93 | return 1 94 | fi 95 | else 96 | sed -i "/ $WAN_CHECK_DOMAIN # $BNAME$/d" $HOSTS_FILE 97 | fi 98 | 99 | return 0 100 | } 101 | 102 | # function format_header() 103 | format_header() { 104 | local prof ip adns rgw sw_vpn_printed 105 | 106 | # publish wan/lan ip information 107 | if echo "$(nvram get wans_dualwan)" | grep -q 'none'; then 108 | printf 'WAN/LAN IP: %s/%s\n\n' \ 109 | $wan0_ip_4disp $(nvram get lan_ipaddr) 110 | else 111 | printf 'WAN1/WAN2/LAN IP: %s/%s/%s\n\n' \ 112 | $wan0_ip_4disp $wan1_ip_4disp $(nvram get lan_ipaddr) 113 | fi 114 | 115 | # publish wan/dhcp dns information 116 | printf " WAN DNS: $(echo $(awk '/^nameserver /{print $2}' \ 117 | /etc/resolv.conf) | sed -r 's/ /, /g')\n" 118 | printf "DHCP DNS: $(echo $(awk -F'[= ]' '/^server=/{print $2}' \ 119 | /tmp/resolv.dnsmasq) | sed -r 's/ /, /g')\n" 120 | 121 | # publish dot (stubby) dns information 122 | if [ "$(nvram get dnspriv_enable)" == '1' ]; then 123 | case $(nvram get dnspriv_profile) in 124 | '0') prof='Opportunistic';; 125 | '1') prof='Strict';; 126 | esac 127 | 128 | printf " DoT DNS: $(echo $(awk '/address_data/{print $3}' \ 129 | /etc/stubby/stubby.yml) | sed -r 's/ /, /g') ($prof)\n" 130 | fi 131 | 132 | # publish openvpn information 133 | for i in 1 2 3 4 5; do 134 | ip="$(ifconfig tun1${i} 2>/dev/null | \ 135 | awk '/inet addr/{split ($2,A,":"); print A[2]}')" 136 | 137 | [ "$ip" ] || continue 138 | 139 | case $(nvram get vpn_client${i}_adns) in 140 | '0') adns='Disabled';; 141 | '1') adns='Relaxed';; 142 | '2') adns='Strict';; 143 | '3') adns='Exclusive';; 144 | esac 145 | 146 | case $(nvram get vpn_client${i}_rgw) in 147 | '0') rgw='No';; 148 | '1') rgw='Yes';; 149 | '2') rgw='VPN Director';; 150 | esac 151 | 152 | printf "\nOVPN${i} IP/DNS Config/Redirect Internet: $ip/$adns/$rgw" 153 | 154 | sw_vpn_printed= 155 | done 156 | 157 | [ ${sw_vpn_printed+x} ] && printf '\n' 158 | 159 | printf "\nActive DNS (Do53/DoT) UDP/TCP Connections\n" 160 | printf " ${sev_lvl_2}Do53 (plaintext) routed over the WAN${RS}\n" 161 | printf " ${sev_lvl_1}DoT (ciphertext) routed over the WAN${RS}\n" 162 | printf " ${sev_lvl_0}Do53/DoT NOT routed over the WAN " 163 | printf "(loopback, local, or VPN)${RS}\n" 164 | echo ' ' 165 | } 166 | 167 | # function format_body() 168 | format_body() { 169 | _print_with_dupe_count() { 170 | local dupe_count=0 171 | local prev_line="$(head -n1 $DATA)" 172 | 173 | # print line w/ duplicate line-count indicator 174 | __print_line() { 175 | if [ $dupe_count -gt 1 ]; then 176 | printf '%-93s %s\n' "$prev_line" "($dupe_count)" 177 | else 178 | echo "$prev_line" 179 | fi 180 | } 181 | 182 | # find and print unique lines while counting duplicates 183 | while read line; do 184 | if [ "$line" == "$prev_line" ]; then 185 | let dupe_count++ 186 | else 187 | __print_line; prev_line="$line"; dupe_count=1 188 | fi 189 | done < $DATA 190 | 191 | [ "$prev_line" ] && __print_line 192 | } 193 | 194 | # publish Do53 over udp (replied and sorted) 195 | grep '^ipv4 .* udp .* dport=53 ' /proc/net/nf_conntrack | \ 196 | awk '$0 !~ /UNREPLIED/{printf "%s %-19s %-19s %-9s %-19s %s\n", 197 | $3, $6, $7, $9, $10, $11}' | \ 198 | sort > $DATA 199 | 200 | # remove duplicates; optionally include dupe count 201 | [ ${sw_dupes+x} ] && _print_with_dupe_count || uniq $DATA 202 | 203 | # publish Do53/DoT over tcp (replied and sorted) 204 | grep -E '^ipv4 .* tcp .* dport=(53|853) ' /proc/net/nf_conntrack | \ 205 | awk '/ASSURED/{printf "%s %-19s %-19s %-9s %-19s %s\n", 206 | $3, $7, $8, $10, $11, $12}' | \ 207 | sort > $DATA 208 | 209 | # remove duplicates; optionally include dupe count 210 | [ ${sw_dupes+x} ] && _print_with_dupe_count || uniq $DATA 211 | } 212 | 213 | # function pause_display() 214 | pause_display() { 215 | read -sp "$(echo -e ${menu}"\nPress [Enter] key to continue..."${RS})" \ 216 | < "$(tty 0>&2)" 217 | } 218 | 219 | # function exit_0() 220 | exit_0() { 221 | # publish name of log file 222 | [ -s $LOG ] && echo -e "\nlog file: $LOG" || rm -f $LOG 223 | 224 | # reenable wan check 225 | wan_check_enabled || toggle_wan_check 226 | 227 | # cleanup work files 228 | rm -f $HEAD $BODY $DATA 229 | 230 | # publish information on restarting 231 | echo -e "\nRun $0 to restart." 232 | 233 | exit 0 234 | } 235 | 236 | # trap on unexpected exit (e.g., crtl-c) 237 | trap 'exit_0' SIGHUP SIGINT SIGTERM 238 | 239 | # enable header 240 | sw_head= 241 | 242 | # set initial update interval 243 | interval=$(max_val $MIN_INTERVAL $(min_val $INTERVAL $MAX_INTERVAL)) 244 | 245 | # set initial logging state 246 | [ "$LOGGING" ] && sw_log= 247 | 248 | # begin display loop 249 | while :; do 250 | 251 | # establish wan ip(s) for analysis and display 252 | wan0_ip="$(nvram get wan0_ipaddr)" 253 | wan0_ip_4disp="$([ ${sw_wanip+x} ] && echo 'x.x.x.x' || echo $wan0_ip)" 254 | wan1_ip="$(nvram get wan1_ipaddr)" 255 | wan1_ip_4disp="$([ ${sw_wanip+x} ] && echo 'y.y.y.y' || echo $wan1_ip)" 256 | 257 | # set display attributes (color (default) or monochrome) 258 | if [ ! ${sw_mono+x} ]; then 259 | sev_lvl_2="$RED" 260 | sev_lvl_1="$YELLOW" 261 | sev_lvl_0="$GREEN" 262 | menu="$CMENU" 263 | else 264 | sev_lvl_2="$BOLD" 265 | sev_lvl_1="$UNDERLINE" 266 | sev_lvl_0="$NORMAL" 267 | menu="$MMENU" 268 | fi 269 | 270 | # format command menu 271 | wan_check_enabled && _wan='disable' || _wan='enable' 272 | [ ${sw_head+x} ] && _head='hide' || _head='show' 273 | [ ${sw_wanip+x} ] && _wanip='show' || _wanip='hide' 274 | [ ${sw_dupes+x} ] && _dupes='hide' || _dupes='show' 275 | [ ${sw_mono+x} ] && _mono='disable' || _mono='enable' 276 | [ ${sw_scroll+x} ] && _scroll='disable' || _scroll='enable' 277 | [ ${sw_log+x} ] && _log='disable' || _log='enable' 278 | 279 | # format header 280 | [ ${sw_head+x} ] && format_header > $HEAD 281 | 282 | # format body 283 | format_body > $BODY 284 | 285 | # clear display 286 | clear 287 | 288 | # start of "more-able" output 289 | { 290 | # display command menu 291 | if [ ! ${sw_next+x} ]; then 292 | printf "${menu}%s | %s | %s | %s | %s | %s%s${RS}\n" \ 293 | "[n]ext menu" \ 294 | "$_wan [w]an check" \ 295 | "$_head [h]eader" \ 296 | "[+/-] interval ($interval)" \ 297 | "[p]ause" \ 298 | "[e]xit" \ 299 | '' 300 | else 301 | printf "${menu}%s | %s | %s | %s | %s | %s%s${RS}\n" \ 302 | "[n]ext menu" \ 303 | "$_wanip wan [i]p" \ 304 | "$_dupes [d]upes" \ 305 | "$_mono [m]ono" \ 306 | "$_scroll [s]croll" \ 307 | "$_log [l]og" \ 308 | '' 309 | fi 310 | 311 | # display header 312 | [ ${sw_head+x} ] && cat $HEAD 313 | 314 | # display column headings 315 | printf '%43s' 'v-------------- sender ---------------v' 316 | printf '%50s\n' 'v------------- recipient -------------v' 317 | 318 | # display body/data (include severity level 0|1|2) 319 | while read line; do 320 | # hide wan/public ip(s) when requested 321 | if [ ${sw_wanip+x} ]; then 322 | line_4disp="$(echo "$line" | \ 323 | sed -r "s/(src|dst)=$wan0_ip($)/\1=$wan0_ip_4disp/g; \ 324 | s/(src|dst)=$wan0_ip( +)/\1=$wan0_ip_4disp /g; \ 325 | s/(src|dst)=$wan1_ip($)/\1=$wan1_ip_4disp/g; \ 326 | s/(src|dst)=$wan1_ip( +)/\1=$wan1_ip_4disp /g")" 327 | else 328 | line_4disp="$line" 329 | fi 330 | 331 | if echo $line | grep 'dport=53 ' | \ 332 | grep -qE "(src|dst)=($wan0_ip|$wan1_ip)( |$)"; then 333 | # Do53 connection routed over WAN 334 | printf "${sev_lvl_2}$line_4disp${RS}\n" 335 | 336 | # log the connection (optional) 337 | if [ ${sw_log+x} ]; then 338 | # remove dupe count (if present) 339 | line="$(echo "$line" | sed 's/\s*([0-9]*)$//')" 340 | # ignore duplicates 341 | grep -qxF "$line" $LOG || echo "$line" >> $LOG 342 | fi 343 | elif echo $line | grep 'dport=853 ' | \ 344 | grep -qE "(src|dst)=($wan0_ip|$wan1_ip)( |$)"; then 345 | # DoT connection routed over WAN 346 | printf "${sev_lvl_1}$line_4disp${RS}\n" 347 | else 348 | # Do53/DoT connection NOT routed over WAN 349 | printf "${sev_lvl_0}$line_4disp${RS}\n" 350 | fi 351 | done < $BODY 352 | 353 | [ -s $BODY ] || echo '' 354 | 355 | # end of "more-able" output 356 | } 2>&1 | $([ ${sw_scroll+x} ] && echo 'tee' || echo 'more') 357 | 358 | # update display at regular interval (capture any user input) 359 | key_press=''; read -rsn1 -t $interval key_press < "$(tty 0>&2)" 360 | 361 | # handle key-press (optional) 362 | if [ $key_press ]; then 363 | case $key_press in 364 | # common/shared menu option(s) 365 | 'n') [ ${sw_next+x} ] && unset sw_next || sw_next=;; 366 | # primary menu options 367 | 'w') toggle_wan_check;; 368 | 'h') [ ${sw_head+x} ] && unset sw_head || sw_head=;; 369 | '+') interval=$(min_val $((interval+3)) $MAX_INTERVAL);; 370 | '-') interval=$(max_val $((interval-3)) $MIN_INTERVAL);; 371 | 'p') pause_display;; 372 | 'e') exit_0;; 373 | # secondary menu options 374 | 'i') [ ${sw_wanip+x} ] && unset sw_wanip || sw_wanip=;; 375 | 'd') [ ${sw_dupes+x} ] && unset sw_dupes || sw_dupes=;; 376 | 'm') [ ${sw_mono+x} ] && unset sw_mono || sw_mono=;; 377 | 's') [ ${sw_scroll+x} ] && unset sw_scroll || sw_scroll=;; 378 | 'l') [ ${sw_log+x} ] && unset sw_log || sw_log=;; 379 | esac 380 | fi 381 | 382 | done # end of 'while :; do' 383 | EOF 384 | [ ${LOGGING+x} ] && sed -ri 's/\$LOGGING/LOGGING/g' $SCRIPT 385 | sed -i "s:\$INTERVAL:$INTERVAL:g" $SCRIPT 386 | chmod +x $SCRIPT 387 | 388 | # begin execution 389 | $SCRIPT 390 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VPNMON-R2 2 | VPNMON-R2 v2.65 - Asus-Merlin VPN Monitor by Viktor Jaep, 2022-2023 3 | 4 | **NOTICE: This script has been discontinued as of January 25, 2024... please visit SNBForums.com to upgrade to VPNMON-R3. 5 | Link: https://www.snbforums.com/threads/vpnmon-r3-v1-10-january-23-2024-monitor-wan-dw-vpn-health-reset-multiple-vpn-connections.87801/** 6 | 7 | **Executive Summary**: VPNMON-R2 is an all-in-one script that is optimized for NordVPN, SurfShark VPN and Perfect Privacy VPN services. It can also compliment @JackYaz's VPNMGR program to maintain a NordVPN/PIA/WeVPN setup, and is able to function perfectly in a standalone environment with your own personal VPN service. This script will check the health of (up to) 5 VPN connections on a regular interval to see if one is connected, and sends a ping to a host of your choice through the active connection. If it finds that connection has been lost, it will execute a series of commands that will kill all VPN clients, will optionally whitelist all NordVPN/PerfectPrivacy VPN servers in the Skynet Firewall, and randomly picks one of your (up to) 5 VPN Clients to connect to. One of VPNMON-R2's unique features is called "SuperRandom", where it will randomly assign VPN endpoints for a random county (or your choice) to your VPN slots, and randomly connect to one of these. It will now also test your WAN connection, and put itself into standby until the WAN is restored before reconnecting your VPN connections. 8 | 9 | I am by no means a serious script programmer. I've combed through lots of code and examples found both on the Merlin FW discussion forums and online to cobble this stuff together. You will probably find inefficient code, or possibly shaking your head with the rudimentary ways I'm pulling things off... but hey, I'm learning, it's fun, and it works! ;) Huge thanks and shoutouts to @JackYaz, @eibgrad and @Martineau for their inspiration and gorgeous looking code, and for everyone else that has helped me along the way on the Merlin forums: https://www.snbforums.com/forums/asuswrt-merlin.42/. As always, a huge thank you and a lot of admiration also goes out to @RMerlin, @Adamm, @L&LD, @SomeWhereOverTheRainBow and @thelonelycoder for everything you've done for the community 10 | 11 | The Problem I was trying to solve 12 | --------------------------------- 13 | * As a former VPNMGR user, I had 5 different NordVPN VPN Client configurations populated on my Asus router running Merlin FW, each with a different city. There were times that I would lose connection to one of these servers, and the router would just endlessly keep trying to reconnect to no avail. Also, sometimes the SKynet firewall would block these NordVPN endpoints, and it would again, endlessly try to connect to a blocked endpoint. Other times, freakishly, I would have more than 1 VPN Client kick on for some reason. This program was built as a way to check to make sure VPN is connected, that the connection is clean, and that there aren't multiple instances running. If anything was off, it would launch a full-on assault and try to reset everything back to a normal state. 14 | * I also wanted a way for my VPN connection to reset each night, so that it would randomly select and connect to a different configuration, thus endpoint, so that I wouldn't be connected to the same city 24x7x365. 15 | * NordVPN literally has thousands of VPN endpoint servers which change frequently, depending on the distance or latency from your location scattered across the globe. On several occations, my Asus-Merlin-based Skynet firewall would block these VPN servers, and wanted to make sure I had a way to find all the latest VPN server IPs, and add them to the Skynet whitelist. 16 | * Above all, I wanted to make this script flexible enough for those who aren't running VPNMGR, using NordVPN or making use of the Skynet Firewall, so options have been built-in to bypass this functionality to make it usable in any VPN usage scenario. 17 | 18 | How is this script supposed to run? 19 | ----------------------------------- 20 | Personally, I run this script in its own SSH window from a PC that's connected directly to the Asus router, as it loops and checks the connection every 60 seconds. Installation instructions: 21 | 1. Download and install directly from AMTM, or using your favorite SSH tools, copy & paste this command: 22 | ``curl --retry 3 "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/master/vpnmon-r2-2.52.sh" -o "/jffs/scripts/vpnmon-r2.sh" && chmod a+rx "/jffs/scripts/vpnmon-r2.sh"`` 23 | 2. To initially configure this script, open up a dedicated SSH window, and simply execute the script 24 | ``sh /jffs/scripts/vpnmon-r2.sh -setup`` 25 | 3. Once you've successfully configured the various options, you can run the script using this command: 26 | ``sh /jffs/scripts/vpnmon-r2.sh -monitor`` 27 | 28 | One particular ingenious way to run this is using the "screen" utility continuously from the router itself, instead of an attached session. (FYI, during the 'vpnmon-r2.sh -setup' process, you will be prompted whether or not you want to install the "screen" utility) 29 | 30 | 1. First, make sure you install the "screen" utility (and have Entware installed): 31 | ``opkg install screen`` 32 | 2. The screen utility allows you to run the script in the background, detached from your current ssh session on the router itself. Type: 33 | ``screen -dmS vpnmon-r2 sh /jffs/scripts/vpnmon-r2.sh -monitor`` 34 | 3. You can then reattach to the running script at any time, from any ssh session, on any client machine! Type: 35 | ``screen -r vpnmon-r2`` 36 | 4. Perform the detach by hitting CTRL-A + D 37 | 38 | What this script does 39 | --------------------- 40 | 1. Checks the VPN State from NVRAM and determines if each of the 5 Clients are connected or not 41 | 2. If a VPN Client is connected, it sends a PING through to Google's DNS server to determine if the link is good (configurable) 42 | 3. If it determines that the VPN Client is down, or connection is broken, it will attempt to reset the VPN 43 | 4. If it determines that multiple VPN Clients are running, it will attempt to reset the VPN 44 | 5. If it determines that the NordVPN server load is too high (optional), it will attempt to reset the VPN 45 | 6. Updates Skynet whitelist with all US-based NordVPN endpoint IP addresses (optional) - FYI, you can easily change this for the country of your choice. 46 | 7. Updates VPNMGR cache with recommended NordVPN/PIA/WeVPN endpoint information (optional), and merges/refreshes these changes with your VPN Client configurations 47 | 8. Uses a randomizer to pick one of 5 different VPN Clients to connect to (configurable between 1 and 5) 48 | 9. It will loop through this process every 60 seconds (configurable) 49 | 10. Logs major events (resets/connection errors/etc) to a log file. 50 | 11. It will reset your VPN connection at a regularly scheduled time using the settings at the top of the script (optional) 51 | 12. It now shows the last time a VPN reset happened indicated by "Last Reset:", an indicator when the next reset will happen, and how often the interval happens (in seconds) on the easy-to-read VPNMON-R2 interface in your SSH shell, along with a progressbar to show script activity 52 | 13. Added a new API lookup to display the VPN exit node city/location next to the active VPN connection. This API is free, and guarantees at least 1000 lookups per month. In lieu of doing a lookup each single refresh interval, a location lookup is only done when either the script starts up fresh, when it detects VPNON doing a reset, or if VPNMON-R2 initiates a reset. 53 | 14. Added the concept of SuperRandom(tm) NordVPN Connections! This is a NordVPN feature only! When enabled, it will fill your VPN client slots with random VPN servers across the country of your choice. Distance, load, and performance be damned!! 54 | 15. Added an integrated configuration utility (by running "vpnmon-r2.sh -config") that steps you through all the options and saves results to a config file, without the need to manually edit and configure the script itself. 55 | 16. Added a script update checker, which notifies you when a new version becomes available, and allows you to easily download an install the latest script by using the 'vpnmon-r2.sh -update' command. 56 | 17. Optionally shows a row of stats on bottom row, indicating low/high ping times, server load, Avg sent/received bandwidth (in Mbps), and total traffic sent/received on the active tunnel. 57 | 18. Added the ability to specify up to 2 additional countries (for a total of 3) to randomly pick VPN servers located within that country. Yes, we have gone completely international! 58 | 19. Happy to report that VPNMON-R2 now integrates beautifully with YazFi - the premier expanded guest network utility for Merlin firmware! For those running multiple guest networks, VPNMON-R2 can now automatically update your guest network slots with the latest VPN slot that VPNMON-R2 just made a connection to, then performs the necessary steps to make YazFi acknowledge the change to ensure your guest client devices continue to work without interruption! 59 | 20. Added capabilities to check if your modem goes down, or your ISP stops working, then falls back and waits until your WAN comes back up in order to re-establish a VPN connection. 60 | 21. VPNMON-R2 is now SurfShark and Perfect Privacy VPN compatible. You will be able to enjoy many of the same features that NordVPN users have, such as SuperRandom functionality that will populate your VPN slots with random servers in your selected country, multi-country capable where SuperRandom will pick one of up to 3 of your selected countries, randomly fill your slots with servers from that country and connect to a random one, keeping an eye on the SurfShark server load, and reconnect to another server if it exceeds your set threshold... and of course, showing all the same stats we've all gotten so accustomed to. 61 | 22. Added capabilities to switch to the fastest connections based on ping ms to your VPN endpoints. 62 | 23. Happy to announce that VPNMON-R2 is now being included in AMTM! Many thanks to @thelonelycoder! 63 | 24. VPNMON-R2 is now compatible with WeVPN! 64 | 25. Added the NordVPN "Recommended Servers" functionality, giving you access to the closest, fastest, lowest latency servers to you! 65 | 26. Added the "Round Robin" method of picking your VPN slots! 66 | 27. Integrated with KILLMON and showing integrity status within the UI 67 | 28. Added AirVPN support! 68 | 29. Added Remote Reboot -- using a simple command in an internet-accessible file, you can remotely reset the VPN or reboot your router! 69 | 30. Added Auto Start after a router reboot... VPNMON-R2 will now run in the screen environment automatically. 70 | 31. Added an integration with Unbound! Become your own secure DNS resolvers with queries being done over your VPN connection! 71 | 72 | What if I'm not running VPNMGR/NordVPN(PIA/WeVPN)/Skynet? 73 | --------------------------------------------------------- 74 | * As long as your VPN slots are configured and tested using the VPN provider of your choice, this script will run perfectly fine, and can monitor, reset and randomly start a new VPN client slot for you each day. Please know, this script was written to compliment VPNMGR, and gives a heavy preference to NordVPN, Surfshark and Perfect Privacy, but none of which is required. 75 | * While stepping through the configuration utility ("vpnmon-r2.sh -config"), you can choose to disable the ability to update VPNMGR hosts, enable/disable specific NordVPN/SurfShark/Perfect Privacy functionality, and the ability to whitelist the latest NordVPN/Perfect Privacy servers in Skynet. 76 | * Let me know how you're using this script! Feel free to post in the forums. ;) 77 | Here: https://www.snbforums.com/threads/release-vpnmon-r2-a-script-that-monitors-your-vpn-connection.76748/ 78 | 79 | Usage 80 | ------- 81 | VPNMON-R2 is driven with commandline parameters. These are the available options: 82 | 83 | * vpnmon-r2 -h (or vpnmon-r2.sh -help) -- displays a short overview of available commands 84 | * vpnmon-r2 -log -- displays the contents of the VPNMON-R2 activity log in the NANO text editor 85 | * vpnmon-r2 -config -- launches the configuration utility and saves your settings to a local config file 86 | * vpnmon-r2 -update -- launches the script update utility to download the newest version 87 | * vpnmon-r2 -setup -- launches the setup menu to configure and add optional Entware components 88 | * vpnmon-r2 -reset -- initiates a VPN reset for use with setting up external CRON jobs (like the vpnon script did) 89 | * vpnmon-r2 -pause -- pauses all operations, sits back and waits for a -resume command 90 | * vpnmon-r2 -resume -- resumes normal operations of VPNMON-R2, coming from a -pause 91 | * vpnmon-r2 -status -- indicates the current status of VPNMON-R2, along with the last known used VPN slot 92 | * vpnmon-r2 -failover -- stops and resumes all operations during a manual WAN failover/failback 93 | * vpnmon-r2 -uninstall -- launches the uninstall utility that removes VPNMON-R2 from your router 94 | * vpnmon-r2 -screen -- launches VPNMON-R2 using the "screen" utility, and places it in -monitor mode 95 | * vpnmon-r2 -monitor -- launches VPNMON-R2 in a normal operations mode, ready to monitor the health of your VPN connections 96 | 97 | Gotchas 98 | ------- 99 | * If you want to make the integration with VPNMGR, please make sure you have installed VPNMGR, have populated your VPN slots with it, have tested refreshing its cache, and that you are able to successfully connect to your VPN provider before running this script. You may find the program and installation/configuration information here: https://www.snbforums.com/threads/v...ent-configurations-for-nordvpn-and-pia.64930/ 100 | * Make sure you keep your VPN Client slots sequential... don't use 1, 2, and 4... for instance. Keep it to 1, 2, and 3. 101 | * If you're using the NordVPN SuperRandom(tm) functionality, please be sure that each of your VPN slots are fully configured, as this function will only replace your "server address" IP and the "description" in NordVPN - [CITY] format. It is also important to disable the VPNMGR update so they don't conflict. 102 | 103 | Disclaimer 104 | ---------- 105 | Use at your own risk. I've been using this script successfully for a long time on an Asus RT-AC86U running Merlin FW v386.3_2, v386.4, and beyond. Currently running under v386.7_2 and v388.1. Please post any questions you may have to the forums (link below), and I will be happy to assist. 106 | 107 | Links/Forums 108 | ---------- 109 | * VPNMON-R2 - https://www.snbforums.com/threads/release-vpnmon-r2-a-script-that-monitors-your-vpn-connection.76748/ 110 | * VPNON - https://www.snbforums.com/threads/release-vpnon-a-script-to-help-reset-and-randomize-your-vpn-connections.76742/ 111 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /archive/vpnmon-r2-1.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # VPNMON-R2 v1.3 (VPNMON-R2.SH) is an all-in-one simple script which compliments @JackYaz's VPNMGR program to maintain a 4 | # NordVPN/PIA/WeVPN setup, though this is not a requirement, and can function without problems in a standalone environment. 5 | # This script checks your (up to) 5 VPN connections on a regular interval to see if one is connected, and sends a ping to a 6 | # host of your choice through the active connection. If it finds that connection has been lost, it will execute a series of 7 | # commands that will kill all VPN clients, and optionally use VPNMGR's functionality to poll NordVPN/PIA/WeVPN for updated 8 | # server names based on the locations you have selected in VPNMGR, optionally whitelists all selected NordVPN servers in the 9 | # Skynet Firewall, and randomly picks one of the 5 VPN Clients to connect to. Logging added to capture relevant events for 10 | # later review. As mentioned, disabling VPNMGR and Skynet functionality is completely supported should you be using other 11 | # VPN options, and as such, this script would help maintain an eye on your connection, and able to randomly reset it if 12 | # needed. 13 | 14 | # ------------------------------------------------------------------------------------------------------------------------- 15 | # Usage and configuration Guide - *UPDATED* 16 | # ------------------------------------------------------------------------------------------------------------------------- 17 | # All previous user-selectable options are now available through the Configuration Utility. You may access and run this 18 | # utility by running "vpnmon-r2.sh -config". Once configured, a "vpnmon-r2.cfg" file will be written to your 19 | # /jffs/addons/vpnmon-r2.d/ folder containing the options you have selected. Once everything looks good, you are able to 20 | # run VPNMON-R2 for under normal monitoring conditions using this command: "vpnmon-r2.sh -monitor". Please note this change 21 | # for any current automations you may have in place. To easily view the log file, enter: "vpnmon-r2.sh -log". You will be 22 | # prompted as new updates become available going forward with v1.2. Use "vpnmon-r2.sh -update" to update the script. 23 | 24 | # ------------------------------------------------------------------------------------------------------------------------- 25 | # System Variables (Do not change beyond this point or this may change the programs ability to function correctly) 26 | # ------------------------------------------------------------------------------------------------------------------------- 27 | Version="1.3" # Current version of VPNMON-R2 28 | DLVersion="0.0" # Current version of VPNMON-R2 from source repository 29 | LOCKFILE="/jffs/scripts/VPNON-Lock.txt" # Predefined lockfile that VPNON.sh creates when it resets the VPN so 30 | # that VPNMON-R2 does not interfere during a reset 31 | RSTFILE="/jffs/addons/vpnmon-r2.d/vpnmon-rst.log" # Logfile containing the last date/time a VPN reset was performed. Else, 32 | # the latest date/time that VPNMON-R2 restarted will be shown. 33 | LOGFILE="/jffs/addons/vpnmon-r2.d/vpnmon-r2.log" # Logfile path/name that captures important date/time events - change 34 | #LOGFILE="/dev/null" # to: "/dev/null" to disable this functionality. 35 | APPPATH="/jffs/scripts/vpnmon-r2.sh" # Path to the location of vpnmon-r2.sh 36 | CFGPATH="/jffs/addons/vpnmon-r2.d/vpnmon-r2.cfg" # Path to the location of vpnmon-r2.cfg 37 | DLVERPATH="/jffs/addons/vpnmon-r2.d/version.txt" # Path to downloaded version from the source repository 38 | connState="2" # Status = 2 means VPN is connected, 1 = connecting, 0 = not connected 39 | let BASE=1 # Random numbers start at BASE up to N, ie. 1..3 40 | STATUS=0 # Tracks whether or not a ping was successful 41 | VPNCLCNT=0 # Tracks to make sure there are not multiple connections running 42 | CURRCLNT=0 # Tracks which VPN client is currently active 43 | CNT=0 # Counter 44 | AVGPING=0 # Average ping value 45 | SPIN=10 # 10-second Spin timer 46 | state1=0 # Initialize the VPN connection states for VPN Clients 1-5 47 | state2=0 48 | state3=0 49 | state4=0 50 | state5=0 51 | START=$(date +%s) # Start a timer to determine intervals of VPN resets 52 | VPNIP="Unassigned" # Tracking VPN IP for city location display. API gives you 1K lookups 53 | # per day, and is optimized to only lookup city location after a reset 54 | VPNLOAD=0 # Variable tracks the NordVPN server load 55 | AVGPING=0 # Variable tracks average ping time 56 | PINGLOW=0 # Variable tracks lowest ping time 57 | PINGHIGH=0 # Variable tracks highest ping time 58 | SHOWSTATS=0 # Tracks whether you want to show stats on/off if you like minimalism 59 | rxbytes=0 # Variables to capture and measure TX/RX rates on VPN Tunnel 60 | txbytes=0 61 | txrxbytes=0 62 | rxgbytes=0 63 | txgbytes=0 64 | oldrxbytes=0 65 | newrxbytes=0 66 | oldtxbytes=0 67 | newtxbytes=0 68 | 69 | # Color variables 70 | CBlack="\e[1;30m" 71 | CRed="\e[1;31m" 72 | InvRed="\e[1;41m" 73 | CGreen="\e[1;32m" 74 | InvGreen="\e[1;42m" 75 | CYellow="\e[1;33m" 76 | CBlue="\e[1;34m" 77 | InvBlue="\e[1;44m" 78 | CMagenta="\e[1;35m" 79 | CCyan="\e[1;36m" 80 | InvCyan="\e[1;46m" 81 | CWhite="\e[1;37m" 82 | CClear="\e[0m" 83 | 84 | # ------------------------------------------------------------------------------------------------------------------------- 85 | # Functions 86 | # ------------------------------------------------------------------------------------------------------------------------- 87 | 88 | # Logo is a function that displays the VPNMON-R2 script name in a cool ASCII font 89 | logo () { 90 | echo -e "${CYellow} _ ______ _ ____ _______ _ __ ____ ___ " 91 | echo -e "| | / / __ \/ | / / |/ / __ \/ | / / / __ \__ \ " 92 | echo -e "| | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ /_/ / " 93 | echo -e "| |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/ __/ " 94 | echo -e "|___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ " 95 | echo "" 96 | } 97 | 98 | # ------------------------------------------------------------------------------------------------------------------------- 99 | 100 | # Promptyn is a function that helps return a 0 or 1 from a Y/N question from the configuration utility. 101 | promptyn () { 102 | while true; do 103 | read -p "$1 " yn 104 | case $yn in 105 | [Yy]* ) return 0;; 106 | [Nn]* ) return 1;; 107 | * ) echo "Please answer yes or no.";; 108 | esac 109 | done 110 | } 111 | 112 | # ------------------------------------------------------------------------------------------------------------------------- 113 | 114 | # Spinner is a script that provides a small indicator on the screen to show script activity 115 | spinner() { 116 | 117 | i=0 118 | j=$((SPIN / 4)) 119 | while [ $i -le $j ]; do 120 | for s in / - \\ \|; do 121 | printf "\r$s" 122 | sleep 1 123 | done 124 | i=$((i+1)) 125 | done 126 | 127 | printf "\r" 128 | } 129 | 130 | # ------------------------------------------------------------------------------------------------------------------------- 131 | 132 | # Preparebar and Progressbar is a script that provides a nice progressbar to show script activity 133 | preparebar() { 134 | # $1 - bar length 135 | # $2 - bar char 136 | barlen=$1 137 | barspaces=$(printf "%*s" "$1") 138 | barchars=$(printf "%*s" "$1" | tr ' ' "$2") 139 | } 140 | 141 | progressbar() { 142 | # $1 - number (-1 for clearing the bar) 143 | # $2 - max number 144 | if [ $1 -eq -1 ]; then 145 | printf "\r $barspaces\r" 146 | else 147 | barch=$(($1*barlen/$2)) 148 | barsp=$((barlen-barch)) 149 | progr=$((100*$1/$2)) 150 | printf "${CGreen}\r [%.${barch}s%.${barsp}s]${CClear} ${CYellow}${InvBlue}${i}s / ${progr}%%\r${CClear}" "$barchars" "$barspaces" 151 | fi 152 | } 153 | 154 | # ------------------------------------------------------------------------------------------------------------------------- 155 | 156 | updatecheck () { 157 | 158 | # Download the latest version file from the source repository 159 | curl --silent --retry 3 "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/master/version.txt" -o "/jffs/addons/vpnmon-r2.d/version.txt" 160 | 161 | if [ -f $DLVERPATH ] 162 | then 163 | # Read in its contents for the current version file 164 | DLVersion=$(cat $DLVERPATH) 165 | 166 | # Compare the new version with the old version and log it 167 | if [ "$DLVersion" != "$Version" ]; then 168 | UpdateNotify="Update available: v$Version -> v$DLVersion" 169 | echo -e "$(date) - VPNMON-R2 - A new update (v$DLVersion) is available to download" >> $LOGFILE 170 | else 171 | UpdateNotify=0 172 | fi 173 | fi 174 | 175 | } 176 | 177 | # ------------------------------------------------------------------------------------------------------------------------- 178 | 179 | # VPNReset() is a script based on my VPNON.SH script to kill connections and reconnect to a clean VPN state 180 | vpnreset() { 181 | 182 | # Start the VPN reset process 183 | echo -e "$(date) - VPNMON-R2 - Executing VPN Reset" >> $LOGFILE 184 | 185 | # Reset the VPN IP/Locations 186 | VPNIP="Unassigned" 187 | 188 | # Start the process 189 | echo -e "${CCyan}Step 1 - Kill all VPN Client Connections\n${CClear}" 190 | 191 | # Kill all current VPN client sessions 192 | echo -e "${CRed}Kill VPN Client 1${CClear}" 193 | service stop_vpnclient1 194 | echo -e "${CRed}Kill VPN Client 2${CClear}" 195 | service stop_vpnclient2 196 | echo -e "${CRed}Kill VPN Client 3${CClear}" 197 | service stop_vpnclient3 198 | echo -e "${CRed}Kill VPN Client 4${CClear}" 199 | service stop_vpnclient4 200 | echo -e "${CRed}Kill VPN Client 5${CClear}" 201 | service stop_vpnclient5 202 | echo -e "$(date) - VPNMON-R2 - Killed all VPN Client Connections" >> $LOGFILE 203 | 204 | # Export NordVPN IPs via API into a txt file, and import them into Skynet 205 | if [[ $UpdateSkynet -eq 1 ]] 206 | then 207 | curl --silent --retry 3 "https://api.nordvpn.com/v1/servers?limit=16384" | jq --raw-output '.[] | select(.locations[].country.name == "'"$NordVPNCountry"'") | .station' > /jffs/scripts/NordVPN.txt 208 | LINES=$(cat /jffs/scripts/NordVPN.txt | wc -l) #Check to see how many lines/server IPs are in this file 209 | 210 | if [ $LINES -eq 0 ] # If there are no lines, error out 211 | then 212 | echo -e "\n${CCyan}Step 2 - Error: NordVPN.txt list is blank! Check NordVPN service or config's Country Name.\n${CClear}" 213 | echo -e "$(date) - VPNMON-R2 - *** ERROR: NordVPN.txt list is blank!" >> $LOGFILE 214 | else 215 | 216 | echo -e "\n${CCyan}Step 2 - Updating Skynet whitelist with NordVPN Server IPs\n${CClear}" 217 | 218 | firewall import whitelist /jffs/scripts/NordVPN.txt 219 | 220 | echo -e "\n${CCyan}VPNMON-R2 is letting Skynet import and settle for $SPIN seconds\n${CClear}" 221 | 222 | spinner 223 | 224 | echo -e "$(date) - VPNMON-R2 - Updated Skynet Whitelist" >> $LOGFILE 225 | fi 226 | else 227 | echo -e "\n${CCyan}Step 2 - Skipping Skynet whitelist update with NordVPN Server IPs\n${CClear}" 228 | fi 229 | 230 | # Randomly select VPN Client slots against entire field of available NordVPN server IPs for selected country 231 | if [[ $NordVPNSuperRandom -eq 1 ]] 232 | then 233 | UpdateVPNMGR=0 # Failsafe to make sure VPNMGR doesn't overwrite values written by the SuperRandom function 234 | 235 | if [ -f /jffs/scripts/NordVPN.txt ] # Check to see if NordVPN file exists from UpdateSkynet 236 | then 237 | LINES=$(cat /jffs/scripts/NordVPN.txt | wc -l) # Check to see how many lines/server IPs are in this file 238 | 239 | if [ $LINES -eq 0 ] # If there are no lines, error out 240 | then 241 | echo -e "\n${CCyan}Step 3 - Error: NordVPN.txt list is blank! Check NordVPN service or config's Country Name.\n${CClear}" 242 | echo -e "$(date) - VPNMON-R2 - *** ERROR: NordVPN.txt list is blank!" >> $LOGFILE 243 | break 244 | fi 245 | 246 | echo -e "\n${CCyan}Step 3 - Updating VPN Slots 1 - $N from $LINES SuperRandom NordVPN Server IPs\n${CClear}" 247 | 248 | i=0 249 | while [[ $i -ne $N ]] # Assign SuperRandom IPs/Descriptions to VPN Slots 1-N 250 | do 251 | i=$(($i+1)) 252 | RANDOM=$(awk 'BEGIN {srand(); print int(32768 * rand())}') 253 | R_LINE=$(( RANDOM % LINES + 1 )) 254 | RNDVPNIP=$(sed -n "${R_LINE}p" /jffs/scripts/NordVPN.txt) 255 | RNDVPNCITY=$(curl --silent --retry 3 --request GET --url https://ipapi.co/$RNDVPNIP/city) 256 | nvram set vpn_client"$i"_addr="$RNDVPNIP" 257 | nvram set vpn_client"$i"_desc="NordVPN - $RNDVPNCITY" 258 | echo -e "\n${CGreen}VPN Slot $i - Assigned SuperRandom IP: $RNDVPNIP - City: $RNDVPNCITY\n${CClear}" 259 | sleep 1 260 | done 261 | echo -e "$(date) - VPNMON-R2 - Refreshed VPN Slots 1 - $N from $LINES SuperRandom NordVPN Server Locations" >> $LOGFILE 262 | 263 | else 264 | 265 | # NordVPN.txt must not exist and/or UpdateSkynet is turned off, so run API to get full server list from NordVPN 266 | curl --silent --retry 3 "https://api.nordvpn.com/v1/servers?limit=16384" | jq --raw-output '.[] | select(.locations[].country.name == "'"$NordVPNCountry"'") | .station' > /jffs/scripts/NordVPN.txt 267 | LINES=$(cat /jffs/scripts/NordVPN.txt | wc -l) #Check to see how many lines/server IPs are in this file 268 | 269 | if [ $LINES -eq 0 ] #If there are no lines, error out 270 | then 271 | echo -e "\n${CCyan}Step 3 - Error: NordVPN.txt list is blank! Check NordVPN service or config's Country Name.\n${CClear}" 272 | echo -e "$(date) - VPNMON-R2 - *** ERROR: NordVPN.txt list is blank!" >> $LOGFILE 273 | break 274 | fi 275 | 276 | echo -e "\n${CCyan}Step 3 - Updating VPN Slots 1 - $N from $LINES SuperRandom NordVPN Server IPs\n${CClear}" 277 | 278 | i=0 279 | while [[ $i -ne $N ]] #Assign SuperRandom IPs/Descriptions to VPN Slots 1-N 280 | do 281 | i=$(($i+1)) 282 | RANDOM=$(awk 'BEGIN {srand(); print int(32768 * rand())}') 283 | R_LINE=$(( RANDOM % LINES + 1 )) 284 | RNDVPNIP=$(sed -n "${R_LINE}p" /jffs/scripts/NordVPN.txt) 285 | RNDVPNCITY=$(curl --silent --retry 3 --request GET --url https://ipapi.co/$RNDVPNIP/city) 286 | nvram set vpn_client"$i"_addr="$RNDVPNIP" 287 | nvram set vpn_client"$i"_desc="NordVPN - $RNDVPNCITY" 288 | echo -e "\n${CGreen}VPN Slot $i - Assigned SuperRandom IP: $RNDVPNIP - City: $RNDVPNCITY\n${CClear}" 289 | sleep 1 290 | done 291 | echo -e "$(date) - VPNMON-R2 - Refreshed VPN Slots 1 - $N from $LINES SuperRandom NordVPN Server Locations" >> $LOGFILE 292 | fi 293 | 294 | else 295 | 296 | echo -e "\n${CCyan}Step 3 - Skipping update of SuperRandom NordVPN Server IPs\n${CClear}" 297 | 298 | fi 299 | 300 | # Clean up API VPN Server Extracts 301 | if [ -f /jffs/scripts/NordVPN.txt ] 302 | then 303 | rm /jffs/scripts/NordVPN.txt #Cleanup 304 | fi 305 | 306 | # Call VPNMGR functions to refresh server lists and save their results to the VPN client configs 307 | if [[ $UpdateVPNMGR -eq 1 ]] 308 | then 309 | echo -e "${CCyan}Step 3 - Refresh VPNMGRs NordVPN/PIA/WeVPN Server Locations and Hostnames\n${CClear}" 310 | sh /jffs/scripts/service-event start vpnmgrrefreshcacheddata 311 | sleep 10 312 | sh /jffs/scripts/service-event start vpnmgr 313 | sleep 10 314 | echo -e "$(date) - VPNMON-R2 - Refreshed VPNMGR Server Locations and Hostnames" >> $LOGFILE 315 | else 316 | echo -e "\n${CCyan}Step 3 - Skipping VPNMGR update for NordVPN/PIA/WeVPN Server Locations and Hostname\n${CClear}" 317 | fi 318 | 319 | # Pick a random VPN Client to connect to 320 | echo -e "${CCyan}Step 4 - Randomly select a VPN Client between 1 and $N\n${CClear}" 321 | 322 | # Generate a number between BASE and N, ie.1 and 5 to choose which VPN Client is started 323 | RANDOM=$(awk 'BEGIN {srand(); print int(32768 * rand())}') 324 | option=$(( RANDOM % N + BASE )) 325 | 326 | # Set option to 1 in that rare case that it comes out to 0 327 | if [[ $option -eq 0 ]] 328 | then 329 | option=1 330 | fi 331 | 332 | # Start the selected VPN Client 333 | case ${option} in 334 | 335 | 1) 336 | service start_vpnclient1 337 | logger -t VPN Client1 "Active" 338 | echo -e "${CGreen}VPN Client 1 ON\n${CClear}" 339 | echo -e "$(date) - VPNMON-R2 - Randomly selected VPN1 Client ON" >> $LOGFILE 340 | ;; 341 | 342 | 2) 343 | service start_vpnclient2 344 | logger -t VPN Client2 "Active" 345 | echo -e "${CGreen}VPN Client 2 ON\n${CClear}" 346 | echo -e "$(date) - VPNMON-R2 - Randomly selected VPN2 Client ON" >> $LOGFILE 347 | ;; 348 | 349 | 3) 350 | service start_vpnclient3 351 | logger -t VPN Client3 "Active" 352 | echo -e "${CGreen}VPN Client 3 ON\n${CClear}" 353 | echo -e "$(date) - VPNMON-R2 - Randomly selected VPN3 Client ON" >> $LOGFILE 354 | ;; 355 | 356 | 4) 357 | service start_vpnclient4 358 | logger -t VPN Client4 "Active" 359 | echo -e "${CGreen}VPN Client 4 ON\n${CClear}" 360 | echo -e "$(date) - VPNMON-R2 - Randomly selected VPN4 Client ON" >> $LOGFILE 361 | ;; 362 | 363 | 5) 364 | service start_vpnclient5 365 | logger -t VPN Client5 "Active" 366 | echo -e "${CGreen}VPN Client 5 ON\n${CClear}" 367 | echo -e "$(date) - VPNMON-R2 - Randomly selected VPN5 Client ON" >> $LOGFILE 368 | ;; 369 | 370 | esac 371 | 372 | echo -e "${CCyan}VPNMON-R2 VPN Reset finished\n${CClear}" 373 | echo -e "$(date) - VPNMON-R2 - VPN Reset Finished" >> $LOGFILE 374 | 375 | # Check for any version updates from the source repository 376 | updatecheck 377 | 378 | # Reset Stats 379 | oldrxbytes=0 380 | oldtxbytes=0 381 | newrxbytes=0 382 | newtxbytes=0 383 | 384 | } 385 | 386 | # ------------------------------------------------------------------------------------------------------------------------- 387 | 388 | # checkvpn() is a script that checks each connection to see if its active, and performs a PING... borrowed 389 | # heavily and much credit to @Martineau for this code from his VPN-Failover script. 390 | 391 | checkvpn() { 392 | 393 | CNT=0 394 | TUN="tun1"$1 395 | VPNSTATE=$2 396 | 397 | if [[ $VPNSTATE -eq $connState ]] 398 | then 399 | while [[ $CNT -lt $TRIES ]]; do 400 | ping -I $TUN -q -c 1 -W 2 $PINGHOST &> /dev/null 401 | RC=$? 402 | if [[ $RC -eq 0 ]];then 403 | STATUS=1 404 | VPNCLCNT=$((VPNCLCNT+1)) 405 | AVGPING=$(ping -I $TUN -c 1 $PINGHOST | awk -F'time=| ms' 'NF==3{print $(NF-1)}' | sort -rn) 406 | 407 | if [[ $VPNIP == "Unassigned" ]];then 408 | VPNIP=$(nvram get vpn_client$1_addr) 409 | VPNCITY=$(curl --silent --retry 3 --request GET --url https://ipapi.co/$VPNIP/city) 410 | echo -e "$(date) - VPNMON-R2 - API call made to update city to $VPNCITY" >> $LOGFILE 411 | fi 412 | 413 | echo -e "${CGreen}==VPN$1 Tunnel is active | ||${CWhite}${InvGreen} $AVGPING ms ${CClear}${CGreen}|| | ${CClear}${CYellow}Exit: ${InvBlue}$VPNCITY${CClear}" 414 | CURRCLNT=$1 415 | break 416 | else 417 | sleep 1 418 | CNT=$((CNT+1)) 419 | 420 | if [[ $CNT -eq $TRIES ]];then 421 | STATUS=0 422 | echo -e "${CRed}x-VPN$1 Ping failed${CClear}" 423 | echo -e "$(date) - VPNMON-R2 - **VPN$1 Ping failed**" >> $LOGFILE 424 | fi 425 | fi 426 | done 427 | else 428 | echo "- VPN$1 Disconnected" 429 | fi 430 | } 431 | 432 | # ------------------------------------------------------------------------------------------------------------------------- 433 | # Begin Commandline Argument Gatekeeper and Configuration Utility Functionality 434 | # ------------------------------------------------------------------------------------------------------------------------- 435 | 436 | # Create the necessary folder/file structure for VPNMON-R2 under /jffs/addons 437 | if [ ! -d "/jffs/addons/vpnmon-r2.d" ]; then 438 | mkdir -p "/jffs/addons/vpnmon-r2.d" 439 | fi 440 | 441 | # Check for Updates 442 | updatecheck 443 | 444 | # Check and see if any commandline option is being used 445 | if [ $# -eq 0 ] 446 | then 447 | clear 448 | echo "" 449 | echo "VPNMON-R2 v$Version" 450 | echo "" 451 | echo "Exiting due to missing commandline options!" 452 | echo "(run 'vpnmon-r2.sh -h' for help)" 453 | echo "" 454 | exit 0 455 | fi 456 | 457 | # Check and see if an invalid commandline option is being used 458 | if [ "$1" == "-h" ] || [ "$1" == "-help" ] || [ "$1" == "-config" ] || [ "$1" == "-monitor" ] || [ "$1" == "-log" ] || [ "$1" == "-update" ] 459 | then 460 | clear 461 | else 462 | clear 463 | echo "" 464 | echo "VPNMON-R2 v$Version" 465 | echo "" 466 | echo "Exiting due to invalid commandline options!" 467 | echo "(run 'vpnmon-r2.sh -h' for help)" 468 | echo "" 469 | exit 0 470 | fi 471 | 472 | # Check to see if the help option is being called 473 | if [ "$1" == "-h" ] || [ "$1" == "-help" ] 474 | then 475 | clear 476 | echo "" 477 | echo "VPNMON-R2 v$Version Commandline Option Usage:" 478 | echo "" 479 | echo "vpnmon-r2.sh -h | -help" 480 | echo "vpnmon-r2.sh -log" 481 | echo "vpnmon-r2.sh -config" 482 | echo "vpnmon-r2.sh -update" 483 | echo "vpnmon-r2.sh -monitor" 484 | echo "" 485 | echo " -h | -help (this output)" 486 | echo " -log (display the current log contents)" 487 | echo " -config (configuration/setup utility)" 488 | echo " -update (script update utility)" 489 | echo " -monitor (normal VPN monitoring operations)" 490 | echo "" 491 | exit 0 492 | fi 493 | 494 | # Check to see if the log option is being called, and display through nano 495 | if [ "$1" == "-log" ] 496 | then 497 | nano $LOGFILE 498 | exit 0 499 | fi 500 | 501 | # Check to see if the configuration option is being called, and run through setup utility 502 | if [ "$1" == "-config" ] 503 | then 504 | clear 505 | if [ -f $CFGPATH ] #Making sure file exists before proceeding 506 | then 507 | logo 508 | echo -e "VPNMON-R2 v$Version Configuration Utility${CClear}" 509 | echo "" 510 | echo -e "${CCyan}Please answer the following items to successfully configure VPNMON-R2." 511 | echo -e "This process is the same for a new installation, or if you wanted to" 512 | echo -e "configure VPNMON-R2 with different options. Upon completion, you have" 513 | echo -e "the option to overwrite an existing config file. Would you like to" 514 | echo -e "continue?${CClear}" 515 | if promptyn "(Yes/No) "; then 516 | echo "" 517 | echo -e "${CCyan}Continuing Setup...${CClear}" 518 | echo "" 519 | else 520 | echo "" 521 | echo -e "${CGreen}Exiting Configuration Utility...${CClear}" 522 | echo "" 523 | kill 0 524 | fi 525 | echo -e "${CCyan}1. How many times would you like a ping to retry your VPN tunnel before" 526 | echo -e "resetting? ${CYellow}(Default = 3)${CClear}" 527 | read -p 'Ping Retries: ' TRIES 528 | echo "" 529 | echo -e "${CCyan}2. What interval (in seconds) would you like to check your VPN tunnel" 530 | echo -e "to ensure the connection is healthy? ${CYellow}(Default = 60)${CClear}" 531 | read -p 'Interval: ' INTERVAL 532 | echo "" 533 | echo -e "${CCyan}3. What host IP would you like to ping to determine the health of your " 534 | echo -e "VPN tunnel? ${CYellow}(Default = 8.8.8.8)${CClear}" 535 | read -p 'Host IP: ' PINGHOST 536 | echo "" 537 | echo -e "${CCyan}4. Would you like to update VPNMGR? (Note: must be already installed " 538 | echo -e "and you must be NordVPN/PIA/WeVPN subscriber) ${CYellow}(Default = No)${CClear}" 539 | if promptyn "(Yes/No): "; then 540 | UpdateVPNMGR=1 541 | else 542 | UpdateVPNMGR=0 543 | fi 544 | echo "" 545 | echo -e "${CCyan}5. Is NordVPN your default VPN Provider? ${CYellow}(Default = No)${CClear}" 546 | if promptyn "(Yes/No): "; then 547 | UseNordVPN=1 548 | else 549 | UseNordVPN=0 550 | fi 551 | 552 | if [ "$UseNordVPN" == "1" ]; then 553 | echo "" 554 | echo -e "${CCyan}5a. Would you like to use the NordVPN SuperRandom functionality?" 555 | echo -e "${CYellow}(Default = No)${CClear}" 556 | if promptyn "(Yes/No): "; then 557 | NordVPNSuperRandom=1 558 | else 559 | NordVPNSuperRandom=0 560 | fi 561 | echo "" 562 | echo -e "${CCyan}5b. What Country is your country of origin for NordVPN? ${CYellow}(Default = " 563 | echo -e "United States). NOTE: Country names must be spelled correctly as below!${CCyan}" 564 | echo "Valid country names as follows: Albania, Argentina, Australia, Austria," 565 | echo "Belgium, Bosnia and Herzegovina, Brazil, Bulgaria, Canada, Chile," 566 | echo "Costa Rica, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Finland," 567 | echo "France, Georgia, Germany, Greece, Hong Kong, Hungary, Iceland, India," 568 | echo "Indonesia, Ireland, Israel, Italy, Japan, Latvia, Lithuania, Luxembourg," 569 | echo "Malaysia, Mexico, Moldova, Netherlands, New Zealand, North Macedonia," 570 | echo "Norway, Poland, Portugal, Romania, Serbia, Singapore, Slovakia, Slovenia," 571 | echo "South Africa, South Korea, Spain, Sweden, Switzerland, Taiwan, Thailand," 572 | echo "Turkey, Ukraine, United Arab Emirates, United Kingdom, United States," 573 | echo -e "Vietnam.${CClear}" 574 | read -p 'NordVPN Country: ' NordVPNCountry 575 | echo "" 576 | echo -e "${CCyan}5c. At what VPN server load would you like to reconnect to a different" 577 | echo -e "NordVPN Server? ${CYellow}(Default = 50)${CClear}" 578 | read -p 'Server Load Threshold: ' NordVPNLoadReset 579 | echo "" 580 | echo -e "${CCyan}5d. Would you like to whitelist NordVPN servers in the Skynet Firewall?" 581 | echo -e "${CYellow}(Default = No)${CClear}" 582 | if promptyn "(Yes/No): "; then 583 | UpdateSkynet=1 584 | else 585 | UpdateSkynet=0 586 | fi 587 | else 588 | NordVPNSuperRandom=0 589 | NordVPNCountry="United States" 590 | NordVPNLoadReset=50 591 | UpdateSkynet=0 592 | fi 593 | echo "" 594 | echo -e "${CCyan}6. Would you like to reset your VPN connection to a random VPN client daily?" 595 | echo -e "${CYellow}(Default = Yes)${CClear}" 596 | if promptyn "(Yes/No): "; then 597 | ResetOption=1 598 | echo "" 599 | echo -e "${CCyan}6a. What time would you like to reset your connection? ${CYellow}(Default = 01:00)${CClear}" 600 | read -p 'Reset Time (in HH:MM 24h): ' DailyResetTime 601 | else 602 | ResetOption=0 603 | DailyResetTime="00:00" 604 | fi 605 | echo "" 606 | echo -e "${CCyan}7. How many VPN client slots do you have properly configured? ${CYellow}(Default = 5)${CClear}" 607 | read -p 'VPN Clients: ' N 608 | echo "" 609 | echo -e "${CCyan}8. Would you like to show near-realtime VPN stats on the UI? ${CYellow}(Default = No)${CClear}" 610 | if promptyn "(Yes/No): "; then 611 | SHOWSTATS=1 612 | else 613 | SHOWSTATS=0 614 | fi 615 | echo "" 616 | logo 617 | echo -e "Configuration of VPNMON-R2 is complete. Would you like to save this config?${CClear}" 618 | if promptyn "(Yes/No): "; then 619 | { echo 'TRIES='$TRIES 620 | echo 'INTERVAL='$INTERVAL 621 | echo 'PINGHOST="'"$PINGHOST"'"' 622 | echo 'UpdateVPNMGR='$UpdateVPNMGR 623 | echo 'UseNordVPN='$UseNordVPN 624 | echo 'NordVPNSuperRandom='$NordVPNSuperRandom 625 | echo 'NordVPNCountry="'"$NordVPNCountry"'"' 626 | echo 'NordVPNLoadReset='$NordVPNLoadReset 627 | echo 'UpdateSkynet='$UpdateSkynet 628 | echo 'ResetOption='$ResetOption 629 | echo 'DailyResetTime="'"$DailyResetTime"'"' 630 | echo 'let N='$N 631 | echo 'SHOWSTATS='$SHOWSTATS 632 | } > $CFGPATH 633 | echo -e "$(date) - VPNMON-R2 - Successfully wrote a new config file" >> $LOGFILE 634 | else 635 | echo "" 636 | echo -e "${CGreen}Discarding changes and exiting setup.${CClear}" 637 | echo "" 638 | kill 0 639 | fi 640 | echo "" 641 | echo -e "${CYellow}Would you like to start VPNMON-R2 now?${CClear}" 642 | if promptyn "(Yes/No): "; then 643 | sh $APPPATH -monitor 644 | else 645 | echo "" 646 | echo -e "${CGreen}Execute VPNMON-R2 using command 'vpnmon-r2.sh -monitor' for normal operations${CClear}" 647 | echo "" 648 | kill 0 649 | fi 650 | else 651 | #Create a new config file with default values to get it to a basic running state 652 | { echo 'TRIES=3' 653 | echo 'INTERVAL=60' 654 | echo 'PINGHOST="8.8.8.8"' 655 | echo 'UpdateVPNMGR=0' 656 | echo 'UseNordVPN=0' 657 | echo 'NordVPNSuperRandom=0' 658 | echo 'NordVPNCountry="United States"' 659 | echo 'NordVPNLoadReset=50' 660 | echo 'UpdateSkynet=0' 661 | echo 'ResetOption=1' 662 | echo 'DailyResetTime="01:00"' 663 | echo 'let N=5' 664 | echo 'SHOWSTATS=0' 665 | } > $CFGPATH 666 | 667 | #Re-run vpnmon-r2 -config to restart setup process 668 | sh $APPPATH -config 669 | fi 670 | fi 671 | 672 | # Check to see if the update option is being called 673 | if [ "$1" == "-update" ] 674 | then 675 | # Check for the latest version from source repository 676 | updatecheck 677 | clear 678 | logo 679 | echo -e "VPNMON-R2 v$Version Update Utility${CClear}" 680 | echo "" 681 | echo -e "${CCyan}Current Version: ${CYellow}$Version${CClear}" 682 | echo -e "${CCyan}Updated Version: ${CYellow}$DLVersion${CClear}" 683 | echo "" 684 | if [ "$Version" == "$DLVersion" ] 685 | then 686 | echo -e "${CGreen}No update available. Exiting Update Utility...${CClear}" 687 | echo "" 688 | kill 0 689 | else 690 | echo -e "${CCyan}Would you like to update to the latest version?${CClear}" 691 | if promptyn "(Yes/No): "; then 692 | echo "" 693 | echo -e "${CCyan}Updating VPNMON-R2 to ${CYellow}v$DLVersion${CClear}" 694 | curl --silent --retry 3 "https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/master/vpnmon-r2-$DLVersion.sh" -o "/jffs/scripts/vpnmon-r2.sh" && chmod a+rx "/jffs/scripts/vpnmon-r2.sh" 695 | echo "" 696 | echo -e "${CCyan}Update successful!${CClear}" 697 | echo -e "$(date) - VPNMON-R2 - Successfully updated VPNMON-R2 from v$Version to v$DLVersion" >> $LOGFILE 698 | else 699 | echo "" 700 | echo -e "${CGreen}Exiting Update Utility...${CClear}" 701 | echo "" 702 | kill 0 703 | fi 704 | echo "" 705 | echo -e "${CYellow}Would you like to start VPNMON-R2 now?${CClear}" 706 | if promptyn "(Yes/No): "; then 707 | sh $APPPATH -monitor 708 | else 709 | echo "" 710 | echo -e "${CGreen}Execute VPNMON-R2 using command 'vpnmon-r2.sh -monitor' for normal operations${CClear}" 711 | echo "" 712 | kill 0 713 | fi 714 | fi 715 | fi 716 | 717 | # Check to see if the monitor option is being called and run operations normally 718 | if [ "$1" == "-monitor" ] 719 | then 720 | clear 721 | if [ -f $CFGPATH ]; then 722 | source $CFGPATH 723 | else 724 | echo -e "${CRed}Error: VPNMON-R2 is not configured. Please run 'vpnmon-r2.sh -config' to complete setup${CClear}" 725 | echo "" 726 | echo -e "$(date) - VPNMON-R2 - *** ERROR: vpnmon-r2.cfg was not found. Please run the configuration tool." >> $LOGFILE 727 | kill 0 728 | fi 729 | fi 730 | 731 | # ------------------------------------------------------------------------------------------------------------------------- 732 | # Begin VPNMON-R2 Main Loop 733 | # ------------------------------------------------------------------------------------------------------------------------- 734 | 735 | #DEBUG=; set -x # uncomment/comment to enable/disable debug mode 736 | #{ # uncomment/comment to enable/disable debug mode 737 | 738 | while true; do 739 | 740 | # Testing to see if a VPN Reset Date/Time Logfile exists or not, and if not, creates one 741 | if [ -f $RSTFILE ] 742 | then 743 | #Read in its contents for the date/time of last reset 744 | START=$(cat $RSTFILE) 745 | else 746 | #Create a new file with a new date/time of when VPNMON-R2 restarted, not sure when VPN last reset 747 | echo -e "$(date +%s)" > $RSTFILE 748 | START=$(cat $RSTFILE) 749 | fi 750 | 751 | # Testing to see if VPNON is currently running, and if so, hold off until it finishes 752 | while test -f "$LOCKFILE"; do 753 | # clear screen 754 | clear && clear 755 | 756 | echo -e "${CRed}VPNON is currently performing a scheduled reset of the VPN. Trying to reconnect every $SPIN seconds...${CClear}\n" 757 | echo -e "$(date +%s)" > $RSTFILE 758 | START=$(cat $RSTFILE) 759 | spinner 760 | 761 | # Reset the VPN IP/Locations 762 | VPNIP="Unassigned" 763 | PINGLOW=0 # Reset ping time history variables 764 | PINGHIGH=0 765 | oldrxbytes=0 # Reset Stats 766 | oldtxbytes=0 767 | newrxbytes=0 768 | newtxbytes=0 769 | done 770 | 771 | # Testing to see if a reset needs to run at the scheduled time, first by pulling our hair out to find a timeslot to 772 | # run this thing, by looking at current time and the scheduled time, converting to epoch seconds, and seeing if it 773 | # falls between scheduled time + 2 * the number of interval seconds, to ensure there's enough of a gap to check for 774 | # this if it happens to be in a sleep loop. 775 | 776 | if [[ $ResetOption -eq 1 ]] 777 | then 778 | currentepoch=$(date +%s) 779 | ConvDailyResetTime=$(date -d $DailyResetTime +%H:%M) 780 | ConvDailyResetTimeEpoch=$(date -d $ConvDailyResetTime +%s) 781 | variance=$(( $ConvDailyResetTimeEpoch + (( $INTERVAL*2 )))) 782 | 783 | # If the configured time is within 2 minutes of the current time, reset the VPN connection 784 | if [[ $currentepoch -gt $ConvDailyResetTimeEpoch && $currentepoch -lt $variance ]] 785 | then 786 | echo -e "\n\n${CCyan}VPNMON-R2 is executing a scheduled VPN Reset${CClear}\n" 787 | echo -e "$(date) - VPNMON-R2 - Executing scheduled VPN Reset" >> $LOGFILE 788 | 789 | vpnreset 790 | 791 | echo -e "\n${CCyan}Resuming VPNMON-R2 in T minus $INTERVAL${CClear}\n" 792 | echo -e "$(date) - VPNMON-R2 - Resuming normal operations" >> $LOGFILE 793 | echo -e "$(date +%s)" > $RSTFILE 794 | START=$(cat $RSTFILE) 795 | 796 | # Provide a progressbar to show script activity 797 | i=0 798 | while [[ $i -le $INTERVAL ]] 799 | do 800 | preparebar 51 "|" 801 | progressbar $i $INTERVAL 802 | sleep 1 803 | i=$(($i+1)) 804 | done 805 | 806 | PINGLOW=0 # Reset ping time history variables 807 | PINGHIGH=0 808 | oldrxbytes=0 # Reset Stats 809 | oldtxbytes=0 810 | newrxbytes=0 811 | newtxbytes=0 812 | fi 813 | fi 814 | 815 | # Calculate days, hours, minutes and seconds between VPN resets 816 | END=$(date +%s) 817 | SDIFF=$((END-START)) 818 | LASTVPNRESET=$(printf '%dd %02dh:%02dm:%02ds\n' $(($SDIFF/86400)) $(($SDIFF%86400/3600)) $(($SDIFF%3600/60)) $(($SDIFF%60))) 819 | 820 | # clear screen 821 | clear && clear 822 | #printf "\033c" 823 | 824 | # Display title/version 825 | echo -e "${CYellow} _ ______ _ ____ _______ _ __ ____ ___ " 826 | echo -e " | | / / __ \/ | / / |/ / __ \/ | / / / __ \__ \ " 827 | echo -e " | | / / /_/ / |/ / /|_/ / / / / |/ /_____/ /_/ /_/ / " 828 | echo -e " | |/ / ____/ /| / / / / /_/ / /| /_____/ _, _/ __/ " 829 | echo -e " |___/_/ /_/ |_/_/ /_/\____/_/ |_/ /_/ |_/____/ ${CGreen}v$Version${CClear}" 830 | 831 | # Display update notification if an update becomes available through source repository 832 | 833 | if [[ "$UpdateNotify" != "0" ]]; then 834 | echo -e "${CRed} $UpdateNotify${CClear}" 835 | echo "" 836 | else 837 | echo "" 838 | fi 839 | 840 | # Show the date and time 841 | echo -e "${CYellow}$(date) -------- Last Reset: ${InvBlue}$LASTVPNRESET${CClear}" 842 | 843 | # Determine if a VPN Client is active, first by getting the VPN state from NVRAM 844 | state1=$(nvram get vpn_client1_state) 845 | state2=$(nvram get vpn_client2_state) 846 | state3=$(nvram get vpn_client3_state) 847 | state4=$(nvram get vpn_client4_state) 848 | state5=$(nvram get vpn_client5_state) 849 | 850 | # Display the VPN states along with scheduled reset time/interval seconds 851 | if [[ $ResetOption -eq 1 ]] 852 | then 853 | echo -e "${CCyan}VPN State 1:$state1 2:$state2 3:$state3 4:$state4 5:$state5${CClear}${CYellow} ------ Sched Reset: ${InvBlue}$ConvDailyResetTime${CClear}${CYellow} / ${InvBlue}$INTERVAL Sec${CClear}" 854 | else 855 | echo -e "${CCyan}VPN State 1:$state1 2:$state2 3:$state3 4:$state4 5:$state5${CClear}${CYellow} --------- Interval: ${InvBlue}$INTERVAL Sec${CClear}" 856 | fi 857 | 858 | echo -e "${CGreen}-----------------------------------------------------------------${CClear}" 859 | 860 | # Cycle through the CheckVPN connection function for N number of VPN Clients 861 | i=0 862 | while [[ $i -ne $N ]] 863 | do 864 | i=$(($i+1)) 865 | checkvpn $i $((state$i)) 866 | done 867 | 868 | echo -e "${CGreen}-----------------------------------------------------------------${CClear}" 869 | 870 | # Determine whether to show all the stats based on user preference 871 | if [[ $SHOWSTATS == "1" ]] 872 | then 873 | 874 | # Keep track of Ping history stats and display skynet and randomizer methodology 875 | if [[ ${PINGLOW%.*} -eq 0 ]] 876 | then 877 | PINGLOW=${AVGPING%.*} 878 | elif [[ ${AVGPING%.*} -lt ${PINGLOW%.*} ]] 879 | then 880 | PINGLOW=${AVGPING%.*} 881 | fi 882 | 883 | if [[ ${PINGHIGH%.*} -eq 0 ]] 884 | then 885 | PINGHIGH=${AVGPING%.*} 886 | elif [[ ${AVGPING%.*} -gt ${PINGHIGH%.*} ]] 887 | then 888 | PINGHIGH=${AVGPING%.*} 889 | fi 890 | 891 | if [[ $UpdateVPNMGR -eq 1 ]] 892 | then 893 | RANDOMMETHOD="VPNMGR" 894 | elif [[ $NordVPNSuperRandom -eq 1 ]] 895 | then 896 | RANDOMMETHOD="NordVPN SuperRandom" 897 | else 898 | RANDOMMETHOD="Standard" 899 | fi 900 | 901 | if [[ $NordVPNSuperRandom -eq 1 ]] || [[ $UseNordVPN -eq 1 ]] 902 | then 903 | # Get the NordVPN server load - thanks to @JackYaz for letting me borrow his code from VPNMGR to accomplish this! ;) 904 | printf "${CYellow}\r[Checking NordVPN Server Load]..." 905 | VPNLOAD=$(curl --silent --retry 3 "https://api.nordvpn.com/v1/servers?limit=16354" | jq '.[] | select(.station == "'"$VPNIP"'") | .load') 906 | printf "\r" 907 | fi 908 | 909 | if [ -z "$VPNLOAD" ]; then VPNLOAD=0; fi # On that rare occasion where it's unable to get the NordVPN load, assign 0 910 | 911 | # Display some of the NordVPN-specific stats 912 | if [[ $NordVPNSuperRandom -eq 1 ]] || [[ $UseNordVPN -eq 1 ]] 913 | then 914 | echo -e "${CYellow}Ping Lo:${CWhite}${InvGreen}$PINGLOW${CClear}${CYellow} Hi:${CWhite}${InvRed}$PINGHIGH${CClear}${CYellow} ms | Load: ${InvBlue} $VPNLOAD % ${CClear}${CYellow} | Config: ${InvBlue}$RANDOMMETHOD${CClear}" 915 | 916 | # Display the high/low ping times, and for non-NordVPN customers, whether Skynet update is enabled. 917 | elif [[ $UpdateSkynet -eq 0 ]] 918 | then 919 | echo -e "${CYellow}Ping Lo:${CWhite}${InvGreen}$PINGLOW${CClear}${CYellow} Hi:${CWhite}${InvRed}$PINGHIGH${CClear}${CYellow} ms | Config: ${InvBlue}$RANDOMMETHOD${CClear}" 920 | else 921 | echo -e "${CYellow}Ping Lo:${CWhite}${InvGreen}$PINGLOW${CClear}${CYellow} Hi:${CWhite}${InvRed}$PINGHIGH${CClear}${CYellow} ms | Skynet: ${InvBlue}[Y]${CClear}${CYellow} | Config: ${InvBlue}$RANDOMMETHOD${CClear}" 922 | fi 923 | 924 | # Grab total bytes VPN Traffic Measurement 925 | txrxbytes=$(awk -F',' '1 == /TUN\/TAP read bytes/ {print $2} 1 == /TUN\/TAP write bytes/ {print $2}' /tmp/etc/openvpn/client$CURRCLNT/status 2>/dev/null) 926 | rxbytes="$(echo $txrxbytes | cut -d' ' -f1)" 927 | txbytes="$(echo $txrxbytes | cut -d' ' -f2)" 928 | 929 | # Assign the latest RX and TX bytes to the new counter 930 | newrxbytes=$rxbytes 931 | newtxbytes=$txbytes 932 | 933 | # Calculations to find the difference between old and new total bytes send/received and divided to give Megabits 934 | diffrxbytes=$(awk -v new=$newrxbytes -v old=$oldrxbytes -v mb=125000 'BEGIN{printf "%.4f\n", (new-old)/mb}') 935 | difftxbytes=$(awk -v new=$newtxbytes -v old=$oldtxbytes -v mb=125000 'BEGIN{printf "%.4f\n", (new-old)/mb}') 936 | 937 | # Results are further divided by the timer/interval to give Megabits/sec 938 | rxmbrate=$(awk -v rb=$diffrxbytes -v intv=$INTERVAL 'BEGIN{printf "%0.2f\n", rb/intv}') 939 | txmbrate=$(awk -v tb=$difftxbytes -v intv=$INTERVAL 'BEGIN{printf "%0.2f\n", tb/intv}') 940 | 941 | # Total bytes sent/received are divided to give total TX/RX Gigabytes 942 | rxgbytes=$(awk -v rx=$rxbytes -v gb=1073741824 'BEGIN{printf "%0.2f\n", rx/gb}') 943 | txgbytes=$(awk -v tx=$txbytes -v gb=1073741824 'BEGIN{printf "%0.2f\n", tx/gb}') 944 | 945 | # If stats are just fresh due to a start or reset, then wait until stats are there to display 946 | # NOTE: after extensive testing, it seems that the RX and TX values are reversed in the OpenVPN status file, so I am reversing these below 947 | # NOTE2: This is by design... not a clumsy coding mistake! :) 948 | 949 | if [[ "$oldrxbytes" == "0" ]] || [[ "$oldtxbytes" == "0" ]] 950 | then 951 | # Still gathering stats 952 | echo -e "${CYellow}[Gathering VPN RX and TX Stats]... | Ttl RX:${InvBlue}$txgbytes GB${CClear} ${CYellow}TX:${InvBlue}$rxgbytes GB${CClear}" 953 | else 954 | # Display current avg rx/tx rates and total rx/tx bytes for active VPN tunnel. 955 | echo -e "${CYellow}Avg RX:${InvBlue}$txmbrate Mbps${CClear}${CYellow} TX:${InvBlue}$rxmbrate Mbps${CClear}${CYellow} | Ttl RX:${InvBlue}$txgbytes GB${CClear} ${CYellow}TX:${InvBlue}$rxgbytes GB${CClear}" 956 | fi 957 | 958 | echo -e "${CGreen}-----------------------------------------------------------------${CClear}" 959 | 960 | #VPN Traffic Measurement assignment of newest bytes to old counter before timer kicks off again 961 | oldrxbytes=$newrxbytes 962 | oldtxbytes=$newtxbytes 963 | 964 | fi 965 | 966 | # ------------------------------------------------------------------------------------------------------------------------- 967 | # Check for 3 major reset scenarios - (1) Lost connection, (2) Multiple connections, or (3) High VPN Server Load, and reset 968 | # ------------------------------------------------------------------------------------------------------------------------- 969 | 970 | # If STATUS remains 0 then reset the VPN 971 | if [[ $STATUS -eq 0 ]]; then 972 | echo -e "\n${CRed}Connection has failed, VPNMON-R2 is executing VPN Reset${CClear}\n" 973 | echo -e "$(date) - VPNMON-R2 - **Connection failed** - Executing VPN Reset" >> $LOGFILE 974 | 975 | vpnreset 976 | 977 | echo -e "\n${CCyan}Resuming VPNMON-R2 in T minus $INTERVAL${CClear}\n" 978 | echo -e "$(date) - VPNMON-R2 - Resuming normal operations" >> $LOGFILE 979 | echo -e "$(date +%s)" > $RSTFILE 980 | START=$(cat $RSTFILE) 981 | PINGLOW=0 # Reset ping time history variables 982 | PINGHIGH=0 983 | oldrxbytes=0 # Reset Stats 984 | oldtxbytes=0 985 | newrxbytes=0 986 | newtxbytes=0 987 | fi 988 | 989 | # If VPNCLCNT is greater than 1 there are multiple connections running, reset the VPN 990 | if [[ $VPNCLCNT -gt 1 ]]; then 991 | echo -e "\n${CRed}Multiple VPN Client Connections detected, VPNMON-R2 is executing VPN Reset${CClear}\n" 992 | echo -e "$(date) - VPNMON-R2 - **Multiple VPN Client Connections detected** - Executing VPN Reset" >> $LOGFILE 993 | 994 | vpnreset 995 | 996 | echo -e "\n${CCyan}Resuming VPNMON-R2 in T minus $INTERVAL ${CClear}\n" 997 | echo -e "$(date) - VPNMON-R2 - Resuming normal operations" >> $LOGFILE 998 | echo -e "$(date +%s)" > $RSTFILE 999 | START=$(cat $RSTFILE) 1000 | PINGLOW=0 # Reset ping time history variables 1001 | PINGHIGH=0 1002 | oldrxbytes=0 # Reset Stats 1003 | oldtxbytes=0 1004 | newrxbytes=0 1005 | newtxbytes=0 1006 | fi 1007 | 1008 | # If the NordVPN Server load is greater than the set variable, reset the VPN and hopefully find a better server 1009 | if [[ $NordVPNLoadReset -le $VPNLOAD ]]; then 1010 | echo -e "\n${CRed}NordVPN Server Load is higher than $NordVPNLoadReset %, VPNMON-R2 is executing VPN Reset${CClear}\n" 1011 | echo -e "$(date) - VPNMON-R2 - **NordVPN Server Load is higher than $NordVPNLoadReset %** - Executing VPN Reset" >> $LOGFILE 1012 | 1013 | vpnreset 1014 | 1015 | echo -e "\n${CCyan}Resuming VPNMON-R2 in T minus $INTERVAL ${CClear}\n" 1016 | echo -e "$(date) - VPNMON-R2 - Resuming normal operations" >> $LOGFILE 1017 | echo -e "$(date +%s)" > $RSTFILE 1018 | START=$(cat $RSTFILE) 1019 | PINGLOW=0 # Reset ping time history variables 1020 | PINGHIGH=0 1021 | oldrxbytes=0 # Reset Stats 1022 | oldtxbytes=0 1023 | newrxbytes=0 1024 | newtxbytes=0 1025 | fi 1026 | 1027 | # Provide a progressbar to show script activity 1028 | i=0 1029 | while [[ $i -le $INTERVAL ]] 1030 | do 1031 | preparebar 51 "|" 1032 | progressbar $i $INTERVAL 1033 | sleep 1 1034 | i=$(($i+1)) 1035 | done 1036 | 1037 | #VPN Traffic Measurement after timer 1038 | txrxbytes=$(awk -v var3="$rxbytes" -v var4="$txbytes" -F',' '1 == /TUN\/TAP read bytes/ {print $2} 1 == /TUN\/TAP write bytes/ {print $2}' /tmp/etc/openvpn/client$CURRCLNT/status 2>/dev/null) 1039 | rxbytes="$(echo $txrxbytes | cut -d' ' -f1)" 1040 | txbytes="$(echo $txrxbytes | cut -d' ' -f2)" 1041 | newrxbytes=$rxbytes 1042 | newtxbytes=$txbytes 1043 | 1044 | #read -rsp $'Press any key to continue...\n' -n1 key 1045 | 1046 | #Reset Variables 1047 | STATUS=0 1048 | VPNCLCNT=0 1049 | CNT=0 1050 | AVGPING=0 1051 | state1=0 1052 | state2=0 1053 | state3=0 1054 | state4=0 1055 | state5=0 1056 | 1057 | done 1058 | 1059 | exit 0 1060 | 1061 | #} #2>&1 | tee $LOG | logger -t $(basename $0)[$$] # uncomment/comment to enable/disable debug mode 1062 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | v2.65 - (January 27, 2024) 2 | - FIXED: Minor change for AMTM compliance purposes. :) 3 | 4 | v2.64 - (January 25, 2024) 5 | - MAJOR: I have made the difficult decision to sunset VPNMON-R2. After this version 6 | is made live, you will be prompted to consider upgrading to VPNMON-R3 when the 7 | script starts up. From the Setup Menu, you will see indicators that an in-place 8 | upgrade to R3 is available. The upgrade allows you to install VPNMON-R3 and keep 9 | VPNMON-R2 in place, or, you can install VPNMON-R3, and uninstall VPNMON-R2. You can 10 | continue running R2 as long as you want, but development/support will be shutting 11 | down in favor of R3. The R2 script will be removed from AMTM and replaced with R3. 12 | As of this version, new installs of VPNMON-R2 v2.64 won't be possible, and will 13 | recommend installation of VPNMON-R3. Thank you for all your support and encouragement 14 | throughout R2's run. It has been a wild ride! I hope R3 serves your needs and exceeds 15 | your expectations! 16 | - FIXED: Thanks to @salvo for identifying that the post-mount entry was not getting 17 | deleted after a VPNMON-R2 uninstall. Fixed! 18 | 19 | v2.63 - (November 4, 2023) 20 | - FIXED: Thanks to @TITAN and @Ripshod for reporting back about unknown operand errors 21 | visible on the display when multiple VPN slots were not being used. This was due to 22 | some erroneous code that was not taking into consideration that some of these values 23 | may have been null. Much appreciation for @Martinski and @Somewhereovertherainbow for 24 | their help and advice on creating a more optimized way of catching this! 25 | 26 | v2.62 - (October 2, 2023) 27 | - ADDED: Thanks to @salvo for suggesting a different approach at displaying and measuring 28 | the pings for the current VPN slot and the disconnected slots. I used this same logic 29 | any time a ping measurement is done (which is now pinging 3x and getting the average), 30 | which should make these values a little more accurate. Please note, the connected VPN 31 | slot continues to measure a ping across the tunnel. The disconnected slots measure a 32 | ping across the WAN to the specified VPN server. As expected, this method does delay 33 | the screen draw of the values across the screen, but annoyance is minimal in favor of 34 | more accuracy. ;) 35 | - FIXED: Added some more context in the logs when WAN0 and WAN1 receive a new city name. 36 | - FIXED: Checking for VPN slot error states (-1), and if any return with this value, then 37 | set them back to zero to avoid any on-screen errors. 38 | 39 | v2.59 - (June 24, 2023) 40 | - FIXED: Couple of items relating to ensuring Unbound resolver DNS IP would be correctly 41 | reflected on screen if any of the other VPN reset events were triggered. This could at 42 | times cause a reset looping issue. 43 | - FIXED: Optimizations and bugfixes 44 | 45 | v2.58 - (May 24, 2023) 46 | - ADDED: Building on the Unbound functionality, I've implemented another reset condition, in 47 | particular, if the Unbound public DNS Resolver IP is not the same at your public VPN IP. 48 | Thanks so much to @Somewhereovertherainbow for his amazing regex and awk skills to pull this 49 | query off with a dig command. You will now find a new item under the config menu to enable 50 | this feature, on page 2, item 18, and will ask if you want to enable an Unbound out-of-sync 51 | reset. In rare conditions (typically for anything messing with your iptables like skynet 52 | version updates, and whatnot, your Unbound public IP DNS Resolver may revert to your public 53 | WAN IP. This reset will force it to send its encrypted DNS traffic back over the VPN tunnel 54 | if it happens to go out-of-sync. If you are OK with your DNS Resolver IP being different than 55 | your Public VPN IP, simply don't enable this. 56 | - FIXED: Thanks to @Somewhereovertherainbow, he uncovered a more stable, preferred method to 57 | run CURL statements. This version of VPNMON-R2 has had all CURL statements modified per these 58 | suggestions! Thank you! 59 | - FIXED: Optimizations and bugfixes 60 | 61 | v2.55 - (May 14, 2023) 62 | - MAJOR: Added major functionality to integrate more closely with Unbound! Unbound allows you 63 | to become your own DNS resolver, so you don't have to rely on other DNS providers (like from 64 | your ISP, Google, Quad9, etc.), and helps somewhat with privacy - because who knows what they 65 | log on their end, right? ;) The downside with Unbound is that the traffic you generate for 66 | your own DNS lookups to root servers or other authoritative servers is not encrypted... which 67 | would allow your ISP (or others) to still snoop on your plaintext port 53 DNS queries. So 68 | here's the good news -- this Unbound modification (thanks to @Martineau/Swinson) forces all 69 | plaintext port 53 traffic that Unbound generates for DNS lookups over your VPN tunnel instead! 70 | This means your internet activity is even more secure from your ISP (or others) prying eyes. 71 | Please note, this is not an end-all-be-all fix to keep all DNS lookups private, but it 72 | certainly helps get you closer. This update will now require that Unbound is installed and 73 | running, and will download and/or apply other scripts to the following files: 74 | /jffs/scripts/nat-start 75 | /jffs/scripts/openvpn-event 76 | /jffs/scripts/post-mount 77 | /jffs/addons/unbound/unbound_DNS_via_OVPN.sh 78 | - NOTE: VPNMON-R2 does not play any role in manipulating Unbound or the associated scripts in 79 | any way... it continues to function as it normally does. Except now, as openvpn events fire 80 | off as VPN tunnels are disconnected or established, this will allow these scripts to work in 81 | harmony with each other to force Unbound traffic over the VPN tunnel. Playing with these 82 | scripts and modifications isn't for the feint of heart, and may take some serious 83 | troubleshooting skills to get it configured right if something doesn't work straight out of 84 | the gate. 85 | - ADDED: Per one of @Martineau's old suggestions in the threads, when enabling this feature in 86 | the configuration menu, I've also added a command in the POST-MOUNT file that will disable 87 | Unbounds's VPN binding upon a router reboot as a fail-safe so that DNS resolutions aren't 88 | impacted as they would still be trying to get out over a VPN tunnel that is no longer in 89 | existence. 90 | 91 | v2.53 - (April 25, 2023) 92 | - FIXED: Syntax fix that might have been causing a "bad number" bug when using the Lowest Ping 93 | setting with 1 or more VPN slots. Thanks to @alisou for the find! 94 | 95 | v2.52 - (March 27, 2023) 96 | - FIXED: Apparently the code that parsed the client slot description field wasn't as solid as 97 | I had hoped for, and thanks to @kuki68ster, was able to identify this issue. I have rolled 98 | back some of the functionality of pulling hostnames from description fields for those who are 99 | using custom entries in the description field. This should hopefully fully restore the 100 | ability to get load indications for NordVPN again. 101 | 102 | v2.51 - (March 26, 2023) 103 | - FIXED: Added some backwards capability back in for those who are manually setting their VPN 104 | slots, and not utilizing the new method that VPNMON-R2 uses in the VPN slot description field 105 | to read part of the NordVPN server hostname in order to do load checks. This will also 106 | hopefully add more backward compatibility for VPNMGR as well, since I believe it sets its own 107 | description field info for its own purposes. 108 | 109 | v2.50 - (March 26, 2023) 110 | - FIXED: Fixed a recommended servers variable tracking issue in part due to the introduction of 111 | AirVPN's similar feature, and getting it to co-exist with NordVPN. Thanks to @kuki68ster for 112 | flagging this! 113 | 114 | v2.49 - (March 26, 2023) 115 | - FIXED: Fixed a terminated quoted string error where I forgot to close a sting for one of the 116 | new options that writes itself to the config file. Thanks Gesa! 117 | 118 | v2.48 - (March 25, 2023) 119 | - MAJOR: We added another major VPN Provider -- AirVPN -- to the mix of compatible VPN services 120 | that play well with APIs, giving us the ability to use these for SuperRandom(r) functionality 121 | in the country (or countries) of your choice. Also, provides us with the ability to use the 122 | AirVPN Recommended Servers feature, for those who want their servers to stay closer or more 123 | optimized for speed. AirVPN gives us the same range of capabilities that NordVPN gives, 124 | including reporting on the current server Load, or resetting the connection if the load 125 | exceeds your specified amount... Also, the ability to whitelist your AirVPN servers in Skynet 126 | so they don't get blocked (as they so frequently do).... so, really happy to get this one 127 | added. Note: This assumes you have all (up to) 5 VPN slots configured and working with AirVPN 128 | config, using OpenVPN, TLS authentication & encryption - which is pretty much the standard 129 | out there. Thanks to @machinist for the ask! 130 | - MAJOR: Added the capability to reset your VPN connection or reboot your router using an 131 | external file! I find myself in a pickle at times, unable to access my devices on a subnet, 132 | and unable to control my router from remote due to a misconfiguration or because the VPN 133 | tunnel got borked up, preventing all our devices from getting out to the internet. I wanted 134 | to (selfishly) find a way to externally cause the router to reset its VPN connection, and in 135 | a worst-case scenario, reboot the router! Well, that is all now possible. Simply host a file 136 | off an internet accessible server, having one of the words "RESET", "REBOOT" or "NORMAL" on 137 | the first line of the file. With options on the 2nd page in the config, you can specify if 138 | you want to enable this feature, what the full URL path to this file is (example: 139 | https://raw.githubusercontent.com/ViktorJp/VPNMON-R2/main/event.txt), and what kind of 140 | interval you want to use to check on this file. The next time VPNMON-R2 checks the file, it 141 | will act on one of these commands! I've added an indicator to the top of the UI if this 142 | feature is enabled, showing the interval seconds as well. 143 | - MAJOR: Added the capability for VPNMON-R2 to auto-start after a reboot. By popular demand, I'm 144 | not sure how many times this was asked, so it's finally in there! Config menu item #16 will 145 | ask if you want VPNMON-R2 to auto-start. It inserts the command 'vpnmon-r2.sh -screen' into 146 | your /jffs/scripts/post-mount file. An indicator at the top of the UI shows if this feature 147 | is enabled, and intact in your post-mount file. If for some reason it's different than what 148 | was originally added, it will indicate that there's an issue. 149 | - ADDED: A second page of config options! Currently with 14 options, the list is getting too 150 | large, and expanded it out onto a second page for future growth! 151 | - FIXED: Made some modifications to the NordVPN API calls in order to hopefully provide a 152 | faster response for those dealing with bandwidth or other possible throttling limitations in 153 | other countries, like Turkey. Thanks to @iTyPsIDg for helping troubleshoot while out there! 154 | - FIXED: Minor code improvements and optimizations. 155 | 156 | v2.41 - (January 22, 2023) 157 | - ADDED: Some logic was added to check for parameters within the killmon.cfg to determine 158 | whether or not to suppress the KILLMON header on the main UI along with the associated 159 | logging that happens. If you have KILLMON installed but not running or enabled, VPNMON-R2 160 | would display warnings that KILLMON is disabled and that rule integrity is compromised. 161 | You can now suppress these warnings from within the KILLMON UI v1.04. 162 | 163 | v2.40 - (December 24, 2022) 164 | - MAJOR: Integration with KILLMON, the new IP4/IP6 Kill Switch Monitor and Configurator! If 165 | KILLMON is installed, it will show the current status on the main VPNMON-R2 UI, indicating 166 | its current IP4/IP6 running status, reboot protection and whether it's kill mode is using 167 | (1) Paranoid, (2) IP Range or (3) Single IP scenarios. Also, it will check against the 168 | IP4/IP6 iptables to check for KILLMON rules integrity, and will warn you if rules are in a 169 | compromised state. If KILLMON is not installed, it will not show any such killswitch 170 | indicators in the UI. 171 | - ADDED: Created an additional switch called "-failover" for the purposes of providing some 172 | more automation for those who need control over VPNMON-R2 during dual-wan failover events, 173 | should you need it. I was originally going to remove this functionality after a failed 174 | attempt at integrating it with @Ranger802004's dual-wan failover script, but ended up 175 | deciding to just keep this functionality around incase it's needed in the future. This 176 | function, when called (ie. "vpnmon-r2 -failover"), will stop all VPN connections, and wait 177 | in a loop until another "-failover" command is sent its way (in other words, a manual 178 | fail-over and fail-back switch), upon which it will try to reconnect its last known good 179 | VPN connection. Thanks to both @Stephen Harrington and @Ranger802004 for their beta testing, 180 | troubleshooting and efforts on this! 181 | 182 | v2.36 - (October 29, 2022) 183 | - CHANGED: Added some functionality to the -stop command, that when it is resumed, it will 184 | attempt to connect to the last known good VPN slot. 185 | - FIXED: Omitted to include an event when VPNMON-R2 goes into a loop during the WAN1 VPN 186 | exception, and will now write that VPNMON-R2 is in a "STOPPED" state. Thanks for the report, 187 | @Stephen Harrington 188 | 189 | v2.35 - (October 21, 2022) 190 | - ADDED: Another commandline parameter "vpnmon-r2 -stop", based on a suggestion from our own 191 | @Stephen Harrington! This parameter, much like -pause, will cause VPNMON-R2 to retreat to a 192 | loop waiting for a -resume command. The difference here is that unlike with -pause, the -stop 193 | command will kill all VPN connections, and will re-establish the VPN once resumed. 194 | - ADDED: Another -config menu item #14 - "Allow WAN1 VPN Connections?". This item determines if 195 | you want to allow VPN connections across your WAN1 connection in Dual-WAN situations where you 196 | have failed over from your primary WAN connection. In the case of WAN1 connections, these are 197 | typically USB devices with limited bandwidth and cost, thus trying to limit the amount of 198 | traffic going over these devices. If this option is set, and WAN fails over to WAN1, VPNMON-R2 199 | will kill all VPN connetions, loop and wait for WAN0 to become active again before connecting 200 | back to your VPN provider. Thanks to @Stephen Harrington for the great suggestion! 201 | - CHANGED: Some of the feedback you receive when VPN resets, to include more granular information 202 | about VPN slots or PING values on screen and in the logs. Thanks to @salvo for noting this! 203 | - CHANGED: Fixed some of the text indents across the board to give it a more uniform look/feel. 204 | - FIXED: There was a sleep variable incorrectly misnamed (as "Sleep"), and corrected this in order 205 | to prevent any possible "Sleep: Not Found" errors that may pop up as a result. Thanks to @TITAN 206 | for finding this mistake! 207 | 208 | v2.32 - (October 18, 2022) 209 | - HOTFIX2: I have backed out this code to determine concurrent sessions for further testing in the 210 | next round of betas. v2.32 is the new stable version. 211 | 212 | v2.31 - (October 18, 2022) 213 | - HOTFIX: The logic to determine whether or not a secondary vpnmon-r2 session was already running 214 | after executing a concurrent -monitor command wasn't working out correctly. This was fixed. 215 | Thanks much to @Stephen Harrington for his keen eye on this! 216 | 217 | v2.30 - (October 18, 2022) 218 | - MAJOR: Another method of picking VPN slots has been introduced to the mix, namely, the "Round 219 | Robin" method. Instead of randomly picking slots, VPNMON-R2 will pick the next VPN slot in line. 220 | Ex: If you are using VPN Slot #1 and it fails, it will connect to VPN Slot #2, then 3, etc. 221 | VPNMON-R2 will keep track of the slot last used, and will survive a reboot, so that it will 222 | correctly pick that next slot in line. Under setup->config, please choose option 5 - how you want 223 | your VPN slots chosen, select "Round Robin". Thanks @ComputerSteve for asking to include this! 224 | - ADDED: Now includes logic to PAUSE, RESUME and inquire about a current STATUS of VPNMON-R2. With 225 | thanks to @ComputerSteve for the suggestion. When running the command "vpnmon-r2 -pause", the 226 | currently running instance of VPNMON-R2 will enter a "paused" state. While in this paused state, 227 | it will not check for any VPN anomalies until it is resumed once again. Entering the command 228 | "vpnmon-r2 -resume" will allow the currently running instance to resume normal operations. Last, 229 | using the "vpnmon-r2 -status" command gives an indication what state VPNMON-R2 is currently 230 | operating in, along with the last known VPN slot being used. 231 | - ADDED: Another stats row, containing information regarding the VPN Slot Selection Method, the 232 | number of chances it gets (in case it's set for the Lowest PING method), the number of PING 233 | retries before reset, and the minimum PING allowable across the VPN tunnel before a reset. 234 | - ADDED: A check when executing 'vpnmon-r2 -monitor' to display a warning message if an existing 235 | session running vpnmon-r2 is already running under the Screen utility. Please know, that running 236 | the -monitor command will not prevent you from running 2 instances of vpnmon-r2 at the same time, 237 | but it will warn you that conflict can very likely occur. 238 | - CHANGED: When bringing up the setup/config menu from within the UI, the UI will now refresh and 239 | use the changes that were made to the config. This prevents you from having to stop and restart 240 | the script to accept changes. Been needing to do this for a while, so thanks again to 241 | @ComputerSteve for lighting a fire under my butt. ;) 242 | - CHANGED: Increased the timeout value for netcat when doing a WAN check from 1s to 3s. This should 243 | help alleviate instances of false WAN-down detection during times of high bandwidth utilization. 244 | Thanks to @salvo for reporting this! 245 | - FIXED: Added a few more references for the VPN status file to be written to during other types of 246 | vpnreset events so the status file reflects accurately throughout. 247 | - FIXED: Minor code improvements and optimizations. Eliminated some inefficient code from v0.1 that 248 | has been nagging my OCD for quite a while. 249 | 250 | v2.26 - (October 10, 2022) 251 | - CHANGED: Added some additional layers of error checking and logic pertaining to VPN provider API 252 | calls to help eliminate any errors from showing on the screen when connectivity might possibly be 253 | interfering with results being returned, resulting in parse error messages from CURL and JQ being 254 | displayed on screen. This behavior was particularly evident in Dual WAN failover situations. HUGE 255 | thanks to @Stephen Harrington for his patience and willingness to help test VPNMON-R2 during these 256 | failovers! You have helped make this script better and better over time, much thanks to you! :) 257 | - FIXED: Minor fixes to the VPN reset functionality to ensure it bypasses the interval timer after 258 | a reset. 259 | - FIXED: Also, revamped the function that kills VPN slots, ensuring it only kills the slots that 260 | are allocated to VPNMON-R2, should you be running other VPN connections on other slots. 261 | - FIXED: the -wipe SCREEN command is now being checked earlier before the script determines how 262 | it is going to initiate a SCREEN session. 263 | 264 | v2.24 - (September 30, 2022) 265 | - ADDED: Included new "Recommended Server" functionality for NordVPN users! As with the PC/Mobile 266 | app, when hitting the "Quick Connect" button, you are taken to the nearest, most fastest servers 267 | to your location. This functionality has now been built into VPNMON-R2, allowing you to fill your 268 | 1-N VPN slots with a selection of the closest/fastest NordVPN end points. Thanks to @monakh for 269 | the great suggestion! Make sure you go into the config menu -> option #6 -> when selecting NordVPN 270 | you will have the option to choose this functionality as long as you do not enable "SuperRandom", 271 | as it operates completely opposite from using NordVPN's recommended servers function. NOTE: 272 | Recommended servers are chosen from the country you have specified as your home country under the 273 | config options. 274 | - CHANGED: Included JQ as part of the prerequisites needed to be installed when VPNMON-R2 is set up 275 | for the first time. This was my error, thinking that the JQ tool was either already installed by 276 | default, or came along with an Entware install by default. Now, when going into Setup -> Config, 277 | the script will check for the existence of JQ, and will prompt an install if it's not already 278 | present under /opt/bin. JQ is necessary for pulling data from the various supported VPN Providers 279 | in order to populate VPN host lists for the country you have configured. Added a check when the 280 | script starts up to ensure that all prerequisites are in place before running the script. Thanks 281 | to @monakh for noticing this behavior with JQ on a fresh install of VPNMON-R2! 282 | - CHANGED: The behavior of the (R)eset button no longer waits to initiate a reset until the timer 283 | runs out, and begins the reset function process immediately. Same goes going to/from the (S)etup 284 | menu, and is now exiting directly back into the main VPNMON-R2 UI loop without waiting. 285 | - CHANGED: Revamped the reset conditions screens, which now display on a cleared page, instead of 286 | appending the reset output to the main UI. 287 | - CHANGED: Joined the reset condition checks together into their own function in order to allow 288 | the (R)eset command to work instantaneously, instead of waiting for a cycle to finish. 289 | - FIXED: I "may" have repaired the elusive unbound operand error that would occasionally appear 290 | on the main UI. 291 | 292 | v2.22 - (September 21, 2022) 293 | - CHANGED: The behavior of the "vpnmon-r2 -screen" command, so that when you execute this commandline 294 | parameter, it first will look for orphaned screens and wipe them... then, it will launch VPNMON-R2 295 | into a new screen environment, and connect to it. This skips the original behavior where it drops 296 | back to a command prompt, and asks the user to connect to the VPNMON-R2 screen by requiring the 297 | user to run the "screen -r vpnmon-r2" command. If a screen session is already running, and you type 298 | "vpnmon-r2 -screen", it will then connect to this screen session without requiring any user input. 299 | Thanks much to @TITAN for the great suggestion! 300 | 301 | v2.21 - (September 10, 2022) 302 | - CHANGED: Replaced the API provider that translates IP to citynames from ipapi.co to ip-api.com, which 303 | seems to much more reliable. I have been encountering issues where the ipapi.co service seemed to be 304 | overloaded or blocked at many times, requiring VPNMON-R2 to have to resort to displaying a plain IP. 305 | The new API from ip-api.com allows for unlimited usage, as long as you stay below 45 requests per 306 | minute, which I *think* we can handle! LOL. Needless to say, they've been around since 2012, and seem 307 | to have nice infrastructure around the world. Think we'll stay with this for the time being! 308 | - CHANGED: Fixed the way that VPNMON-R2 checks for a lockfile should you run the script with the -reset 309 | switch either manually or through a cron job. It is now hyper-aware of this lockfile, and checks for 310 | this lockfile throughout the script, as well as during the timer interval. 311 | - FIXED: Minor code optimizations and tweaks 312 | 313 | v2.20 - (August 24, 2022) 314 | - MAJOR: VPNMON-R2 now officially supports WeVPN, including SuperRandom(r) and Multi-Country SuperRandom(r) 315 | functionality. Please note: WeVPN does not provide server loads (yet), and will incorporate that when it 316 | becomes available. Also, they don't provide straight IP addresses for their VPN hosts, which makes it 317 | more difficult to make it compatible with Skynet, so these two options are grayed out. 318 | - CHANGED: Changed the logic that kills VPN client slots to only kill the number of VPN clients you have 319 | configured for VPNMON-R2's purposes, and leaves all others alone in case you are using them for other 320 | purposes. Thanks to @IKNOWNOTHING for this great suggestion! 321 | - FIXED: Minor code optimizations and tweaks 322 | 323 | v2.15 - (August 15, 2022) 324 | - CHANGED: The order of operations for checkwan, and now occurs directly after the interface tab is drawn. 325 | It makes sense to perform this operation here, before the WAN0/1 checks are done, in a more optimized 326 | fashion. Also, changed the look/feel of the checkwan/load check notifications to fall more in line with 327 | the rest of the theme. 328 | - CHANGED: In a dual-WAN scenario, the high ping rule will be disabled should the WAN failover to WAN1, 329 | due to the fact that it will most likely be a slower more latent device. In this scenario, this rule 330 | would most likely cause continuous resets due to higher ping/latency, and is rightly so ignored in this 331 | particular scenario. 332 | - FIXED: Minor tweaks and corrections 333 | 334 | v2.12 - (August 8, 2022) 335 | - CHANGED: the color scheme to match that of RTRMON and PWRMON a bit more. Seeing a little more uniformity 336 | and standardization between the three helps calm my OCD. ;) 337 | - FIXED: realizing that the timezone abbreviation can vary from 1 char to 5 chars across the world, which 338 | skews the time to the left/right,so I have built in some logic that adjusts the top line that includes 339 | the current line to ensure that it lines up with the subsequent lines underneath. Yep, another OCD- 340 | related fix. lol 341 | 342 | v2.11 - (August 3, 2022) 343 | - ADDED: Added a VPN Director rule restart after VPNMON-R2 goes through a reset cycle to help with possible 344 | compatibility issues in dual WAN/secondary WAN disconnects. 345 | - FIXED: Minor tweaks and corrections 346 | 347 | v2.1 - (July 22, 2022) 348 | - ADDED: Completely reworked the setup/config menus to make the look/feel/act like RTRMON's. The hope was 349 | to simplify the process, allowing one to pick and choose settings to configure, instead of having to run 350 | down a long laundry list of configuration questions. I have done away with the loading of current config 351 | values as "defaults" when hitting the enter button, as it would be fairly easy to scroll up and see what 352 | value you had in place if need be. Enter on a blank line now assumes you want the system default. 353 | - ADDED: An extra round of VPN client kill commands when the router detects WAN trouble, just to make sure 354 | it pre-emptively kills everything incase these VPN clients try to reconnect while the WAN is down. 355 | - FIXED: Vastly reworked the logic of the WAN down scenario, and seems to be transitioning much smoother 356 | through the various stages of dealing with a lost connection. Definitely game-changing!! 357 | 358 | v2.01 - (July 17, 2022) 359 | * ADDED: New logic to determine if a screen session already is running with the alias 'vpnmon-r2'. If there 360 | is a session running, and you execute another "vpnmon-r2 -screen", it will prompt you whether or not you 361 | want to just reattach to the already-running session - thanks @Kal1975! 362 | * FIXED: Better dual-wan logic for those running @Ranger802004's dual-wan script to eliminitate some error 363 | messages when both WAN0 and WAN1 were connected at the same time. Thanks to @JAX1337 and @Stephen 364 | Harrington for the heads-up! Huge thanks To @Ranger802004 for further troubleshooting routing 365 | compatibility between our two scripts in a Dual-WAN failover/load balancing situation. Please note, this 366 | is an interim release until I can dive into Dual-WAN capabilities at a near future date to ensure 367 | VPNMON-R2 can effectively handle each situation presented to it. 368 | 369 | v2.0 - (July 10, 2022) 370 | * MAJOR: The VPNON.SH project has been sunset. Instead of maintaining almost 2 identical functions in both 371 | VPNMON-R2 and VPNON, I have decided to terminate the VPNON project. All functionality of VPNON will 372 | continue to live on in VPNMON-R2. 373 | * ADDED: The ability to reset the VPN with a "vpnmon-r2.sh -reset" commandline switch. This gives you the 374 | same functionality that VPNON gave you, and are able to use this method to randomly reset your VPN 375 | connection using CRON jobs. VPNMON-R2 running in its own SSH or Screen window will be aware of these 376 | actions, will pause the UI while the reset is running, and will resume when finished. 377 | * ADDED: New indicator showing if one of your pre-configured VPN host slots goes down, and is no longer 378 | reachable via ping, and will display the affected VPN slot as OFFLINE. 379 | * Configured an alias for VPNMON-R2 which lets you call all functions relating to the script from any 380 | location (without having to be in the /jffs/scripts folder or having to call it like 381 | /jffs/scripts/vpnmon-r2.sh), now using a command like this: "vpnmon-r2 -log" 382 | * FIXED: Made a few more wording changes in the setup menu thanks to the keen eye of @RimRider, and also 383 | tweaked the functionality of the menu a bit more. Now, when calling the setup menu from the UI, you will 384 | return to the UI when exiting out of the menu. 385 | 386 | v1.93 - (July 6, 2022) 387 | * MAJOR: Very happy to announce that VPNMON-R2 is now being included in AMTM! Many thanks to @thelonelycoder 388 | for his consideration and help getting this included! 389 | * FIXED: Fixed the logic to dispay the proper router model using some of @thelonelycoder's code which should 390 | report back the right info from NVRAM. 391 | * CHANGED: As such, did a few more cleanup items to make menu choices less ambiguous, and creating proper 392 | exits for items that require an exit vs. going back to a menu. 393 | 394 | v1.92 - (July 5, 2022) 395 | * FIXED: A bug in the setup menu (thanks @kuki68ster), and now checks for the existence of the timeout and 396 | screen utilities - if they exist, then it just continues on to the configuration menu, bypassing the need 397 | to answer whether you want to install these two utilities. 398 | * CHANGED: Resets the terminal colors on exit to play more friendly with other scripts. 399 | * ADDED: An easter-egg. Let me know if you find it, and if it gave you a chuckle. ;) 400 | 401 | v1.91 - (July 4, 2022) 402 | * FIXED: Minor wording changes, small bug fixes from some stuff I've noticed while running it to help with 403 | further increasing stability. 404 | 405 | v1.9 - (July 3, 2022) 406 | * ADDED: A fourth qualifier variable thanks to @JAX1337 that will reset the VPN connection if the average 407 | ping across the tunnel is greater than the specified amount, in the hopes of eliminating a slow connection 408 | in favor of something a little faster. Please make sure you run through the config to change the default 409 | of 100ms to something you prefer. 410 | * ADDED: new functionality thanks to a suggestion from @JAX1337... this option will let you be able to use 411 | VPNMON-R2 to reset connections based on best speed/ping to your pre-configured VPN client slots. Going 412 | through the "-config", new question 5 will let you choose whether you want it to randomly pick, or use the 413 | lowest ping when choosing your VPN servers. In the process, the UI now shows average ping going to each of 414 | your configured slots, and will notify you on the bottom of the UI if it has found a better server to 415 | connect to. You have the option in question 5a to specify how many chances you would like your current VPN 416 | connection to deal with other servers that might have a lower ping, giving your current connection a chance 417 | to recover. I have found that if you have other servers configured in your vicinity, there's a chance they 418 | will compete with each other, which would be causing your connection to drop and reconnect to the "now" 419 | fastest server repeatedly. This configurable counter will help alleviate this behavior. ;) 420 | * ADDED: the capability to use a keypress from the main UI to get into the -setup menu using (S), or forcing 421 | a reset with the {R} key, and of course being able to gracefully exit using the (E) key. Please note, you 422 | can press these keys at any time, but they won't get picked up until the main progress bar starts its 423 | interval count. These keypress options are indicated at the top right of the UI at all times. Sounds like 424 | an opportunity to build in some Easter Eggs now. :) 425 | * CHANGED: Enhanced and simplified some of the setup process when it comes to asking questions about NordVPN, 426 | SurfShark and PerfectPrivacy, and assigning variables to each. Also completely revamped the -config process 427 | to either let you start from scratch with default values, or use already existing values that you have 428 | modified in your current config file. Great suggestion by @iTyPsIDg to prevent you from having to 429 | continually modify the same entries over and over when a new version comes out. 430 | * CHANGED: reduced the amount of clutter that a reset produces on the screen, and is much less verbose, and 431 | looks much cleaner. Using on-screen indicators to show what's currently happening in the script. Will 432 | continue to refine these. 433 | 434 | v1.8 - (June 23, 2022) 435 | * ADDED: A new row of VPN stats have been added to include current protocol, port, cryptography, and 436 | authentication digest, just to give you more detailed info pertaining to your current VPN connection. 437 | * CHANGED: Made some minor changes to the look/feel and layout of the UI, and gave it more of an old-skool 438 | DOS folders kind of feel. Please note, I will never be satisfied with the look, and will continue to 439 | enhance it when I find something else that's pleasing to the eye. Also, the progress bar will change 440 | from green to yellow to red as it gets closer to its interval time. 441 | 442 | v1.71 - (June 9, 2022) 443 | * FIXED: Minor fix on the code that handled resets when VPN server loads exceeded a certain amount. The 444 | code was preventing a reset, unless you were a Perfect Privacy VPN user. Fixed! 445 | 446 | v1.7 - (June 4, 2022) 447 | * SIGNIFICANT: Added capabilities for Perfect Privacy VPN services on VPNMON-R2. As with the Surfshark 448 | integration, you get to enjoy all the same features that both Surfshark and NordVPN users get to have. You 449 | can randomly pick to randomly reconnect one of your VPN slots at a scheduled time, use Perfect Privacy 450 | SuperRandom functionality to pick one random server within your country, or from multiple countries to 451 | connect to, and optionally updates Skynet to ensure that your connection experience stays whitelisted at 452 | all times. Thanks for the suggestion, @Swistheater! 453 | * SIGNIFICANT: Added the option to leverage your Entware installation in order to utilize the CoreUtils-Timeout 454 | utility. It is recommended to allow VPNMON-R2 to use this utility in order to cut down on (what I'm 455 | guessing is) random hardware-level hangups when calling for nvram values specifically on RT-AC86U routers. 456 | When running VPNMON-R2, it will detect whether or not you have CoreUtils-Timeout installed, and will use 457 | the utility if it's present. If it's not installed, VPNMON-R2 will just operate as normal. You can install 458 | this optional utility using the -install switch, and step through option 1. 459 | * ADDED: Created a new Install menu that you can access by running 'vpnmon-r2.sh -install'. This option 460 | will guide the user through installing the optional Entware CoreUtils-Timeout utility, and prompt the 461 | user to go through the config menu. You also have the option to force re-install the Entware Timeout 462 | utility, or go through the vpnmon-r2 uninstall process. 463 | * FIXED: There was an issue with the Load calculation for Perfect Privacy. Added corrective measures, and 464 | should be showing the correct values now! 465 | * CHANGED: Some code cleanup and other housekeeping items 466 | v1.6 - (May 23, 2022) 467 | * SIGNIFICANT: Added capabilities for SurfShark VPN services on VPNMON-R2! This is basically a duplication of 468 | the capabilities that NordVPN users got to enjoy. You can randomly connect to one of your VPN slots at a 469 | scheduled time, use SurfShark SuperRandom functionality where it will pick random servers for you across 470 | your country and configure those in your VPN slots, then randomly connect to one. Also, you can choose up 471 | to 3 countries to randomly draw from under SuperRandom mode. Looking for feedback from SurfShark users. :) 472 | - thanks for the suggestion @Phk! 473 | * ADDED: A log rotation option has been added to the -config, which allows you to specify how large you would 474 | like your VPNMON-R2.log file to get before it starts trimming it down. Default will be 1000 lines, which 475 | should give you several weeks worth of data to sift through. 476 | * CHANGED: Reworked the script -update function to exit to the -config menu, rather than running the script 477 | using the -monitor function. The thinking is people would rather run through the -config immediately after 478 | due to potentially new functionality that would need to be enabled/disabled. 479 | * FIXED: the VPN reset date/time counter wasn't resetting after a WAN failure, and now accurately reflects 480 | when the VPN was last reset. 481 | 482 | v1.5 - (May 20, 2022) 483 | * SIGNIFICANT community testing and development has been done on the WAN up/down functionality... VPNMON-R2 is 484 | now checking for 2 distinct events -- (1) where the modem is physically off/disconnected, and (2) where the 485 | modem is on, but the ISP is down/disconnected. I never knew that the router/NVRAM couldn't tell the difference 486 | until @Stephen Harrington and @iTyPsIDg made this observation. But the end results after testing this is that 487 | it seems to be able to get past both hurdles now, and successfully re-establish a VPN connection after a 488 | major event. Sidenote: I don't think I've brought my internet down this much in the last 10 years total. 489 | My family thanks you and is praying this is the gold version! LOL. Sincere thanks to everyone involved on 490 | helping troubleshoot this and jumping in to pull apart this code! You all absolutely rock -- 491 | @Stephen Harrington, @SomeWhereOverTheRainBow, @dave14305, @iTyPsIDg ... thank you so much! 492 | * NEW: Added some extra bonus features and expanded the number of stats to include the WAN state, public- 493 | facing VPN IP address, as well as ping stats across the WAN interface(s). Should be dual-WAN capable, and 494 | indicate which WAN interface is active. 495 | * Crunched the code through shellcheck.net... lots of small changes to formatting of calculations and logic 496 | based on its suggestions -- thanks @SomeWhereOverTheRainBow 497 | * Added a new parameter called "-uninstall" to the list in order to completely uninstall the script (not that 498 | I'm encouraging you to do so, but at least you can now!) Usage: "vpnmon-r2 -uninstall" -- thanks @andywee 499 | * Added a new parameter called "-screen", which will kick off VPNMON-R2 using the screen utility so we don't 500 | have to type this huge commandline each time. Please note -- requires the "screen" utility to be installed. 501 | Usage: "vpnmon-r2.sh -screen" -- thanks @Kal1975 502 | * Added the ability to hit enter on items during the config that were asking for values, and adds default values 503 | for fill-in-the-blank and yes/no items -- thanks @chongnt 504 | * Added live feedback during the config process to indicate what you just entered, to hopefully catch any typos 505 | before getting saved into the config. I thought this would be less messy than showing a huge summary of what 506 | all entries would be added to the config at the end of the setup process -- thanks @Kal1975 507 | * Added a WAN connectivity check to the top of the VPN reset function. It will start off by first validating 508 | whether or not there's a functional WAN connection before attempting to initiate a VPN connection. 509 | * Added a WAN connectivity check during the regular loop to see if the WAN is up or down based on an SSL 510 | handshake + verification to 8.8.8.8 (over the WAN connection). If this fails, VPNMON-R2 will fall back to a 511 | loop, and keep rechecking until the WAN is re-established, then will re-establish the VPN -- thanks @Kal1975 512 | * Changed the exit VPN city lookup to use the icanhazip.com external/public ip service to help with location 513 | accuracy -- thanks @Kal1975 514 | * Some excellent coding suggestions allowed me to eliminate my last [[ ]] wild card match and replace it with a 515 | fancy grep statement to attempt to catch an error condition when calling the API to check the city name based 516 | on the IP address -- thanks so much @SomeWhereOverTheRainBow/@iTyPsIDg 517 | * Added another item to the config menu -- a delayed start-up option -- allowing you to specify how many 518 | seconds you would like to delay VPNMON-R2 from running after it starts up. This was added to allow for more 519 | compatibility with other potential scripts that are starting up after a router reboot. Please go through the 520 | "vpnmon-r2.sh -config" to add this setting -- thanks @Stephen Harrington 521 | * Fixed: If the avgping value = null, then display 0 until it fixes itself the next time around 522 | * Fixed: Added some modification to the timing involved in calculating the TX/RX values over the VPN tunnel. 523 | Due to the time it takes for the WAN to determine connectivity + the NordVPN Load lookup, I'm timing these 524 | functions to add their results to the entire calculation, hopefully to display slightly more accurate stats. 525 | 526 | v1.4 - (May 01, 2022) 527 | * The big news today is that VPNMON-R2 is now able to integrate with YazFi! Thanks to @iTyPsIDg for the great 528 | suggestion! Using the setup utility (-config switch), you can now specify which of the 3 x 2.4Ghz, 5Ghz and 529 | secondary 5Ghz guest networks you want to sync with VPNMON-R2 when it randomly picks a new VPN connection 530 | and updates the slot number directly in YazFi. This should make life a lot more bearable for those running 531 | multiple guest networks, and wanting to make use of the full power of randomized VPN connections! :) 532 | * The other big news is that VPNMON-R2 can now also accept 2 additional NordVPN countries for a total of 3 533 | supported countries to randomly connect to! Also configurable through the setup utility (-config switch), 534 | you can now specify which additional (up to) 2 countries you want to add. When VPNMON-R2 goes through it's 535 | reset function, it will randomly pick from one of the (up to) 3 countries, optionally whitelist all available 536 | NordVPN servers for that country in your Skynet firewall, and optionally make a SuperRandom(r) connection 537 | to one out of the many available servers in the specified country! Yes, we have gone international! Thanks 538 | goes to @Spud for the excellent suggestion! 539 | * Some more code cleanup, optimizations and expanded on the config menu to handle the new YazFi and multiple 540 | country questions during setup. 541 | 542 | v1.3 - (Mar 20, 2022) 543 | * Added another row of stats! The latest additions include near-realtime average RX and TX bandwitdh (in Mbps) 544 | across the active VPN tunnel. Also, the current total TX and RX bytes for the VPN tunnel is displayed and 545 | gradually increments from when the tunnel was initialized (in Gb). Stats for these bandwith figures are 546 | interpreted from an OpenVPN status file that is auto generated when the tunnel is initiated. Please understand 547 | that these numbers are generated based on the interval time period you have configured, and may not reflect 548 | actual real-world amounts. These will give you a good general indicator on what's happening across your VPN. 549 | That's my disclaimer. ;) 550 | * The ability to enable/disable these stats is available in the configuration utility (vpnmon-r2.sh -config). 551 | * I have really taken a liking to the new ASCII art font title for VPNMON-R2, that I have now incorporated it on 552 | the top of the main UI. Version number was moved to its right. 553 | * I have moved the new version alert to directly below the ASCII art font title, and is more discreet in a red 554 | font in letting you know when a new version is available. 555 | 556 | v1.2 - (Mar 17, 2022) 557 | * Added for the capability of VPNMON-R2 to check for a new version on a periodic basis, and will alert you within 558 | the interface when a new version becomes available for download. From v1.2 moving forward, the script will 559 | provide for the capability to check and alert you for new updates. 560 | * Added a new commandline argument to the list of available commands: "sh vpnmon-r2.sh -update" -- this runs the 561 | script update utility which downloads and installs the latest version from the github repository. 562 | * Minor optimizations and enhancements 563 | 564 | v1.1 - (Mar 15, 2022) 565 | * Added an integrated configuration utility that steps you through all available configurable options to give you 566 | the most compatible experience for your setup. This tools makes the experience much more pleasing than having 567 | to deal with manually editing (and understanding) the options that were available at the top of the script. The 568 | configuration tool is called by using the following command: "sh vpnmon-r2.sh -config" 569 | * Introduced the capability to use commandline arguments to perform various functions in the script. Available 570 | commands are (1) -h or -help -- to display a quick overview of available commands, (2) -log -- to display the 571 | contents of the log file within the NANO text editor, (3) -config -- this runs the configuration utility, and 572 | steps you through all available options, and writes your selections to a config file, and (4) -monitor -- this 573 | runs VPNMON-R2 under normal monitoring operating conditions to keep an eye on the health of your VPN connection. 574 | * Moved all working files (config, log and reset log) to its own dedicated folder named "vpnmon-r2.d" under 575 | "/jffs/addons". The main script can still be found under "/jffs/scripts/vpnmon-r2.sh" 576 | * Various optimizations and small bug fixes (more like annoyances that bother my OCD). 577 | 578 | v1.0 - (Feb 26, 2022) 579 | * We're at the big v1.0! VPNMON-R2 (and VPNON) have made some huge strides in these 2 short months! ;) 580 | * Introducting a new NordVPN Server Load stat! In lieu of showing whether or not Skynet is getting updated on the 581 | stats row, it now shows the NordVPN Server Load thanks to a suggestion by @JackYaz. This Load stat is only 582 | available if you enable the "UseNordVPN" variable and set it to "1", or if the "NordVPNSuperRandom" variable is set 583 | to "1". Otherwise, it will default to showing the Skynet stat based on if "UpdateSkynet" is set to "1". 584 | * A great byproduct to now showing this Load stat, is that another VPN reset can occur if it exceeds a certain 585 | threshhold. Currently the "NordVPNLoadReset" is set to 50, so if the current NordVPN server you're connected to 586 | exceeds a 50% load, it will reset the VPN to look for another server with a lesser load. All these items are totally 587 | configurable at the top of the script. 588 | 589 | v0.9 - (Feb 23, 2022) 590 | * Added a row of stats to the bottom of VPNMON-R2's interface, specifically showing the Low and High ping history for 591 | the current connection, whether or not Skynet gets updated with NordVPN IPs, and how VPNMON-R2 is currently 592 | configured, showing either: (a) "VPNMGR" - VPNMON-R2 is integrated with VPNMGR and using its functionality 593 | periodically to update latest NordVPN/PIA/WeVPN server information into your VPN slots, (b) "NordVPN SuperRandom" - 594 | VPNMON-R2 is randomly selecting one of hundreds/thousands of NordVPN servers from within the specified country and 595 | populating your VPN slots, and (c) "Standard" - VPNMON-R2 is neither using VPNMGR or SuperRandom functionality, and 596 | optionally restarting your VPN connections on a random basis based on your set schedule. This is a clean and easy 597 | way to see how VPNMON-R2 is configured, and giving you some performance stats along with it. Enjoy! 598 | 599 | v0.8 - (Feb 20, 2022) 600 | * Added the concept of SuperRandom(tm) NordVPN Connections! This mode, when enabled (NordVPNSuperRandom=1) -- if you 601 | choose to be so incredibly daring and adventurous -- will fill your VPN client slots with random VPN servers across 602 | the country of your choice! Distance, load, and performance be damned!! In the US, the number of available VPN 603 | servers is up to around 1920, which fluctuates. This option will bypass VPNMGR functionality to update your VPN 604 | slots with its recommendations (based on chosen city, performance and load). Thus -- it is assumed that each of 605 | your (up to 5) VPN client slots are fully configured and operational! The SuperRandom(tm) function will only 606 | replace the "server address" IP and "description" (in a "NordVPN - City" format), and reinitiate the connection as 607 | usual after losing your connection, having multiple connections going, or after a scheduled reset. Enjoy! 608 | * The NordVPNCountry variable is now available for you to populate with the country of your choice without having to 609 | mess around with the code. These are all available country names to choose from: Albania, Argentina, Australia, 610 | Austria, Belgium, Bosnia and Herzegovina, Brazil, Bulgaria, Canada, Chile, Costa Rica, Croatia, Cyprus, Czech 611 | Republic, Denmark, Estonia, Finland, France, Georgia, Germany, Greece, Hong Kong, Hungary, Iceland, India, 612 | Indonesia, Ireland, Israel, Italy, Japan, Latvia, Lithuania, Luxembourg, Malaysia, Mexico, Moldova, Netherlands, 613 | New Zealand, North Macedonia, Norway, Poland, Portugal, Romania, Serbia, Singapore, Slovakia, Slovenia, South 614 | Africa, South Korea, Spain, Sweden, Switzerland, Taiwan, Thailand, Turkey, Ukraine, United Arab Emirates, United 615 | Kingdom, United States, Vietnam. 616 | * Other code optimizations, error catching, and formatting fixes just to make it more pleasing to the eye. ;) 617 | 618 | v0.7 - (Feb 18, 2022) 619 | * Spent a lot of time dealing with a persistent hang issue, and looks to be resolved. I believe the script was running 620 | into a race/deadlock type of situation where it would hang during successive NVRAM lookups that were happening too 621 | close together calling for the same values. I reduced the number of lookups being done, and works flawlessly now. 622 | * Added some debug commands for future debugging needs, thanks to @eibgrad for his expert help and advice on how to 623 | accomplish all this. 624 | * Added a VPNMON-R2.LOG entry that shows when a city lookup is being done through the API. 625 | 626 | v0.6 - (Feb 1, 2022) 627 | * Added a new API lookup to display the VPN exit nde city/location next to the active VPN connection. This API is 628 | free, and guarantees at least 1000 lookups per month. In lieu of doing a lookup each single refresh interval, a 629 | location lookup is only done when either the script starts up fresh, when it detects VPNON doing a reset, or if 630 | VPNMON-R2 initiates a reset. So, hopefuly not more than 1x or 2x/day, or 30x/60x/month, well below the cut-off. 631 | So here is a disclaimer... lookups are based on your VPN's IP address, and we all know how wrong an IP location 632 | lookup can be at times when ISP's move IP ranges around, so please understand if it's not displaying the correct 633 | city at times. So far, it's been pretty darn near 100% correct for me. 634 | * Enhanced the alert entries in the logs a bit more to make them stand out when we're dealing with a connection 635 | failure, or multiple connections. VPN failures are now surrounded with asterisks during DEFCON5 level events. 636 | * Moved the refresh interval indicator to the top row next to the scheduled reset time. 637 | * Some cosmetics color change enhancements to the output screen and cleaned up the code to make it look more uniform. 638 | Need to work on variable naming uniformity next, as that's *ALL* over the place still. Give me time! 639 | * Replaced the spinner with a decent looking progress bar... spinner was looking long-in-the-tooth. Enjoy! ;) 640 | 641 | v0.5 - (Jan 23, 2022) Wow, where to start... 642 | * VPNMON.SH was heavily overhauled into VPNMON-R2.SH to incorporate my other script, VPNON.SH, so that it could act 643 | standalone, without needing to call a second script. VPNON has now turned into a function within the script. 644 | * Speaking of which -- I learned lots about functions ;) ... In doing so, I cleaned up some of the inefficient code, 645 | namely, how it checks for each individual VPN connection. Now, it basically loops from 1 through N and calls the 646 | function that checks the VPN connection without having to make so much duplication in the code itself. 647 | * Speaking of functions, I turned the spinner into a function as well. Cleaner and more optimized code is wonderful! 648 | * I wanted to display the last time VPN was reset, so that it saved this point-in-time each time you restarted 649 | VPNMON-R2 instead of resetting to 0d 0h 0m, etc. I built functionality that saves the exact time to a file called 650 | /jffs/scripts/vpnmon-rst.log, from where it reads and populates this time on screen each time a reset occurs. 651 | * VPNMON-R2 is now also able to perform a regularly scheduled VPN reset without the need to run VPNON.SH through a 652 | CRU job. This is completely configurable, and now also displays your configured reset time on screen. 653 | * Also being displayed on screen, is the interval (in seconds) in which it loops to check the validity of your VPN 654 | connections. 655 | * Overall, spruced up the look and feel of the visual in your SSH window to show pertinent information without 656 | cluttering up the screen. Hope you like it! 657 | * Above all, I wanted to make this script flexible enough for those who aren't running VPNMGR, using NordVPN or 658 | making use of the Skynet Firewall, so options have been built-in to bypass this functionality to make it usable 659 | in any VPN usage scenario. 660 | 661 | ------------------------------------- 662 | VPNMON.SH was deprecated on Jan 22, 2022) 663 | 664 | v0.8 - (Jan 20, 2022) 665 | * Added a timer to show the last time that the VPN was reset, or, when vpnmon.sh was restarted last, whichever 666 | happened most recently. 667 | * Also, added a spinner to indicate that the script is still active. Various optimizations and code clean-up. 668 | 669 | v0.7 - (Jan 15, 2022) 670 | * Added the avg ping time next to the "Ping is Alive" indicator, which shows avg time in ms across the active VPN 671 | tunnel to the ping host specified. 672 | 673 | v0.6 - (Jan 14, 2022) 674 | * Added logging capabilities. Major events (resets/connection issues/etc) are logged to a file named 675 | "vpnmon-on.log" in the /jffs/scripts folder by default. This capability can be disabled by changing the value to 676 | "/dev/null". PSA: though it doesn't do a crazy amount of logging, over time it will get larger and larger and will 677 | eventually impact the total space available in /jffs. Recommend keeping an eye on this, and wiping the 678 | "vpnmon-on.log" on occasion. Will consider adding a more automated log purging feature in the future. ;) 679 | 680 | v0.5 - Initial release of VPNMON.SH (Jan 12, 2022) 681 | --------------------------------------------------------------------------------