Skip to content

Instantly share code, notes, and snippets.

@Sn4kY
Forked from Apsu/failover.sh
Last active January 30, 2022 00:20
Show Gist options
  • Save Sn4kY/b741478b5c302fd221a8bc314921d7a2 to your computer and use it in GitHub Desktop.
Save Sn4kY/b741478b5c302fd221a8bc314921d7a2 to your computer and use it in GitHub Desktop.
A failover script for dual WAN with dual interfaces, using a ping healthcheck and managing default routes appropriately, with antiflap and back to normal state availability
#!/bin/bash
# Set defaults if not provided by environment
CHECK_DELAY=${CHECK_DELAY:-5}
CHECK_LOOPS_FAIL=${CHECK_LOOPS_FAIL:-3}
CHECK_LOOPS_REVERT=${CHECK_LOOPS_REVERT:-5}
CHECK_IP=${CHECK_IP:-8.8.8.8}
PRIMARY_IF=${PRIMARY_IF:-enp0s17}
PRIMARY_GW=${PRIMARY_GW:-192.168.1.252}
BACKUP_IF=${BACKUP_IF:-enp0s18}
BACKUP_GW=${BACKUP_GW:-192.168.100.1}
# Compare arg with current default gateway interface for route to healthcheck IP
gateway_if() {
[[ "$1" = "$(ip r g "$CHECK_IP" | sed -rn 's/^.*dev ([^ ]*).*$/\1/p')" ]]
}
ip route del ${CHECK_IP} via ${PRIMARY_GW}
LOOP_FAIL=0
LOOP_REVERT=0
# Cycle healthcheck continuously with specified delay
while sleep "$CHECK_DELAY"
do
# If healthcheck succeeds from primary interface
ip route add ${CHECK_IP} via ${PRIMARY_GW}
if ping -I "$PRIMARY_IF" -c1 "$CHECK_IP" &>/dev/null
then
ip route del ${CHECK_IP} via ${PRIMARY_GW}
# Are we using the backup?
if gateway_if "$BACKUP_IF"
then # anti-flap
LOOP_REVERT=$(( $LOOP_REVERT + 1 ))
if [[ $LOOP_REVERT -le $CHECK_LOOPS_REVERT ]] ; then echo $(date +'%Y-%m-%d %H:%M:%S') " : check successful ! (${LOOP_REVERT}/${CHECK_LOOPS_REVERT})" ; fi
if [[ $LOOP_REVERT -ge $CHECK_LOOPS_REVERT ]]
then # swith to primary
echo $(date +'%Y-%m-%d %H:%M:%S') " : reverting to primary after ${LOOP_REVERT} checks successful"
ip r d default via "$BACKUP_GW" dev "$BACKUP_IF"
ip r a default via "$PRIMARY_GW" dev "$PRIMARY_IF"
LOOP_FAIL=0
fi
else LOOP_FAIL=0
fi
else
ip route del ${CHECK_IP} via ${PRIMARY_GW}
LOOP_FAIL=$(( $LOOP_FAIL + 1 ))
if [[ $LOOP_FAIL -le $CHECK_LOOPS_FAIL ]] ; then echo $(date +'%Y-%m-%d %H:%M:%S') " : check ${LOOP_FAIL}/${CHECK_LOOPS_FAIL} failed" ; fi
if [[ $LOOP_FAIL -ge $CHECK_LOOPS_FAIL ]]
then
# Are we using the primary?
if gateway_if "$PRIMARY_IF"
then # Switch to backup
echo $(date +'%Y-%m-%d %H:%M:%S') " : switching to backup"
ip r d default via "$PRIMARY_GW" dev "$PRIMARY_IF"
ip r a default via "$BACKUP_GW" dev "$BACKUP_IF"
LOOP_REVERT=0
else LOOP_REVERT=0
fi
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment