Router redundancy scripts

This commit is contained in:
Emmanuel BENOîT 2012-07-29 11:34:35 +02:00
parent 1cb97260ba
commit 7b0b2087b3
8 changed files with 356 additions and 0 deletions

66
routers/README Normal file
View file

@ -0,0 +1,66 @@
Redundant routers control
==========================
I'm using two Linux routers at home, along with a manageable switch and an ADSL
modem.
Both routers have their own address, and so does the switch. When one of the
routers is active, it uses an additional address which serves as the default
gateway for the rest of the boxes.
One of the routers is an old box; it's rather slow, doesn't have much memory,
and more importantly, it's dying. Obviously, it should only be used when the
other one is down. However, if the connection has been established by that
secondary router, the primary should not take over until the DSL link goes down
on its own.
The scripts in this directory are used to control which router is active.
Checks on the primary router
-----------------------------
When the primary router is the active router:
1/ Check the switch
2/ If the switch is down, deactivate.
When the primary router is inactive:
1/ Check the switch and the main router address
2/ If the switch is up and the main router does not exist, activate.
Checks on the secondary router
-------------------------------
When the secondary router is the active router:
1/ Check the switch, the primary router, and a remote server
2/ If the remote server is reachable, do nothing
3/ If the switch is down, or if the primary router is up, deactivate.
When the secondary router is inactive:
1/ Check the switch, the primary router, and the main router address
2/ If the switch is up, and both the primary router and the main router
address are down, activate.
Installation
-------------
1/ Copy router-checks.conf to /etc, modify it however you want.
2/ Copy share/ to /usr/local/share/router-checks (or to whatever you set the
LIB_DIR configuration variable to).
3/ Modify activate.sh and deactivate.sh; they determine how a router becomes
the primary router and how a router releases primary routing control,
respectively.
4/ Copy primary-router.sh or secondary-router.sh to
/usr/local/sbin/router-checks
5/ If necessary (and if it will work on whatever distribution you use), use
the provided init script to start the checks on boot.

67
routers/init-script Normal file
View file

@ -0,0 +1,67 @@
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: router-checks
# Required-Start: $local_fs networking
# Required-Stop: $local_fs networking
# Should-Start: iptables-persistent ip6tables-persistent
# Should-Stop: iptables-persistent ip6tables-persistent
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Router control
### END INIT INFO
. /lib/lsb/init-functions
. /etc/router-checks.conf
case "$1" in
start)
log_daemon_msg "Starting router control..." "router-checks"
if [ -f $PID_FILE ]; then
log_action_msg "PID file exists"
log_end_msg 1
fi
/usr/local/sbin/router-checks </dev/null >/dev/null 2>&1
sleep 1
if [ -f $PID_FILE ]; then
log_end_msg 0
else
log_end_msg 1
fi
;;
stop)
log_daemon_msg "Stopping router control..." "router-checks"
if ! [ -f $PID_FILE ]; then
log_action_msg "PID file not found"
log_end_msg 1
fi
rm -f $PID_FILE.`cat $PID_FILE`
sleep 2
if [ -f "$PID_FILE" ]; then
count=18
log_action_begin_msg " Waiting"
while [ $count -gt 0 ] && [ -f "$PID_FILE" ]; do
sleep 5
log_action_cont_msg ""
count=$(( count - 1 ))
done
if [ -f "$PID_FILE" ]; then
log_end_msg 1
fi
fi
log_end_msg 0
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0

63
routers/primary-router.sh Normal file
View file

@ -0,0 +1,63 @@
#!/bin/bash
(
. /etc/router-checks.conf
exec >>$LOG_FILE 2>&1
date
echo "... STARTING"
. "$LIB_DIR/pings"
echo $$ > $PID_FILE
stop_file="$PID_FILE.$$"
trap "rm -f $stop_file" SIGINT SIGTERM
touch $stop_file
SLEEP_TIME=60
while [ -f "$stop_file" ]; do
sleep $SLEEP_TIME
SLEEP_TIME=1
pr_switch=`mktemp`
if [ -f "$ACTIVATION_FILE" ]; then
# When the primary router is active, disable it if the switch
# is off-line
wait_pings `try_ping $SWITCH_ADDR $pr_switch`
if [ -f "$pr_switch" ]; then
date
echo "de-activating connection"
$LIB_DIR/deactivate.sh
rm -f "$ACTIVATION_FILE"
SLEEP_TIME=10
fi
else
# When the primary router is inactive, enable it if the switch
# is up and the main router IP does not exist
pr_main=`mktemp`
wait_pings `try_ping $SWITCH_ADDR $pr_switch` \
`try_ping $MAIN_ADDR $pr_main`
if [ -f "$pr_main" ] && ! [ -f "$pr_switch" ]; then
date
echo "activating connection"
$LIB_DIR/activate.sh
touch "$ACTIVATION_FILE"
SLEEP_TIME=20
fi
rm -f "$pr_main"
fi
rm -f "$pr_switch"
done
if [ -f "$ACTIVATION_FILE" ]; then
$LIB_DIR/deactivate.sh
rm -f "$ACTIVATION_FILE"
fi
date
echo "... EXITING"
rm "$PID_FILE"
) &

View file

@ -0,0 +1,25 @@
# Router checks configuration
# Some remote address to ping
INTERNET_ADDR="173.194.34.1"
# Main router address
MAIN_ADDR="192.168.1.1"
# Primary router's own address
PRIMARY_ADDR="192.168.1.1"
# Address of the switch
SWITCH_ADDR="192.168.1.4"
# PID files
PID_FILE="/var/run/router-check"
# Activation file, used to keep track of state
ACTIVATION_FILE="/var/run/router-active"
# Library directory - where scripts reside
LIB_DIR="/usr/local/share/router-checks"
# Log file
LOG_FILE="/var/log/router-checks.log"

View file

@ -0,0 +1,73 @@
#!/bin/bash
(
. /etc/router-checks.conf
exec >>$LOG_FILE 2>&1
date
echo "... STARTING"
. "$LIB_DIR/pings"
echo $$ > $PID_FILE
stop_file="$PID_FILE.$$"
trap "rm -f $stop_file" SIGINT SIGTERM
touch $stop_file
SLEEP_TIME=60
while [ -f "$stop_file" ]; do
sleep $SLEEP_TIME
SLEEP_TIME=1
pr_switch=`mktemp`
pr_peer=`mktemp`
if [ -f "$ACTIVATION_FILE" ]; then
# When the secondary router is active, disable it if the
# internet is not reachable and either the primary router is
# up or the switch is down
pr_internet=`mktemp`
wait_pings `try_ping $INTERNET_ADDR $pr_internet` \
`try_ping $PRIMARY_ADDR $pr_peer` \
`try_ping $SWITCH_ADDR $pr_switch`
if [ -f "$pr_internet" ]; then
if [ -f "$pr_switch" ] || ! [ -f "$pr_peer" ]; then
date
echo "de-activating connection"
$LIB_DIR/deactivate.sh
rm -f "$ACTIVATION_FILE"
SLEEP_TIME=10
fi
fi
rm -f "$pr_internet"
else
# When the secondary router is inactive, enable it if the
# switch is up and both the primary router and the main address
# are unreachable
pr_main=`mktemp`
wait_pings `try_ping $SWITCH_ADDR $pr_switch` \
`try_ping $PRIMARY_ADDR $pr_peer` \
`try_ping $MAIN_ADDR $pr_main`
if [ -f "$pr_main" ] && [ -f "$pr_peer" ] && ! [ -f "$pr_switch" ]; then
date
echo "activating connection"
$LIB_DIR/activate.sh
touch "$ACTIVATION_FILE"
SLEEP_TIME=20
fi
rm -f "$pr_main"
fi
rm -f "$pr_peer" "$pr_switch"
done
if [ -f "$ACTIVATION_FILE" ]; then
$LIB_DIR/deactivate.sh
rm -f "$ACTIVATION_FILE"
fi
date
echo "... EXITING"
rm "$PID_FILE"
) &

15
routers/share/activate.sh Normal file
View file

@ -0,0 +1,15 @@
#!/bin/bash
#
# Example router activation script
#
# 1/ Remove default route through peer
# 2/ Take active router address
# 3/ Activate PPP link
# 4/ Wait for a few seconds
#
ip route del default via 192.168.1.1 dev eth0
ip addr add 192.168.1.1/24 dev eth0
ifup ppp0
sleep 10

View file

@ -0,0 +1,18 @@
#!/bin/bash
#
# Example router de-activation script
#
# 1/ Kill internet link
# 2/ Nuke them from orbit, it's the only way to be sure
# 3/ Release main router address
# 4/ Add default route through peer
#
ifdown --force ppp0
sleep 2
killall -9 pppd
sleep 2
ip addr del 192.168.1.1 dev eth0
ip route add default via 192.168.1.1 dev eth0

29
routers/share/pings Normal file
View file

@ -0,0 +1,29 @@
#!/bin/bash
try_ping()
{
export target="$1"
export prfile="$2"
export endfile=`mktemp`
(
if ping -c1 $target >/dev/null 2>&1; then
rm -f $prfile
fi
rm -f $endfile
) >/dev/null 2>&1 &
echo $endfile
}
wait_pings()
{
local ok=0
while [ "$ok" = "0" ]; do
sleep 1
ok=1
for file in $*; do
if [ -f "$file" ]; then
ok=0
fi
done
done
}