IpCop

Aus ConfigWiki
Wechseln zu: Navigation, Suche

IPCop ist eine Linuxdistribution für Router und Firewalls und ist erhältlich unter http://www.ipcop.org/ . Weitere allg. Informationen unter http://de.wikipedia.org/wiki/IPCop

Einrichtung mit dem Network-Manager

Für den Network-Manager muß das PKCS12-Zertifikat in 3 einzelne PEM-Zertifikate aufgeteilt werden:

p12to3pem.sh

#!/bin/bash

# p12to3pem.sh
# converts a IPCop-PKCS12-cert to 3 separate PEM-Certs

if [[ "${1##*.}" == "p12" && -f $1 ]]; then
    CERT=${1%.p12}
else
    echo "Usage $0 <p12-File>"
    exit 1
fi

echo "extract client cert:"
openssl pkcs12 -in $CERT.p12 -clcerts -nokeys -nodes -out $CERT-user.pem
echo "extract private key:"
openssl pkcs12 -in $CERT.p12 -nocerts -nodes -out $CERT-keys.pem
echo "extract CA cert:"
openssl pkcs12 -in $CERT.p12 -cacerts -nodes -out $CERT-ca.pem

Ausführliche Informationen sind im IPCop-Forum zu finden.

ipsec-watch

Im praktischen Einsatz ergab sich das Problem, daß dead-peer-detection bei den IPsec-VPN-Verbindungen nicht funktionierte. Zum Teil liegt das vermutlich auch an der Art des Internetzugangs.

Der 1. Router befindet sich hinter einem Kabelmodem, welches als Bridge arbeitet und dem IPCop die öffentliche IP durchreicht.
Der 2. Router befindet sich hinter einer FritzBox und hat eine private IP an RED.
Beide Router haben eine dynamische IP, die aber erst nach 14 Tagen geändert wird. (Kabel Deutschland)

Der 3. Router wählt sich via DSL-Modem selbst ein und erhält jeden Tag eine neue IP. (T-Com)

Nach der DSL-Neueinwahl mit Änderung der IP-Adresse werden die VPN-Verbindungen nicht neu initialisiert. Die genaue Ursache ist noch nicht ermittelt.

Da es sich um Netz-zu-Netz-VPNs handelt ist ein Monitoring via ping von den IPCops selbst nicht möglich. Ein externes Monitoring einer Maschine im Netz informiert per Mail über eine fehlende Verbindung. Ggf. kann von dort aus auch ein gezielter Neustart einzelner Verbindungen mit dedizierten ssh-Keys eingerichtet werden. Ziel ist es jedoch, daß die IPCops selbst den Fehler zu korrigieren.

Als Workaround wurde ein Shellskript geschrieben, welches regelmäßig kontrolliert, ob die Verbindungen in einem definierten Zustand sind und diese ggf. neu startet. Das Skript vergleicht die in der Konfigurationsdatei hinterlegten Verbindungen mit der Ausgabe von "ipsec eroute" ( -> $EROUTE). Der einzige als "garantiert bestehende Verbindung" bekannte Zustand ist "tun0x*@<IP>:0", wobei die IP der aktuell gültigen IP der Gegenstelle entsprechen muß. Letztere wird wiederum mit "host" aus dem FQDN der zugehörigen Verbindung aus der Config (Feld_12 -> $RIGHT) ermittelt. Die zugehörige Verbindung ergibt sich aus der Config (Feld_13 -> $RIGHTSUBNET_CFG) und $EROUTE (Feld_4 -> $RIGHTSUBNET), jeweils ab dem "/" um die in unterschiedlicher Schreibweise angegebene Subnetzmaske gekürzt. Feld_1 in der Config ist der jeweilige Verbindungsname (bzw. Nr.) für ipsecctrl. Damit kann die jeweilige Verbindung gezielt neugestartet werden.

Als fehlerhaft bekannt sind die Zustände:

  • "tun" + alte <IP>
  • "trap"
  • ggf. "hold"
#!/bin/bash

CONFIG='/var/ipcop/vpn/config'
EROUTE=$( ipsec eroute )

# pruefe alle aktiven Verbindungen ($2=on) aus CONFIG
while read CONN_NR CONN_NAME RIGHT RIGHTSUBNET_CFG; do

   # IP-Adresse aus Config-FQDN der Gegenstelle ermitteln
   read F1 F2 F3 RIGHT_IP F4 <<< $( host -t a $RIGHT )
   # ToDo: vorher pruefen, ob in CONFIG eine IP statt FQDN eingetragen wurde
   #       dann eruebrigt sich die Namensaufloesung
   #       BASH#IP-Validierung funktioniert nicht, =~ wird nicht akzeptiert

   # Werte zuruecksetzen
   CONN_STATE="-"

   # vergleichen, falls noch wenigstens 1 Verbindung steht
   if [ "$EROUTE" != "" ]; then
	# EROUTE zeilenweise verarbeiten
	while read P_COUNT LEFTSUBNET A1 RIGHTSUBNET A2 RAW_STATE; do
	    if [ "${RIGHTSUBNET_CFG%/*}" == "${RIGHTSUBNET%/*}" ] ; then
		CONN_STATE=${RAW_STATE%%0x*}          # alles ab 0x entfernen
		if [ "$CONN_STATE" == "tun" ]; then
	    	    # RAW_STATE = tun0x<NR>@<IP>:0
	    	    CONN_RIGHT=${RAW_STATE#*\@}       # alles bis zum @ entfernen
		    CONN_RIGHT_IP=${CONN_RIGHT%:*}    # alles ab : entfernen
		    if [ "$RIGHT_IP" != "$CONN_RIGHT_IP" ] ; then
			logger -p local0.warning -t ipcop "ipsec-watch restarting $CONN_NAME $RIGHT_IP $CONN_RIGHT_IP(IP changed)"
			/usr/local/bin/ipsecctrl S $CONN_NR
		    fi
		else
	    	    # RAW_STATE = %trap:0 || %hold:0 (oder war das bei hold anders?)
		    CONN_STATE=${RAW_STATE#%}         # % am Anfang entfernen
		    CONN_STATE=${CONN_STATE%:*}       # alles ab : entfernen
		    logger -p local0.warning -t ipcop "ipsec-watch restarting $CONN_NAME $RIGHT_IP (state = $CONN_STATE) $RAW_STATE"
		    /usr/local/bin/ipsecctrl S $CONN_NR
		fi
	    fi
	done <<< "$EROUTE"
   fi

   if [ "$CONN_STATE" == "-" ] ; then
	logger -p local0.warning -t ipcop "ipsec-watch restarting $CONN_NAME (connection down)"
	/usr/local/bin/ipsecctrl S $CONN_NR
   fi

done <<< "$( awk -F , '($2 == "on")  {printf "%s %s %s %s\n", $1, $3, $12, $13}' $CONFIG )"

Eintrag in der crontab (fcrontab -e):

*/2 * * * *     [ -x "/usr/local/bin/ipsec-watch" ] && /usr/local/bin/ipsec-watch >/dev/null 2>&1

schaut alle 2 Minuten nach dem Rechten. (ursprünglich aller 5 Minuten)

Festgestellt wurde, daß der (2.) Router mit der privaten IP an RED nach der DSL-Neueinwahl des 3. Routers die geänderte IP-Adresse nach 5 Minuten noch nicht bemerkt hat. Die Verbindung wurde erst mit dem 2. Neustart wieder aktiviert, also erst nach 10 Minuten. Der 1. Router war bereits nach dem 1. Versuch wieder im Normalzustand.

Zustand der VPNs nach der DSL-Neueinwahl: 1. Check (+5min):

  • 1 -> 2: nicht betroffen (wird nicht neugestartet)
  • 1 <- 2: nicht betroffen (wird nicht neugestartet)
  • 1 -> 3: Verbindung weg (kein eroute-Eintrag)
  • 1 <- 3: trap
  • 2 -> 3: tun -> alte IP
  • 2 <- 3: trap

2. Check (+10min):

  • 2 -> 3: Verbindung weg (kein eroute-Eintrag)
  • 2 <- 3: trap
Meine Werkzeuge