Since pfSense is not actually rerouting router traffic itself (such as DNS, VPN, …) but only incoming traffic when a gateway goes down and another one is configured in the same gateway group, I have written the following script that you can use in a cron job. It will change the IPv4 default route for basically all traffic not specifically treated via FW rules – including the internal services.
- MOBILE1 needs to be set to your second gateway, in my case a mobile LTE device
- MOBILE2 and MOBILE3 need to be set to rarely used IPs – so the LTE traffic going there is not too much as
- MOBILE2 and MOBILE3 need to be statically routed via LTE, always, to check their reachability
- WAN1 needs to be set to your main gateway, in my case a FritzBox
- WAN2 and WAN3 need to be set to pages you usually want to reach, but it is not so bad to be unreachable in case of a downtime of the WAN gateway as
- WAN2 and WAN3 need to be statically routed via WAN, always, to check their reachability
The script will log changes and send mails to the email address configured in pfSense.
#!/usr/local/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
ROUTE=/sbin/route
LOG=/root/switched.txt
# Destinations, die man fast nie braucht (Traffic-Beschraenkung via MOBILE) und von MOBILE gehen sollten, muessen via MOBILE geroutet werden!
# Router selber
MOBILE1=192.168.166.1
# www.t-online.de
MOBILE2=217.6.164.162
# www.lrz.de
MOBILE3=129.187.255.234
# Normale IPs, muessen via WAN geroutet werden!
# Router selber
WAN1=192.168.178.1
# www.berlin.de
WAN2=212.45.111.17
# www.hamburg.de
WAN3=212.1.41.12
TRIES=3
SLEEP=0
WAN_SUCCESS=0
MOBILE_SUCCESS=0
# Router does not count
let MIN_TIMES=$TRIES*2
if [ $(netstat -nr4 | grep default | grep $WAN1 | wc -l) -eq 1 ]
then
ON_WAN=1
ON_MOBILE=0
else
ON_WAN=0
ON_MOBILE=1
fi
for try in $(seq 1 $TRIES)
do
for ip in $WAN1 $WAN2 $WAN3;
do
ping -t 2 -c 1 $ip 2>/dev/null >/dev/null && let WAN_SUCCESS=$WAN_SUCCESS+1
sleep $SLEEP
done
done
echo "3 WAN IPs reachable $WAN_SUCCESS times in $TRIES runs, minimum is $MIN_TIMES."
if [ $WAN_SUCCESS -ge $MIN_TIMES ] && [ $ON_WAN -eq 1 ]
then
echo "Enough WAN results and on WAN, nothing to do, exiting!"
exit
elif [ $WAN_SUCCESS -ge $MIN_TIMES ] && [ $ON_MOBILE -eq 1 ]
then
echo "Enough WAN results but on MOBILE, change back to WAN"
echo -n "Switching to WAN at " >> $LOG
date >> $LOG
echo "" | /usr/local/bin/mail.php -s"Switching to WAN"
$ROUTE del default && $ROUTE add default $WAN1
exit
fi
# Not enough WAN results, continue with MOBILE checks/actions
for try in $(seq 1 $TRIES)
do
for ip in $MOBILE1 $MOBILE2 $MOBILE3;
do
ping -t 2 -c 1 $ip 2>/dev/null >/dev/null && let MOBILE_SUCCESS=$MOBILE_SUCCESS+1
sleep $SLEEP
done
done
echo "3 MOBILE IPs reachable $MOBILE_SUCCESS times in $TRIES runs, minimum is $MIN_TIMES."
if [ $MOBILE_SUCCESS -ge $MIN_TIMES ] && [ $ON_MOBILE -eq 1 ]
then
echo "Enough MOBILE results and on MOBILE, nothing to do, exiting!"
exit
elif [ $MOBILE_SUCCESS -ge $MIN_TIMES ] && [ $ON_WAN -eq 1 ]
then
echo "Enough MOBILE results but on WAN, change to MOBILE"
echo -n "Switching to MOBILE at " >> $LOG
date >> $LOG
echo "" | /usr/local/bin/mail.php -s"Switching to MOBILE"
$ROUTE del default && $ROUTE add default $MOBILE1
exit
fi