Hola muy buenas

hoy os pongo un pequeño script que he tuneado (muy poco también es cierto) para chequear el estado de un túnel IPSEC establecido con un firewall pfSense y en caso de estar caído, reiniciar el túnel.

Me ha pasado que tengo unos túneles establecidos con el pfSense contra diversos Cisco y a veces , sin saber muy bien por qué, se caen. Así que después de varias pruebas, he decidido monitorizar el estado del túnel y reiniciarlo si está caído.

El script original está en

https://wiki.strongswan.org/attachments/314/ipsec-monitor.sh

En mi caso, he cambiado para que en lugar de utilizar el comando NC , pues me utilizara un ping. Por alguna razón el comando NC no me estaba funcionando bien.

El código completo es

#!/usr/local/bin/bash

function main()
{
local SLEEP_SECONDS=60
while [[ 0 == 0 ]]; do
monitor_from_file $*
sleep $SLEEP_SECONDS
done
}

function monitor_vpn_ip_port()
{
local CONN_NAME=$1
local IP=$2
local PORT=$3

ping -S 192.168.2.1 -c1 -W5 $IP || ( \
echo “$IP $PORT did not respond, resetting connection $CONN_NAME”; \
ipsec down $CONN_NAME; ipsec up $CONN_NAME; )
}

function monitor_from_file()
{
local FILE=$1
if [[ ! -e $FILE ]]; then
echo “Can not find file $FILE.”
return 1
fi

# load the file into memory. Hope it’s not too big. 🙂
# -t strips out the newlines on each line.
mapfile -t MYARRAY < $FILE
# init local variable to contain the current connection name.
local CONN=
for LINE in “${MYARRAY[@]}”; do
# Skip over any lines that have the comment at the very beginning.
# if [[ $LINE =~ ^\# ]]; then continue

# Look for a line that looks like this which defines a VPN connection:
# conn CONNECTION-NAME
if [[ $LINE =~ ^conn[\ ] ]]; then
# extract the part after the “conn ” to get the name.
CONN=`echo $LINE | sed ‘s/^conn //’`

# Look for a line where we have the commented ‘monitor’ keyword.
# Example: #monitor 172.17.105.80 9898
elif [[ $LINE =~ \#monitor ]]; then
# Remove everything from the beginning up to and including the “#monitor ”
IP_PORT=`echo $LINE | sed ‘s/^.*#monitor //’`
printf “`date` monitoring $CONN \t $IP_PORT\n”
# IP_PORT should be space delimited and hence should work as separate parameters.
monitor_vpn_ip_port $CONN $IP_PORT

# if we have a blank line, that ends any connection configuration.
elif [[ $LINE =~ ^$ ]]; then
CONN=
fi
done
}

# now start running the script by calling main() with all parameters.
main $*

Adicionalmente, hay que poner en un fichero, las direcciones IP que quieras monitorizar y el nombre de la conexión que quieras resetear en caso necesario. En mi caso el fichero es así:

conn con11000
#monitor 192.168.168.250
conn con5000
#monitor 192.168.169.250

Tengo 2 conexiones a monitorizar, que se llaman con11000 y con5000 (estos nombres se pueden ver en /var/etc/ipsec/ipsec.conf) , y quiero ver si están vivas las maquinas 192.168.168.250 para la con11000 y 192.168.169.250 para la con5000. Aquí podéis poner tantas conexiones como queráis , precedidas de la palabra conn y luego con el #monitor la ip de esa conexión que servirá para verificar si la conexión está funcionando o no.

Luego para llamar al monitor es simplemente ejecutar “./ipsec_monitor.sh <nombre-fichero-donde-esten-las-ip-a-monitorizar>”, por ejemplo “./ipsec_monitor.sh vpn.txt”

El script se ejecuta cada 60 segundos, y eso lo podéis controlar con la variable SLEEP_SECONDS. También podéis quitarla y meterlo en un cron o ajustarlo a conveniencia 🙂

Suerte!