add failover.sh and failover init script

update README
master
Thomas Lynch 3 years ago
parent 8a34056c40
commit 012ea39c6f
  1. 15
      README.md
  2. 10
      failover
  3. 103
      failover.sh

@ -1,3 +1,16 @@
# Basic Mwan
init.d script for monitoring and adjusting route metrics of 2 WANs in a multi-WAN setup on OpenWRT. Used as a simple alternative to mwan3, where I just want failover and all traffic forwarded through wireguard vpn (mwan3 seems to struggle with this).
init.d script for monitoring and adjusting route metrics of 2 WANs in a multi-WAN setup on OpenWRT.
Used as a simple alternative to mwan3, where I just want failover and all traffic forwarded through wireguard vpn (mwan3 seems to struggle with this).
```bash
cp failover /etc/init.d/failover
cp failover.sh /usr/bin/failover.sh
chmod +x /etc/init.d/failover
chmod +x /usr/bin/failover.sh
/etc/init.d/failover enable
/etc/init.d/failover start
```
The script uses logger to write to openwrt system log, which can be monitored using `logread`.
It will log when it starts, when some pings fail, and when switching between WANs.

@ -0,0 +1,10 @@
#!/bin/sh /etc/rc.common
START=90
start() {
/usr/bin/failover.sh &
}
stop() {
PID=`ps | awk '/failover.sh/ {print $1}'`
kill -9 $PID
}

@ -0,0 +1,103 @@
#!/bin/bash
INTERVAL=1
PACKETS=1
#reliable hosts for checking are cloudflare, quad9, hgoogle
HOSTS=("1.1.1.1" "9.9.9.9" "8.8.8.8")
WAN1=eth0
WAN2=wwan0
USINGWAN=eth0
CHECKWAN=eth0
COUNTER=0
CHANGED=0
function change_wan_metric() {
CHANGED=$SECONDS
local ROUTE=0
# 100 just in case this runs away for some reason
while [ $ROUTE -le 100 ]
do
local ROUTE_IFACE=`uci get network.@route[$ROUTE].interface`
if [ "$ROUTE_INTERFACE" == "uci: Entry not found" ]; then
break
elif [ "$ROUTE_INTERFACE" == "wan" ]; then
uci set network.@route[$ROUTE].metric='$1'
uci commit
reload_config
break
fi
let ROUTE++
done
}
function debug {
logger -t failover "`date`: pings:$PINGS, counter:$COUNTER, changed:$CHANGED, seconds:$SECONDS, usingwan:$USINGWAN, checkwan:$CHECKWAN"
}
logger -t failover "`date`: Failover script started."
while sleep $INTERVAL
do
if [ "$USINGWAN" == "$WAN2" ] && [ $(($SECONDS-$CHANGED)) -gt 300 ]; then
debug
# after 5 minutes on failover wan2, check main wan. if it fails counter will go to 1 but since
# wan2 is still fine it should reset to 0 next time and stay on wan2, until the check repeats and so on.
CHECKWAN=$WAN1
CHANGED=$SECONDS #and reset changed so it just tried once then returns to checking working wan
fi
PINGS=0
for (( c=0; c<${#HOSTS[@]}; c++ ))
do
RET=`ping -I $CHECKWAN -w 1 -W 1 -c $PACKETS ${HOSTS[c]} 2>/dev/null | awk '/received/ {print $4}'`
if [ "$RET" == "$PACKETS" ]; then
let PINGS++
fi
done
#debug if any pings fail, just for fun
if [ $PINGS -lt ${#HOSTS[@]} ]; then
debug
fi
# if all pings failed increase counter
if [ $PINGS -eq 0 ]; then
let COUNTER++
else
COUNTER=0
fi
# counter failed pings to all hosts multiple times, switch WAN
if [ $COUNTER -gt 3 ]; then
debug
# NOTE: if both wan fail, it will just switch back and forth. but not like it matters, neither would work anyway... lol
if [ "$USINGWAN" == "$WAN1" ]; then
#if failed and currently on wan, switch to wanb
change_wan_metric 2
USINGWAN=$WAN2
CHECKWAN=$USINGWAN
logger -t failover "`date`: Changed active WAN metric to 4G modem!"
elif [ "$USINGWAN" == "$WAN2" ]; then
#if failed and currently on wanb, switch back to wan
change_wan_metric 0
USINGWAN=$WAN1
CHECKWAN=$USINGWAN
logger -t failover "`date`: Changed active WAN metric to Cable connection!"
fi
elif [ $COUNTER -eq 0 ]; then
# counter is successful, if on wan2 and wan1 has recovered return to wan1
if [ "$CHECKWAN" == "$WAN1" ] && [ "$USINGWAN" == "$WAN2" ]; then
debug
#if failed and currently on wanb, switch back to wan
change_wan_metric 0
USINGWAN=$WAN1
CHECKWAN=$USINGWAN
logger -t failover "`date`: Changed active WAN metric to Cable connection!"
fi
fi
#set the checkwan back to the usingwan, in case it was set to the other wan for recovery check
CHECKWAN=$USINGWAN
done;
Loading…
Cancel
Save