Router redundancy scripts
This commit is contained in:
parent
1cb97260ba
commit
7b0b2087b3
8 changed files with 356 additions and 0 deletions
66
routers/README
Normal file
66
routers/README
Normal 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
67
routers/init-script
Normal 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
63
routers/primary-router.sh
Normal 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"
|
||||
|
||||
) &
|
25
routers/router-checks.conf
Normal file
25
routers/router-checks.conf
Normal 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"
|
73
routers/secondary-router.sh
Normal file
73
routers/secondary-router.sh
Normal 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
15
routers/share/activate.sh
Normal 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
|
18
routers/share/deactivate.sh
Normal file
18
routers/share/deactivate.sh
Normal 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
29
routers/share/pings
Normal 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
|
||||
}
|
Loading…
Reference in a new issue