Eine neue Version des vpn-watch von Sven nachgeschoben.

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@621 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
This commit is contained in:
ms
2007-06-09 20:53:21 +00:00
parent 2b0b368950
commit 1d4b4bae1e

View File

@@ -1,239 +1,181 @@
#!/bin/sh #!/bin/sh
################################################## # IPsec startup and shutdown script
##### VPN-Watch.sh Version 1.6.3 ##### # Copyright (C) 1998, 1999, 2001 Henry Spencer.
################################################## # Copyright (C) 2002 Michael Richardson <mcr@freeswan.org>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is free software; you can redistribute it and/or modify it
# but WITHOUT ANY WARRANTY; without even the implied warranty of # under the terms of the GNU General Public License as published by the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # Free Software Foundation; either version 2 of the License, or (at your
# GNU General Public License for more details. # option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
# Written by: Daniel Berlin <daniel.berlin@itechnology.de>.
# Download: http://www.itechnology.de/front_content.php?idcat=87
# #
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# RCSID $Id: setup.in,v 1.122.6.3 2006/10/26 23:54:32 paul Exp $
#
# ipsec init.d script for starting and stopping
# the IPsec security subsystem (KLIPS and Pluto).
#
# This script becomes /etc/rc.d/init.d/ipsec (or possibly /etc/init.d/ipsec)
# and is also accessible as "ipsec setup" (the preferred route for human
# invocation).
#
# The startup and shutdown times are a difficult compromise (in particular,
# it is almost impossible to reconcile them with the insanely early/late
# times of NFS filesystem startup/shutdown). Startup is after startup of
# syslog and pcmcia support; shutdown is just before shutdown of syslog.
#
# chkconfig: 2345 47 76
# description: IPsec provides encrypted and authenticated communications; \
# KLIPS is the kernel half of it, Pluto is the user-level management daemon.
# changed by: R<>diger Sobeck me='ipsec setup' # for messages
# last changed: 31-01-2006
# Configuration # where the private directory and the config files are
# IPSEC_EXECDIR="${IPSEC_EXECDIR-/usr/libexec/ipsec}"
CHECK_INTERVAL='120' # Check this often (in seconds) IPSEC_LIBDIR="${IPSEC_LIBDIR-/usr/lib/ipsec}"
DNS_RESOLVE_TRIES='3' # Try to resolve IPs this often (each try takes max. 2 seconds) IPSEC_SBINDIR="${IPSEC_SBINDIR-/usr/sbin}"
NICENESS='+5' # Adjust niceness of child processes: '-20' ... '+19'; '0' is default IPSEC_CONFS="${IPSEC_CONFS-/etc}"
ipfire_VPN_CONFIG='/var/ipfire/vpn/config' # Location of ipfire's vpn configuration file
ipfire_VPN_SETTINGS='/var/ipfire/vpn/settings' # Location of ipfire's vpn settings file
VERSION='1.6.3'
# Workaround for nonexistent "nl" command on ipfire 1.4.x if test " $IPSEC_DIR" = " " # if we were not called by the ipsec command
nl --help >/dev/null 2>&1 then
if test $? -ne 0; then # we must establish a suitable PATH ourselves
alias nl='cat' PATH="${IPSEC_SBINDIR}":/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin
fi export PATH
MyHost=`grep VPN_IP /var/ipfire/vpn/settings | cut --delimiter='=' --output-delimiter=' ' -f2` IPSEC_DIR="$IPSEC_LIBDIR"
MyIP=`cat /var/ipfire/red/local-ipaddress` export IPSEC_DIR IPSEC_CONFS IPSEC_LIBDIR IPSEC_EXECDIR
MyDynDnsIP=`ping -c 1 "$1" 2>/dev/null | head -n1 | awk '{print $3}' | tr -d '()' | tr -d ':'` fi
case "$1" in # Check that the ipsec command is available.
'start' | '--start') found=
if test ! -r "$ipfire_VPN_CONFIG"; then for dir in `echo $PATH | tr ':' ' '`
echo 'Error: cannot read ipfire VPN configuration file; exit.' >&2 do
exit 1 if test -f $dir/ipsec -a -x $dir/ipsec
fi then
found=yes
break # NOTE BREAK OUT
fi
done
if ! test "$found"
then
echo "cannot find ipsec command -- \`$1' aborted" |
logger -s -p daemon.error -t ipsec_setup
exit 1
fi
mknod -m 0660 "/var/run/$(basename $0)" p >/dev/null 2>&1 # Create pipe for status-information # accept a few flags
# Read VPN configuration and fork a child process for each VPN connection export IPSEC_setupflags
# IPSEC_setupflags=""
while read line; do
VPN=($(echo $line | cut --delimiter=',' --output-delimiter=' ' -f1,2,3,5,6,12)) #
CONNR=${VPN[0]} # connection number
CONACTIVE=${VPN[1]} # active (on|off)
CONNAME=${VPN[2]} # connection name
CONTYPE=${VPN[3]} # connection type (host|net)
CONCERTPSK=${VPN[4]} # key type (cert|psk)
CONDNSNAME=${VPN[5]} # FQDN name of other side
echo -n "${CONACTIVE}" | grep -qi '^off$' && continue # Ignore: deactivated connections
echo -n "${CONTYPE}" | grep -qi '^host$' && continue # Ignore: Roadwarriors (->DPD)
# echo -n "${VPN[1]}${MyHost}" | grep -q '^[[:digit:]\.]\+$' && continue # Ignore: "left" and "right" side set to an IP
$0 'conn:' "${CONNAME}" "${MyHost}" "${CONDNSNAME}" "${CONNR}" >/dev/null 2>&1 & # Fork child process (parameters: "conn: NAME LEFT RIGHT NUMBER") config=""
echo -n 'S'
done < "$ipfire_VPN_CONFIG"
echo <20>"<22>Starte VPN-Watch"
exit 0 # Parent dies here... RIP
;;
'stop' | '--stop')
# Terminate processes
for proc in $(pidof -x -o %PPID $(basename $0)); do
kill -15 $proc
echo -n 'T'
done
sleep 1
# Kill remaining processes
for proc in $(pidof -x -o %PPID $(basename $0)); do
kill -9 $proc
echo -n 'K'
done
rm -f "/var/run/$(basename $0)" # Remove pipe
echo "Stoppe VPN-Watch"
exit 0
;;
'restart' | '--restart')
$0 stop
$0 start
exit 0
;;
'status' | '--status')
echo "VPN-Watch ${VERSION} (mail: daniel@itechnology.de, web: www.itechnology.de/vpn-watch)"
if ps --no-heading axw | grep -v 'grep' | grep -q "$(basename $0) conn: "; then
trap '' USR1
killall -q -g -s USR1 -- $(basename $0)
sleep 1
cat "/var/run/$(basename $0)" | sort | nl # Read children's info from pipe
else
echo ' no instances running.'
fi
exit 0
;;
'conn:')
# Children proceed here...
renice ${NICENESS:-0} -p $$ >/dev/null 2>&1 # Adjust niceness
shift # Remove the first positional parameter ("conn:"), as we don't need it anymore
;;
*)
echo "Usage: $0 { start | stop | restart | status }" >&2
exit 1
;;
esac
# Logging, signal handlers for dummy
# do
alias log="logger -t '$(basename $0 | cut -d '.' -f 1) ${VERSION}' \(${1}\)" case "$1" in
trap 'log "terminated after ${RESTART_COUNT} restarts."' EXIT --showonly|--show) IPSEC_setupflags="$1" ;;
trap 'echo "connection \"${1}\" restarted ${RESTART_COUNT} times" >>/var/run/$(basename $0)' USR1 --config) config="--config $2" ; shift ;;
*) break ;;
esac
shift
done
log "started"
# Get IP of a FQDN... using 'arp', 'traceroute' or 'ping', # Pick up IPsec configuration (until we have done this, successfully, we
# because ipfire has no 'nslookup', 'host' or 'dig' command. # do not know where errors should go, hence the explicit "daemon.error"s.)
# # Note the "--export", which exports the variables created.
function get_ip () { eval `ipsec _confread $config --optional --varprefix IPSEC --export --type config setup`
local RESULT=''
for ((i=1; ${i} <= ${DNS_RESOLVE_TRIES}; i++)); do
if which arp >/dev/null 2>&1; then
RESULT=$(arp "$1" 2>/dev/null | awk '{ print $2 }' | tr -d '()')
elif which traceroute >/dev/null 2>&1; then
RESULT=$(traceroute -m1 -q1 "$1" 2>/dev/null | head -n1 | awk '{ print $4 }' | tr -d '(),')
else
RESULT=$(ping -c 1 "$1" 2>/dev/null | head -n1 | awk '{print $3}' | tr -d '()' | tr -d ':')
fi
test -n "$RESULT" && break
done
test -z "$RESULT" && log "Warning: could not resolve ${1} after ${DNS_RESOLVE_TRIES} tries..."
echo -n "$RESULT"
}
function get_tunnelip () { if test " $IPSEC_confreadstatus" != " "
file=/var/tmp/$1.remoteip then
local TRESULT='' case $1 in
TVPN=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $2}'` stop|--stop|_autostop)
DYNHOST=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $12}'` echo "$IPSEC_confreadstatus -- \`$1' may not work" |
CONNR=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $1}'` logger -s -p daemon.error -t ipsec_setup;;
REMOTEIP=`/usr/bin/ping -c 1 "$DYNHOST" 2>/dev/null | head -n1 | awk '{print $3}' | tr -d '()' | tr -d ':'`
if ! test -f $file; then *) echo "$IPSEC_confreadstatus -- \`$1' aborted" |
cat $REMOTEIP > $file logger -s -p daemon.error -t ipsec_setup;
fi exit 1;;
OLDIP=`cat $file` esac
TUNIP=`ipsec whack --status | grep "$1"` fi
if [ "$TUNIP" != "" ]; then
TUNIP=`ipsec whack --status | grep "$1" | awk 'BEGIN{FS="["}{print $2}' | awk 'BEGIN{FS="---"}{print $3}'`
log "currently used tunnel IP = $TUNIP, current remote IP = $REMOTEIP"
echo $REMOTEIP > $file
TRESULT=${TUNIP}
fi
test -n "$TRESULT" && break IPSEC_confreadsection=${IPSEC_confreadsection:-setup}
test -z "$TRESULT" && log "Warning: could not retrieve last used VPN tunnel IP..." export IPSEC_confreadsection
echo -n "$TRESULT"
}
# Restarts a VPN connection IPSECsyslog=${IPSECsyslog-daemon.error}
# export IPSECsyslog
function restart_vpn () {
if test -x /usr/local/bin/ipsecctrl; then
/usr/local/bin/ipsecctrl D "$1" # This works for ipfire 1.4.x
/usr/local/bin/ipsecctrl R # re-read secrets
/usr/local/bin/ipsecctrl S "$1" # start tunnel
else
ipsec auto --down "$1" # This works for ipfire 1.3.x
ipsec auto --unroute "$1"
ipsec auto --delete "$1"
ipsec auto --rereadall
ipsec auto --add "$1"
ipsec auto --route "$1"
ipsec auto --up "$1"
fi
}
# Get left and right IP # misc setup
# umask 022
LEFT_IP_OLD=$MyIP
RIGHT_IP_OLD=$(get_ip $3)
# Infinite loop; checks, whether the IP of a left or right FQDN has changed. mkdir -p /var/run/pluto
# If so, the affected connection gets restarted; this is logged to syslog.
#
RESTART_COUNT=0
while :; do
sleep $CHECK_INTERVAL
# Skip check until IPSec is running
ipsec auto --status >/dev/null 2>&1 || continue
# get own IP (may have changed) # do it
ThisHostIP=`cat /var/ipfire/red/local-ipaddress` case "$1" in
start|--start|stop|--stop|_autostop|_autostart)
# this our own IP as reported in /var/ipfire/ppp/local-ipadress wanttodo=$1
LEFT_IP_NEW=$ThisHostIP if test " `id -u`" != " 0"
# check our own DYNDNS IP then
LEFT_IP_DYN=$(get_ip $MyHost) echo "permission denied (must be superuser)" |
# this is DYNDNS IP of other side logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
RIGHT_IP_NEW=$(get_ip $3) exit 1
# this the last used (right) IP for VPN-Tunnel fi
RIGHT_TUN_IP_OLD=$(get_tunnelip $1) tmp=/var/run/pluto/ipsec_setup.st
outtmp=/var/run/pluto/ipsec_setup.out
(
ipsec _realsetup $1
echo "$?" >$tmp
) > ${outtmp} 2>&1
st=$?
if test -f $tmp
then
st=`cat $tmp`
rm -f $tmp
fi
if [ -f ${outtmp} ]; then
cat ${outtmp} | logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
rm -f ${outtmp}
fi
if [ "$wanttodo" = "start" -o "$wanttodo" = "--start" -o "$wanttodo" = "_autostart" ]; then
sleep 20 && chown root:nobody /var/run/pluto -R && chmod 770 /var/run/pluto -R && ln -f /var/run/pluto/pluto.pid /var/run/pluto.pid 2>&1 &
fi
exit $st
;;
# for whatever reason, ipsec did not notice our own IP has changed for this connection restart|--restart|force-reload)
if [ "${LEFT_IP_NEW}" != "${LEFT_IP_DYN}" ]; then $0 $IPSEC_setupflags stop
restart_vpn "$4" $0 $IPSEC_setupflags start
let RESTART_COUNT++ ;;
log "Red IP = $LEFT_IP_NEW, IP by DynDNS = $LEFT_IP_DYN"
log 'incorrect dynamic IP in tunnel used: restarting connection...'
fi
# left or right IP has changed...
if test "${LEFT_IP_OLD} ${RIGHT_IP_OLD}" != "${LEFT_IP_NEW} ${RIGHT_IP_NEW}"; then
restart_vpn "$4"
let RESTART_COUNT++
log 'left or right IP has changed: restarting connection...'
fi
# right IP / IP of tunnel endpoint has changed... _autorestart) # for internal use only
if [ "$RIGHT_TUN_IP_OLD" != "" ]; then $0 $IPSEC_setupflags _autostop
if test "${RIGHT_TUN_IP_OLD}" != "${RIGHT_IP_NEW}"; then $0 $IPSEC_setupflags _autostart
restart_vpn "$4" ;;
let RESTART_COUNT++
log 'VPN tunnel IP has changed: restarting connection...'
fi
fi
LEFT_IP_OLD=$LEFT_IP_NEW status|--status)
RIGHT_IP_OLD=$RIGHT_IP_NEW ipsec _realsetup $1
done exit
;;
--version)
echo "$me $IPSEC_VERSION"
exit 0
;;
--help)
echo "Usage: $me [ --showonly ] {--start|--stop|--restart}"
echo " $me --status"
exit 0
;;
*)
echo "Usage: $me [ --showonly ] {--start|--stop|--restart}"
echo " $me --status"
exit 2
esac
exit 0