]>
git.ipfire.org Git - ipfire-2.x.git/blob - src/scripts/vpn-watch
2 ##################################################
3 ##### VPN-Watch.sh Version 1.6.3 #####
4 ##################################################
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2, or (at your option)
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # Written by: Daniel Berlin <daniel.berlin@itechnology.de>.
17 # Download: http://www.itechnology.de/front_content.php?idcat=87
20 # changed by: Rüdiger Sobeck
21 # last changed: 31-01-2006
25 CHECK_INTERVAL
='120' # Check this often (in seconds)
26 DNS_RESOLVE_TRIES
='3' # Try to resolve IPs this often (each try takes max. 2 seconds)
27 NICENESS
='+5' # Adjust niceness of child processes: '-20' ... '+19'; '0' is default
28 ipfire_VPN_CONFIG
='/var/ipfire/vpn/config' # Location of ipfire's vpn configuration file
29 ipfire_VPN_SETTINGS
='/var/ipfire/vpn/settings' # Location of ipfire's vpn settings file
32 # Workaround for nonexistent "nl" command on ipfire 1.4.x
33 nl --help >/dev
/null
2>&1
34 if test $?
-ne 0; then
38 MyHost
=`grep VPN_IP /var/ipfire/vpn/settings | cut --delimiter='=' --output-delimiter=' ' -f2`
39 MyIP
=`cat /var/ipfire/red/local-ipaddress`
40 MyDynDnsIP
=`ping -c 1 "$1" 2>/dev/null | head -n1 | awk '{print $3}' | tr -d '()' | tr -d ':'`
44 if test ! -r "$ipfire_VPN_CONFIG"; then
45 echo 'Error: cannot read ipfire VPN configuration file; exit.' >&2
49 mknod
-m 0660 "/var/run/$(basename $0)" p
>/dev
/null
2>&1 # Create pipe for status-information
51 # Read VPN configuration and fork a child process for each VPN connection
54 VPN
=($
(echo $line | cut
--delimiter=',' --output-delimiter=' ' -f1,2,3,5,6,12)) #
55 CONNR
=${VPN[0]} # connection number
56 CONACTIVE
=${VPN[1]} # active (on|off)
57 CONNAME
=${VPN[2]} # connection name
58 CONTYPE
=${VPN[3]} # connection type (host|net)
59 CONCERTPSK
=${VPN[4]} # key type (cert|psk)
60 CONDNSNAME
=${VPN[5]} # FQDN name of other side
62 echo -n "${CONACTIVE}" |
grep -qi '^off$' && continue # Ignore: deactivated connections
63 echo -n "${CONTYPE}" |
grep -qi '^host$' && continue # Ignore: Roadwarriors (->DPD)
64 # echo -n "${VPN[1]}${MyHost}" | grep -q '^[[:digit:]\.]\+$' && continue # Ignore: "left" and "right" side set to an IP
66 $0 'conn:' "${CONNAME}" "${MyHost}" "${CONDNSNAME}" "${CONNR}" >/dev
/null
2>&1 & # Fork child process (parameters: "conn: NAME LEFT RIGHT NUMBER")
68 done < "$ipfire_VPN_CONFIG"
69 echo Â
"ÂStarte VPN-Watch"
70 exit 0 # Parent dies here... RIP
74 for proc
in $
(pidof
-x -o %PPID $
(basename $0)); do
79 # Kill remaining processes
80 for proc
in $
(pidof
-x -o %PPID $
(basename $0)); do
84 rm -f "/var/run/$(basename $0)" # Remove pipe
85 echo "Stoppe VPN-Watch"
88 'restart' |
'--restart')
93 'status' |
'--status')
94 echo "VPN-Watch ${VERSION} (mail: daniel@itechnology.de, web: www.itechnology.de/vpn-watch)"
95 if ps
--no-heading axw |
grep -v 'grep' |
grep -q "$(basename $0) conn: "; then
97 killall
-q -g -s USR1
-- $
(basename $0)
99 cat "/var/run/$(basename $0)" |
sort |
nl # Read children's info from pipe
101 echo ' no instances running.'
106 # Children proceed here...
107 renice
${NICENESS:-0} -p $$
>/dev
/null
2>&1 # Adjust niceness
108 shift # Remove the first positional parameter ("conn:"), as we don't need it anymore
111 echo "Usage: $0 { start | stop | restart | status }" >&2
116 # Logging, signal handlers
118 alias log
="logger -t '$(basename $0 | cut -d '.' -f 1) ${VERSION}' \(${1}\)"
119 trap 'log "terminated after ${RESTART_COUNT} restarts."' EXIT
120 trap 'echo "connection \"${1}\" restarted ${RESTART_COUNT} times" >>/var/run/$(basename $0)' USR1
124 # Get IP of a FQDN... using 'arp', 'traceroute' or 'ping',
125 # because ipfire has no 'nslookup', 'host' or 'dig' command.
129 for ((i
=1; ${i} <= ${DNS_RESOLVE_TRIES}; i
++)); do
130 if which arp
>/dev
/null
2>&1; then
131 RESULT
=$
(arp
"$1" 2>/dev
/null |
awk '{ print $2 }' |
tr -d '()')
132 elif which traceroute >/dev
/null
2>&1; then
133 RESULT
=$
(traceroute -m1 -q1 "$1" 2>/dev
/null |
head -n1 |
awk '{ print $4 }' |
tr -d '(),')
135 RESULT
=$
(ping -c 1 "$1" 2>/dev
/null |
head -n1 |
awk '{print $3}' |
tr -d '()' |
tr -d ':')
137 test -n "$RESULT" && break
139 test -z "$RESULT" && log
"Warning: could not resolve ${1} after ${DNS_RESOLVE_TRIES} tries..."
143 function get_tunnelip
() {
144 file=/var
/tmp
/$1.remoteip
146 TVPN
=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $2}'`
147 DYNHOST
=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $12}'`
148 CONNR
=`grep "$1" /var/ipfire/vpn/config| awk 'BEGIN{FS=","}{print $1}'`
149 REMOTEIP
=`/usr/bin/ping -c 1 "$DYNHOST" 2>/dev/null | head -n1 | awk '{print $3}' | tr -d '()' | tr -d ':'`
150 if ! test -f $file; then
151 cat $REMOTEIP > $file
154 TUNIP
=`ipsec whack --status | grep "$1"`
155 if [ "$TUNIP" != "" ]; then
156 TUNIP
=`ipsec whack --status | grep "$1" | awk 'BEGIN{FS="["}{print $2}' | awk 'BEGIN{FS="---"}{print $3}'`
157 log
"currently used tunnel IP = $TUNIP, current remote IP = $REMOTEIP"
158 echo $REMOTEIP > $file
162 test -n "$TRESULT" && break
163 test -z "$TRESULT" && log
"Warning: could not retrieve last used VPN tunnel IP..."
167 # Restarts a VPN connection
169 function restart_vpn
() {
170 if test -x /usr
/local
/bin
/ipsecctrl
; then
171 /usr
/local
/bin
/ipsecctrl D
"$1" # This works for ipfire 1.4.x
172 /usr
/local
/bin
/ipsecctrl R
# re-read secrets
173 /usr
/local
/bin
/ipsecctrl S
"$1" # start tunnel
175 ipsec auto
--down "$1" # This works for ipfire 1.3.x
176 ipsec auto
--unroute "$1"
177 ipsec auto
--delete "$1"
178 ipsec auto
--rereadall
179 ipsec auto
--add "$1"
180 ipsec auto
--route "$1"
185 # Get left and right IP
188 RIGHT_IP_OLD
=$
(get_ip
$3)
190 # Infinite loop; checks, whether the IP of a left or right FQDN has changed.
191 # If so, the affected connection gets restarted; this is logged to syslog.
195 sleep $CHECK_INTERVAL
197 # Skip check until IPSec is running
198 ipsec auto
--status >/dev
/null
2>&1 ||
continue
200 # get own IP (may have changed)
201 ThisHostIP
=`cat /var/ipfire/red/local-ipaddress`
203 # this our own IP as reported in /var/ipfire/ppp/local-ipadress
204 LEFT_IP_NEW
=$ThisHostIP
205 # check our own DYNDNS IP
206 LEFT_IP_DYN
=$
(get_ip
$MyHost)
207 # this is DYNDNS IP of other side
208 RIGHT_IP_NEW
=$
(get_ip
$3)
209 # this the last used (right) IP for VPN-Tunnel
210 RIGHT_TUN_IP_OLD
=$
(get_tunnelip
$1)
212 # for whatever reason, ipsec did not notice our own IP has changed for this connection
213 if [ "${LEFT_IP_NEW}" != "${LEFT_IP_DYN}" ]; then
216 log
"Red IP = $LEFT_IP_NEW, IP by DynDNS = $LEFT_IP_DYN"
217 log
'incorrect dynamic IP in tunnel used: restarting connection...'
220 # left or right IP has changed...
221 if test "${LEFT_IP_OLD} ${RIGHT_IP_OLD}" != "${LEFT_IP_NEW} ${RIGHT_IP_NEW}"; then
224 log
'left or right IP has changed: restarting connection...'
227 # right IP / IP of tunnel endpoint has changed...
228 if [ "$RIGHT_TUN_IP_OLD" != "" ]; then
229 if test "${RIGHT_TUN_IP_OLD}" != "${RIGHT_IP_NEW}"; then
232 log
'VPN tunnel IP has changed: restarting connection...'
236 LEFT_IP_OLD
=$LEFT_IP_NEW
237 RIGHT_IP_OLD
=$RIGHT_IP_NEW