IPsec Verbindung mittels strongSwan und
RSA Schlüsseln + EAP-MSCHAPv2 Authentifizierung
unter Debian jessie mit strongSwan 5.2.1 und easy-rsa 2.2.2 Date: 22.11.2016
Mögliche Verbindungen:

PC (Server) === Router (Fritzbox) === Internet === Client: Android/Laptop

PC (Server) === Router === Internet === Router === Client: Android/Laptop
 

IPsec (Kurzform für Internet Protocol Security) ist eine Protokoll-Suite, die eine gesicherte Kommunikation über potentiell unsichere IP-Netze wie das Internet ermöglicht. IPsec kann zum Aufbau virtueller privater Netzwerke (VPN) verwendet werden. Ich gehe hier auf die grundlegenden Dinge wie z.B. was ist IPsec, was ist ein Diffie-Hellman-Schlüsselaustausch oder was ist EAP-MSCHAPv2 nicht ein. Wer mehr darüber erfahren will, kann alle nötigen grundlegenden Informationen bei Wikipedia Stichwort IPsec nachlesen. Lediglich das Thema RSA Schlüssel werde ich ein wenig ausführlicher behandeln, da zwar die theoretischen Grundlagen auch bei Wikipedia nachlesbar sind, die praktische Umsetzung aber fehlt. Sozusagen möchte ich hier eine kleine Brücke zwischen Theorie und Praxis schlagen, welche ich schmerzlich im Internet vermisst habe.

Grundlegendes zu Schlüsseln und Zertifikaten

Das RSA-Kryptosystem (benannt nach den Nachnamen der Entwickler Rivest, Shamir und Adleman) ist ein asymmetrisches kryptographisches Verfahren, das sowohl zum Verschlüsseln als auch zum digitalen Signieren verwendet wird. Es verwendet ein Schlüsselpaar, bestehend aus einem privaten Schlüssel, der zum Entschlüsseln oder Signieren von Daten verwendet wird, und einem öffentlichen Schlüssel, mit dem man verschlüsselt oder Signaturen prüft. Der private Schlüssel wird geheim gehalten und kann nur mit extrem hohem Aufwand aus dem öffentlichen Schlüssel berechnet werden.

In der Praxis geht das so: Man hat zwei Dateien, eine private Schlüssel-Datei, nennen wir sie mal user.key und eine Zertifikats-Datei, nennen wir sie mal user.crt. Die Zertifikats-Datei user.crt enthält auch den öffentlichen Schlüssel. Der private Schlüssel (private Key) ist der geheime Teil und sollte nie in fremde Hände gelangen. In dem Sinne sollte er nie den hoffentlich sicheren Rechner verlassen, denn er ist dazu da um die verschlüsselten Informationen wieder zu entschüsseln. Der öffentliche Schlüssel (public Key, enthalten in unserer Zertifikats-Datei) ist die Datei die über ein unsicheres Netzwerk wie z.B. das Internet weiter gegeben werden kann. Obwohl der öffentliche Schlüssel aus dem privaten berechnet wird, ist es mit heutigen technischen Mitteln und einer starken Verschlüsselung vorrausgesetzt nicht möglich aus dem öffentlichen Schlüssel den privaten zurück zu berechnen, daher nennt man dieses Verfahren auch Einwegfunktion. Beispielsweise ist nach aktuellem Wissensstand die Faktorisierung einer großen Zahl, also ihre Zerlegung in ihre Primfaktoren, sehr aufwändig, während das Erzeugen einer Zahl durch Multiplikation von Primzahlen recht einfach und schnell möglich ist. Spezielle Einwegfunktionen sind Falltürfunktionen (engl. trapdoor one-way function), die mit Hilfe einer Zusatzinformation auch rückwärts leicht zu berechnen sind. Die Einwegeigenschaft begründet, warum die Entschlüsselung (bzw. das Signieren) ohne den geheimen Schlüssel (die Falltür) schwierig ist.

Veranschaulichen wir das Anhand eines Beispiels in der Praxis: User Bob hat ein Schlüsselpaar, bestehend aus seinem eigenen privaten Schlüssel bob.key und dem öffentlichen Schlüssel mit Zertifikat bob.crt. Möchte er nun eine verschlüsselte Nachricht von User Dave erhalten, schickt er ihm über das Internet seinen öffentlichen Schlüssel bob.crt. Mit Hilfe des öffentlichen Schlüssels kann Dave die Nachricht verschüsseln. Nach Verschüsselung der Nachricht kann nur noch Bob sie mit seinem privaten Schlüssel entschlüsseln. Nicht einmal der Verschlüsseler selbst, also Dave kann sie noch lesen oder wieder in Klartext verwandeln um noch etwas zu ändern. Dabei stört es nicht, daß der öffentliche Schlüssel über ein solch unsicheres Medium wie das Internet verschickt wird, da er ja lediglich zum Verschüsseln da ist und durch ihn auch keinerlei Rückschlüsse auf den privaten Schlüssel hergestellt werden können. Nur der private Schlüssel kann die Nachricht wieder in Klartext verwandeln. Hier sieht man wie wichtig die Geheimhaltung des privaten Schlüssels ist.

Zusätzlich zur Verschlüsselung von Nachrichten werden diese auch signiert um sicherzustellen, daß die Nachricht vom Absender ist und nicht auf ihrem Weg verfälscht wurde. Um eine Nachricht zu signieren, wird vom Sender auf die Nachricht die RSA-Funktion mit dem eigenen privaten Schlüssel angewendet. Zum Prüfen wendet der Empfänger auf die Signatur mit Hilfe des öffentlichen Schlüssels des Senders die Umkehrfunktion an und vergleicht diese mit der zusätzlich übermittelten unverschlüsselten Nachricht. Wenn beide übereinstimmen, ist die Signatur gültig und der Empfänger kann sicher sein, dass derjenige, der das Dokument signiert hat, auch den privaten Schlüssel besitzt und dass niemand seit der Signierung das Dokument geändert hat. Es wird also die Integrität und Authentizität garantiert.

Was hat es nun mit dem Zertifikat auf sich? Ein digitales Zertifikat ist ein digitaler Datensatz, der bestimmte Eigenschaften von Personen oder Objekten bestätigt und dessen Authentizität und Integrität durch kryptografische Verfahren überprüft. Das digitale Zertifikat enthält insbesondere die zu seiner Prüfung erforderlichen Daten. Die Ausstellung des Zertifikats erfolgt i.d. Regel durch eine offizielle Zertifizierungsstelle, die Certification Authority (CA).

Schlüssel- und Zertifikats-Dateien

In der Praxis bedeutet das, man braucht immer 3 Dateien für RSA.
user.key   -- der private Schlüssel der geheim gehalten werden sollte.
user.crt-- der öffentliche Schlüssel mit Zertifikat.
ca.crt-- das Zertifikat der offiziellen Zertifizierungsstelle.

Zertifikate gibt es in zwei unterschiedlichen Versionen, als Text und Binär. Die Endung sagt nicht unbedingt etwas über den Inhalt aus. Ein binäres DER Format kann auch neben der Endung .der die Endung .cer oder .crt haben. Trotzdem unterscheidet man:

  • .DER = binäres Format, Endung i.d. Regel .der, kann aber auch .cer oder .crt haben.
  • .PEM = Die PEM Erweiterung wird benutzt für X.509v3 Files, welche Daten in ASCII (Base64) encodiert enthalten und mit einer “—– BEGIN …” Linie beginnen.

Übliche Datei-Endungen:

  • .CRT = Die CRT Erweiterung wird für Zertifikate benutzt. Zertifikate können binär im DER Format oder als ASCII Text im PEM Format gespeichert sein. Die Endungen CER und CRT sind nahezu gleich.
  • .CER = Alternative Form von .crt (Microsoft Convention). Man kann MS benutzen um .crt zu .cer zu konvertieren.
  • .KEY = Die KEY Erweiterung wird für private und öffentliche Schlüssel nach PKCS#8 benutzt. Schlüssel können sowohl binär als DER oder auch als ASCII PEM gespeichert werden.

Betrachten kann man ein Zertifikat mit dem openssl Befehl:
# openssl x509 -in ca.crt -text -noout                          # für Text Zertifikate
# openssl x509 -in ca.der -inform der -text -noout   # für Binäre Zertifikate

Um Zertifikate zu konvertieren, hilft ebenfalls der openssl-Befehl:
PEM zu DER
# openssl x509 -in cert.crt -outform der -out cert.der
DER zu PEM
# openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

Außerdem kann man mehrere Zertifikate in einem Archiv zusammenfassen, um sie beispielsweise an einen Clienten zu schicken. Dazu benutzt man am Besten das PKCS#12 oder PFX Format.
# openssl pkcs12 -export -inkey clientname.key -in clientname.crt -name "Udo's Certificate" -certfile ca.crt -out client_zertifikat.pfx
oder auch
# openssl pkcs12 -export -inkey clientnameKey.pem \
-in clientnameCert.pem -name "Udo's Certificate" \
-certfile caCert.pem \
-caname "strongSwan Root CA" \
-out client_zertifikat.p12

In diesem Format wird das Zertifikat zusammen mit dem Privatschlüssel und beziehungsweise mit anderen Zertifikaten in Chain gespeichert. In einer Datei ist also alles gespeichert, was für den Betrieb des Zertifikats benötigt wird. Es handelt sich um das Binär-Format, welches besonders auf dem Windows- und Microsoft-Server verwendet wird. Das typische Suffix ist .pfx oder .p12.


1. Eigene Schlüssel und Zertifikate mit easy-rsa generieren

Genug der Vorrede, jetzt legen wir los. Natürlich hat nicht jeder als Privatmann eine offizielle Zertifizierungsstelle zur Hand, da so etwas ja Geld kostet und sich daher eher für Firmen eignet. Glücklicherweise kann man seine eigene Zertifizierungsstelle mit ein paar einfachen Schritten und der Hilfe von easy-rsa selbst erstellen. easy-rsa ist eine Sammlung von Shell-Skripten, welche die Erstellung von Zertifikaten sehr einfach machen. Dazu installieren wir zuerst einmal das Paket easy-rsa:
# apt-get install easy-rsa
Anschließend erstellen wir unter /etc/ ein Verzeichnis namens easy-rsa:
# mkdir /etc/easy-rsa
In dieses Verzeichnis kopieren wir nun sämtliche Dateien von der easy-rsa Paket-Installation:
# cp -v /usr/share/easy-rsa/* /etc/easy-rsa/
Normalerweise sollte der Ordner keys/, in welchem später unsere erstellten Schlüssel liegen, automatisch erstellt werden. Anscheinend gab es in der Vergangenheit Probleme mit der Automatik, daher ist es besser man erstellt den Ordner vorab selbst:
# mkdir /etc/easy-rsa/keys/
Jetzt wechseln wir in das Verzeichnis easy-rsa und editieren zuerst die Variablen-Datei, damit wir Standardwerte für den gewünschten Namen haben.
# cd /etc/easy-rsa/
# nano vars

In der Variablen-Datei kann man nützliche Dinge einstellen, wie z.B. die verwendete Schlüssel-Größe export KEY_SIZE=2048. Hier empfiehlt sich kein kleinerer Wert als 2048, da Schlüssel mit einer Länge von 1024 mittlerweile als zu unsicher eingestuft werden. Auch interessant sind export CA_EXPIRE=3650 und export KEY_EXPIRE=3650, welche die Anzahl Tage definiert, in denen ein Zertifikat gültig ist. Erster Eintrag steht für die Zertifizierungsstelle selbst und der zweite Eintrag für die Lebensdauer der Schlüssel. Hier 3650 Tage, was 10 Jahre bedeutet. Dann kommen die Default-Werte für unsere Namensangaben:
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"
# X509 Subject Field
export KEY_NAME="EasyRSA"

Hat man alle Einstellungen getätigt und die Datei gespeichert, ruft man die Datei mit folgendem Befehl auf:
# . ./vars   # setzt die Umgebungs-Variablen
Natürlich sind die gesetzten Variablen nach dem nächsten Neustart wieder verschwunden. Möchte man zu einem späteren Zeitpunkt weitere Zertifikate erstellen, muß man die Variablen mit einem erneutem Aufruf der Datei wieder neu setzen. Anschließend führt man folgenden Befehl aus um eventuell früher erstellte Zertifikate zu löschen:
# ./clean-all

Damit hat man seine eigene Zertifizierungs-Stelle (CA) gebaut. Als allerersten Schritt wird ein Key für diese Zertifizierungs-Stelle erstellt, mit welchem man berechtigt ist, weitere Keys und Zertifikate für Server und Clienten zu erstellen. Ist man ganz Paranoid, sollte man diesen Key auf einem vom Netz abgetrennten Rechner erstellen und anschließend auf einen verschlüsselten USB-Stick speichern. Allerdings muß ich sagen, für unser kleines privates Vorhaben, eine Verbindung zum eigenen Rechner aufzubauen, ist das weit übertrieben, denn von der Logik her: Wenn es jemand schafft auf den Rechner zu gelangen um den CA-Key zu stehlen, macht es dann Sinn weitere Zertifikate zu erstellen damit man auf den Rechner zugreifen kann auf dem man sowieso schon ist? Macht keinen Sinn, aber ich bin kein Hacker, vielleicht überseh ich da auch ein Detail.
Trotzdem sollte man natürlich mit diesem Key vorsichtig sein, denn fällt er in fremde Hände, kann jemand damit beliebig viele Keys für das Eigene System erstellen. Als zusätzliche Sicherheit könnte man den CA-Key auch mit einem Paßwort schützen.
Der Befehl
# ./build-ca
erstellt den Key und das Zertifikat der CA-Stelle. Als Ergebnis erhält man zwei Files: ca.crt und ca.key im keys-Verzeichnis. Nochmal zur Übersicht:

  • Das ca.key File ist der vertrauliche Key und sollte geheim gehalten werden.
  • Das ca.crt File ist das Zertifikat und kann über unsichere Kanäle wie Plain-Text E-Mail weiter gegeben werden.
  • Das ca.key File muß nicht und sollte auch nicht von Computer zu Computer weiter kopiert werden.
  • Jeder Computer erhält sein eigenes Zertifikat/Key Paar.
Anschließend kann man weitere Keys und Zertifikate für den Server und Clients (Roadwarriors) erstellen. Für den Server ruft man dazu folgendes Skript auf:
# ./build-key-server servername
Zuerst wird der Key erstellt. Anschließend wird ein Zertifikat angefordert, welches durch unsere Zertifikatsstelle (CA) beglaubigt wird. Bei der Paßwort-Abfrage für ein challenge-Paßwort sollte man keines vergeben, da es für einen selbst keinen Sinn macht. Es ist lediglich für eine externe Zertifikats-Stelle, welche Anhand des Paßworts überprüft, ob man berechtigt ist, ein Zertifikat signiert zu bekommen.
Üblicherweise läuft das ganze so ab:
  1. Ein Benutzer benötigt ein Zertifikat. Er erzeugt ein Private + Public Key Paar.
  2. Der Benutzer packt Informationen über seine Entität (Common Name, Organization, Location, ...) zusammen mit seinem Public Key in ein Certificate Signing Request (CSR).
  3. Der Benutzer schickt das CSR an die Certificate Authority (CA), welche die Daten prüft.
  4. Die CA signiert das CSR. Dadurch entsteht das Zertifikat.
  5. Die CA schickt das Zertifikat an den Benutzer, welcher es verwenden kann.
Das challenge password ist lediglich ein Extrafeld im CSR das eventuell von der CA verlangt wird. So kann sichergestellt werden, dass nur der richtige Benutzer ein Zertifikat beantragt. Wirklich sicher ist das aber nicht.
Aufpassen muß man wenn bei den Namenseingaben ein Hinweis steht: Hostname des Servers, denn dann sollte man den tatsächlichen Hostnamen auch angeben, da strongSwan sonst eventuell eine Verbindung verweigert. Im Falle einer DynDNS Adresse muß diese hier eingetragen werden.
Nach Beendigung des Skripts erhält man zwei Dateien im keys-Verzeichnis: Das Zertifikat (servername.crt) und den Key (servername.key).

Anschließend erstellt man Schlüssel und Zertifikate für ein oder mehrere Clienten:
# ./build-key clientname             # ohne Passwort
# ./build-key-pass clientname   # mit Passwort
Das generiert die drei Files: clientname.crt, clientname.csr und clientname.key.
Zwei davon müssen dann später zusammen mit der ca.crt auf einen Client-PC transferiert werden. Natürlich ist mit dem private Key des Clienten vorsicht geboten, dieser sollte natürlich nicht in fremde Hände fallen. Hat man keine Möglichkeit ihm diesen per USB-Stick persönlich zu überreichen oder einen sicheren Kanal wie eine ssh-Verbindung für einen Dateitransfer zu benutzen, sollte man ihn zumindest mit einem ausreichend langen und komplizierten Paßwort versehen. So ist er zumindest durch das Paßwort vor fremden Händen geschützt. Manche werden jetzt sagen, aber halt mal, ich dachte private Keys sollten niemals den Rechner verlassen? Ja, das ist korrekt, aber normalerweise werden die private Keys auch auf den entsprechenden Client-PCs generiert und -wie etwas weiter oben zu lesen war- der public Key mit einer Zertifizierungs-Anfrage an die CA geschickt. Durch die Erstellung aller Schlüssel auf demselben Rechner umgehen wir diesen für private Zwecke etwas zu aufwändigen Zwischenschritt.

Zum Schluß kann man noch die DIFFIE-HELLMAN PARAMETERS (falls notwendig für den Server für eine SSL/TLS Verbindung) mit folgenden Skript erstellen lassen:
# ./build-dh
Die Erstellung dauert eine Weile (1-2 Minuten). Man erhält die Datei dh2048.pem im keys-Verzeichnis.

Für den Versand und anschließendem Import auf einem Android Smartphone empfiehlt es sich auf jedenfall die Client-Files in ein PKCS#12 oder PFX Format zu verpacken.
# openssl pkcs12 -export -inkey clientname.key -in clientname.crt -name "Udo's Certificate" -certfile ca.crt -out client_files.p12

Nochmal eine Zusammenfassung, wo welches File hingehört:

ca.key - dient zum Erstellen von neuen Schlüsseln und Zertifikaten, ist also der Schlüssel für unsere Key-Factory und sollte entweder gelöscht werden oder an einem sehr sicheren Ort (verschlüsselter USB-Stick) aufbewahrt werden, da mit diesem Schlüssel unendlich viele weitere Schlüssel generiert werden können.
ca.crt - das Zertifikat von unserer Zertifizierungsstelle. Muß auf jeden Rechner (Server+Client) kopiert werden.
servername.key - der private (geheime) Schlüssel des Servers, verbleibt auf dem Server.
servername.crt - das Zertifikat des Servers mit dem öffentlichen (public) Schlüssel, verbleibt auf dem Server.
clientname.key - der private (geheime) Schlüssel des Clients, bekommt der Client Computer.
clientname.crt - das Zertifikat des Clients mit dem öffentlichen (public) Schlüssel, bekommt der Client Computer.

im Safe   Server   Client
ca.key   ca.crt
server.key
server.crt
  ca.crt
client.key
client.crt


2. Server konfigurieren mit strongSwan unter Linux

Wie der Name strongSwan vermuten läßt, bietet die Software eine starke (strong) Verschlüsselung mit IKEv2 (Internet Key Exchange version 2). Dabei bezieht sich das Swan auf ein secure wide area network. Oder anders ausgedrückt: Mit Hilfe von strongSwan kann man stark verschlüsselte Verbindungen über unsichere Netzwerke aufbauen und somit VPN's (Virtual Private Network) herstellen, mit welchen man eventuelle Sperren eines Firmennetzwerks oder Landes umgehen kann. strongSwan gibt es unter beiden Plattformen, Windows und Linux. Ich gehe hier aber nur auf die Linux-Variante und ihre Einrichtung ein. Zuerst einmal müssen wir die erforderlichen Pakete installieren mittels
# apt-get install strongswan libstrongswan-extra-plugins libcharon-extra-plugins
Die zusätzlichen PlugIn-Paket-Angaben stellen sicher, daß alle erforderlichen PlugIns mit installiert werden. Allen voran das PlugIn für MSCHAPv2 (enthalten in den libcharon-extra-plugins), da ansonsten unsere zweite Authentifzierungs-Methode nicht funktioniert. Für höchste Sicherheit richten wir einen Server ein, welcher als erste Authentifzierung unsere generierten RSA Schlüssel nimmt und als zweite Authentifzierung eine Benutzer und Passwort Angabe mittels MSCHAPv2. Unser Server ist der heimische Rechner hinter einem Router mit NAT (Network Adress Translation). Somit sehen mögliche Verbindungen so aus:

PC (Server) === Router (Fritzbox) === Internet === Android Smartphone

PC (Server) === Router === Internet === anderer Router === Laptop

Damit die Verbindung über den Router reibungslos funktioniert, müssen wir noch die entsprechenden Ports freigeben. Als da wären:
Port 500 UDP und Port 4500 UDP

Als nächstes kopieren wir unsere selbst generierten Server-Schlüssel in das strongSwan Verzeichnis:
# cp keys/ca.crt /etc/ipsec.d/cacerts/
# cp keys/server.crt /etc/ipsec.d/certs/
# cp keys/server.key /etc/ipsec.d/private/

Es gibt drei Konfigurations-Dateien die wir bearbeiten müssen. Zuerst die Datei /etc/ipsec.conf, welche die Konfiguration der Verbindungen enthält:

# ipsec.conf - strongSwan IPsec configuration file

config setup

conn %default
keyexchange=ikev2
fragmentation=yes
dpdaction=clear
dpddelay=300s

conn rw
left=%localhost
leftsubnet=0.0.0.0/0
leftauth=pubkey
leftcert=server.crt
leftid=serveradresse.de
leftfirewall=yes
right=%any
rightsourceip=%dhcp
rightauth=pubkey
rightcert=client.crt
rightauth2=eap-mschapv2
auto=add

include /var/lib/strongswan/ipsec.conf.inc

Die ipsec.conf beinhaltet verschiedene Sektionen. Die erste Sektion conn setup ist für generelle Einstellungen und brauchen wir hier nicht, daher lassen wir sie leer. Die Sektion conn %default definiert Default-Einstellungen die für alle Verbindungen gelten. Danach können ein oder mehrere Verbindungs-Sektionen folgen, die mögliche Verbindungen spezifizieren. In unserem Fall legen wir als Default folgende Parameter fest:
keyexchange=ikev2 bestimmt den Schlüsselaustausch mit IKEv2.
fragmentation=yes schaltet die Fragmentierung ein (dazu später mehr im Abschnitt zu den Verbindungsproblemen).
dpdaction=clear legt fest, daß die Verbindung bei einem Ausfall (wird überwacht durch das Dead Peer Detection Protokoll) einfach gelöscht wird und keine weitere Aktion erfolgt.
dpddelay=300s bestimmt das Überprüfungsintervall in Sekunden durch DPD ob die Verbindung noch besteht.

Anschließend kommt unsere Verbindungs-Sektion rw (Roadwarrior). Der Name kann frei gewählt werden und dient lediglich der Wiedererkennung. Die Sektion ist in zwei Seiten gegliedert. Wenn nicht näher bestimmt ist per Default die linke Seite (left) die Server-Seite. Folglich die rechte Seite (right) die Client-Seite.

left=%localhost die I.P.-Adresse des Servers, hier localhost.
leftsubnet=0.0.0.0/0 bestimmt das Subnetz hinter dem Server und kann auch als Filter verwendet werden. In diesem Fall wird der gesamte Netzwerkverkehr ungefiltert erlaubt. Somit haben wir einen vollständigen Tunnel.
leftauth=pubkey bestimmt die Authentifzierungs-Methode des Servers durch unseren RSA public Key.
leftcert=server.crt der Name des Zertifikats des Servers.
leftid=server-id die ID des Servers wie im Zertifikat eingegeben. Normalerweise der FQDN (fully qualified domain name) des Servers. Im Falle einer DynDNS Adresse, diese.
leftfirewall=yes strongSwan legt automatisch IP-Regeln für eine Firewall an.
right=%any erlaubt jeden Clienten einen Anmeldevorgang zu starten.
rightsourceip=%dhcp vergibt per DHCP eine virtuelle Netzwerkadresse vom DHCP-Server. Normalerweise ist das der Router. Die dhcp-Option in Verbindung mit dem farp-PlugIn (fake arp) läßt den Client wie einen tatsächliches Mitglied des lokalen Server Netzwerks agieren.
rightauth=pubkey die erste Authentifzierungs-Methode des Clients: der RSA public Key.
rightcert=client.crt der Name der Zertifikats-Datei des Clients.
rightauth2=eap-mschapv2 die zweite Authentifzierungs-Methode des Clients: EAP-MSCHAPv2 mittels Benutzername und Passwort.
auto=add bestimmt die Operation, welche wenn überhaupt, beim IPsec-Start automatisch ausgeführt werden soll. add lädt eine Verbindung ohne sie zu starten.

Die nächste Datei ist /etc/ipsec.secrets und wie der Name schon verrät, beinhaltet sie die geheimen Dinge wie den Server-Key und die Benutzer/Passwort Abfrage für EAP:

# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host
# which knows the public part.

# this file is managed with debconf and will contain
# the automatically created private key
include /var/lib/strongswan/ipsec.secrets.inc

: RSA server.key

Benutzername : EAP "Passwort"

Die Datei ist eigentlich selbsterklärend. Unter : RSA server.key trägt man den Namen des Server-Key-Files ein. Zwei Zeilen tiefer wählt man einen Benutzernamen und ein ausreichend langes und kompliziertes Passwort. Ausreichend lang und kompliziert bedeutet, daß es aus unsinnigen Groß- und Kleinbuchstaben mit Zahlen und eventuell Sonderzeichen besteht und mindestens 13 Zeichen lang ist. Also keine Namen und Bezeichnungen die in einem Wörterbuch stehen. Ab dieser Länge würden heutige High-Speed-Großrechner über 100 Jahre brauchen um es durch ausprobieren heraus zu finden. Wählt man ein Passwort, das nicht so sicher ist, könnte man sich die zweite Authentifzierungs-Methode gleich sparen oder von der NSA ein Dankesschreiben fordern für leichten Zugang...

Eigentlich könnte man die Konfiguration hier beenden, jedoch gibt es noch eine Kleinigkeit die man verbessern kann damit die Liste der Rechner im Router nicht allzu lang wird. Wir erinnern uns, wir bekommen eine virtuelle I.P.-Adresse die uns automatisch per DHCP zugeteilt wird. In der Regel fungiert der Router als DHCP-Server. Mit einer Fritzbox als Router funktioniert das so: Der Client fragt bei der Fritzbox nach einer I.P.-Adresse. Die Fritzbox registriert die MAC-Adresse des Clients und weist ihm die nächste, freie I.P. zu. Gleichzeitig wird intern in der Fritzbox die Liste der Netzwerkgeräte aktualisiert und der neue Client mit MAC-Adresse und I.P.-Adresse eingetragen. Unterbricht der Client die Verbindung und verschwindet somit aus dem Netzwerk, bleibt er trotzdem in der Liste der Fritzbox als inaktives Netzwerkgerät. Bei einer erneuten Verbindung und einer erneuten Nachfrage nach einer I.P.-Adresse, bekommt er die gleiche I.P.-Adresse wieder zugewiesen, da die Fritzbox Anhand der MAC-Adresse das Gerät aus der Liste eindeutig identifziert.

Im Falle von strongSwan ist das farp-PlugIn dafür zuständig, ein virtuelles Netzwerk-Device zu erstellen, welches als virtueller Client eine I.P.-Adresse von unserer Fritzbox verlangt. Dummerweise verwendet das farp-PlugIn in der Standard-Einstellung jedesmal eine andere, zufällige MAC-Adresse. Dies führt dazu, daß wir bei jedem Anmelde-Vorgang eine neue I.P.-Adresse zugewiesen bekommen und die Liste der Netzwerkgeräte länger und länger wird....

Um dem entgegen zu wirken, editieren wir eine weitere Konfigurations-Datei von strongSwan, die strongswan.conf:

# strongswan.conf - strongSwan configuration file
#
# Refer to the strongswan.conf(5) manpage for details
#
# Configuration changes should be made in the included files

charon {
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
dhcp {
identity_lease = yes
}

}
}

Mit der dhcp-Klammer und identity_lease = yes wird das farp-Plugin angewiesen, die MAC Adresse aus einem Hashwert der Identität des Clients zu erstellen. Da die Identität immer gleich ist, ist auch die MAC-Adresse immer gleich und somit bekommen wir immer dieselbe I.P.-Adresse zugewiesen.

Damit haben wir die Konfiguration unseres Home-Servers abgeschlossen. Damit strongSwan alle Einstellungen übernimmt, müssen wir den Server noch mittels
# ipsec restart
neustarten.


3. Client-Konfiguration mit strongSwan-App auf Android Smartphone

Unter Android gibt es die strongSwan-App, welche man über den App-Store von Google Play beziehen kann. Nach Installation der App, müssen wir erst einmal unser Zertifikats-Paket client_files.p12 in Android installieren. Entweder man schließt das Handy per USB-Kabel an den PC an und schiebt das Paket in den Downloads Ordner, oder man schickt es sich einfach per E-Mail aufs Handy selbst zu. Ich bevorzuge letztere Methode, da ich zwar einen MTP-Treiber für Linux gefunden habe, es aber bisher damit noch nicht geschafft habe, Dateien aufs Handy zu kopieren. Lediglich die umgekehrte Methode, also vom Handy auf Festplatte zu kopieren funktionierte bei mir. Alternativ kann man natürlich auch Windows 7 starten, wenn man es denn hat, da es von Haus aus Unterstützung für MTP-Devices mitbringt.

Zum importieren genügt es die Anhangs-Datei client_files.p12 anzutippen. Android fragt, ob man das Zertifikat installieren will. Nach erfolgreichem Import meckert Android zwar mit einer Meldung, in der Art daß das "Netzwerk möglicherweise abgehört wird", was daran liegt, daß unser Zertifikat von unserer eigenen CA ist und nicht einer Offieziellen, aber mit einer kleinen Finger-Bewegung ist selbige schnell wieder verschwunden. Ob der Import erfolgreich war, kann man unter
Einstellungen/Sicherheit/Vertrauenswürdige Anmeldedaten
und dem Reiter Nutzer nachsehen. Taucht dort das selbst erstellte Zertifikat auf, ist alles bestens.

Als nächstes starten wir die strongSwan-App und tippen auf Profil hinzufügen. Eigentlich sind fast alle Punkte selbst erklärend, aber zur Sicherheit gehe ich sie einzeln nochmal durch:

Pic: strongSwan-App.jpg

  • Unter Server gibt man die I.P.-Adresse oder den Hostnamen des Servers an. Im Falle einer DynDNS-Adresse trägt man selbige hier ein.
  • Im Feld VPN-Typ wählt man IKEv2 Zertifikat + EAP (Benutzername+Passwort)
  • Unter Benutzername und Passwort trägt man die Anmeldedaten ein, die man in der Datei /etc/ipsec.secrets festgelegt hat.
  • Im Feld Benutzer-Zertifikat wählt man das zuvor importierte Zertifikat aus.
  • Unter CA-Zertifikat entfernt man besser den Haken für Automatisch wählen und wählt das CA-Zertifikat per Hand wie zuvor das Benutzer-Zertifikat. Die Automatik klappt zwar auch, aber dann dauert die Verbindung wesentlich länger, da die strongSwan-App erst einmal sämtliche System-Zertifikate durcharbeitet.
  • Unter Profilname kann man noch optional einen Namen für das Profil vergeben.
Alle anderen Einstellungen kann man so belassen wie sie sind. Mit einem Fingertip auf Speichern sichern wir unser Profil. Anschließend reicht ein Fingertip auf unser Profil und die Verbindung wird aufgebaut. Ob man verbunden ist, erkennt man an dem kleinem Schloß-Symbol in der oberen Leiste. Möchte man die Verbindung trennen, reicht ein weiterer Fingertip auf unser Profil und "Trennen".


4. Client-Konfiguration mit strongSwan unter Linux

Die Client-Konfiguration mit strongSwan unter einem Linux-System ist beinahe identisch zur Server-Konfiguration.

a) Installieren:
# apt-get install strongswan libstrongswan-extra-plugins libcharon-extra-plugins

b) Befindet man sich hinter einem Router müssen die entsprechenden Ports freigegeben und weitergeleitet werden: Port 500 UDP und Port 4500 UDP.

c) Die Client-Zertifikate kopieren:
# cp keys/ca.crt /etc/ipsec.d/cacerts/
# cp keys/server.crt /etc/ipsec.d/certs/
# cp keys/server.key /etc/ipsec.d/private/

d) Editieren der Datei /etc/ipsec.conf:

# ipsec.conf - strongSwan IPsec configuration file

config setup
strictcrlpolicy=no

conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
fragmentation=yes
keyexchange=ikev2
dpdaction=hold
dpddelay=30s

conn home
left=I.P.-Client-Rechner
leftsourceip=%config
leftcert=client.crt
leftid=client-id
leftauth=pubkey
leftauth2=eap-mschapv2
leftfirewall=yes
right=serveradresse.org
rightsubnet=0.0.0.0/0
rightid=server-id
rightauth=pubkey
auto=add

include /var/lib/strongswan/ipsec.conf.inc

Zu beachten ist hier, daß die linke Seite der Client-Rechner ist, während die rechte Seite unser entfernter Server. ikelifetime, keylife und rekeymargin bestimmen die Zeiten für die Key-Lebensdauer und deren Channels bevor neu verhandelt wird. keyingtries bestimmt, wie viele Versuche vom Clienten gemacht werden sollten, um eine Verbindung oder einen Ersatz zu verhandeln. dpdaction=hold versucht den Netzwerk-Verkehr abzufangen und bei Bedarf eine neue Verbindung auszuhandeln.

e) Editieren der Datei /etc/ipsec.secrets:

# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host
# which knows the public part.

# this file is managed with debconf and will contain
# the automatically created private key
include /var/lib/strongswan/ipsec.secrets.inc

: RSA client.key "key-passwort"

Benutzername : EAP "Passwort"

Noch ein anschließender Neustart mittels
# ipsec restart
damit die Einstellungen übernommen werden und unser IPsec-Client ist bereit für die Verbindung. Um eine Verbindung herzustellen genügt
# ipsec up home   # ipsec up verbindungsname
Um die Verbindung wieder zu trennen:
# ipsec down home

Möchte man überprüfen, ob eine Verbindung besteht, eignen sich diese Kommandos:
# ipsec status verbindungsname
Zeigt informationen über eine Verbindung an. Läßt man den Verbindungsnamen weg, zeigt der Befehl Informationen über alle Verbindungen.
# ip xfrm state
# ip xfrm policy
Zeigt Informationen über das IP framework an. Im ersten Fall über die Security Association Database, im zweiten Fall über die Security Policy Database.

Noch ein Wort zur Sicherheit

Bei all der starken Verschlüsselung hat die ganze Sache mit IPsec und strongSwan leider einen großen Haken: ein aufgebauter Tunnel kann jederzeit in sich zusammenfallen. Während man eben noch stark verschlüsselte I.P.-Pakete versendet, können sie im nächsten Moment schon wieder im Klartext über die unsicheren Kanäle des Internets wandern. Dabei kommt es natürlich darauf an, welche Netze man aufbaut und wofür man IPsec verwendet. Verbindet man sich z.B. aus der Ferne über das Internet mit dem Netz zu Hause, welches einen privaten Adressbereich wie z.B. 192.168.1.0/24 hat, dann stört es nicht weiter wenn der Tunnel zusammen fällt, da dieses Netz nicht durch den Aufruf einer Adresse wie 192.168.1.50 über das Internet erreichbar ist. Man merkt dann sofort, daß der Tunnel nicht mehr besteht. Verbindet man aber zwei Subnetze miteinander, die man auch ohne IPsec im Internet erreichen kann, sieht die Sache schon ganz anders aus. Möchte man dann vertrauliche Pakete versenden und kann nicht sicherstellen, daß sie auch verschlüsselt sind, ist das ein großes Sicherheitsrisiko. Auf dieses Sicherheitsrisiko wird auf der strongSwan Homepage im Abschnitt Security Recommendations auch eingegangen und ein paar Tips für entsprechende Maßnahmen gegeben, wie man seinen Traffic abzusichern kann. Dazu kann man sich entweder der iptables Firewall bedienen und entsprechende Rules definieren, welche sicherstellen, daß nur verschlüsselter Traffic über das Internet geleitet wird oder auch die Einstellung auto=route in der ipsec.conf festlegen. Benutzt man strongSwan nur um die Internet-Sperre einer Firma oder eines Landes zu umgehen, stört es auch nicht wenn der Tunnel zusammenfällt, bzw. merkt man es sofort, wenn die Webseiten sich nicht mehr öffnen lassen.

In dem Sinne ist eine OpenVPN Verbindung mit den tun oder tap Devices besser, da hier die Zugriffe auf jeden Fall über die entsprechenden Devices geroutet werden. Und diese Devices bestehen in der Regel, solange OpenVPN läuft. Auf dem Handy unter Android hat man immerhin ein Symbol daß den Status der Verbindung anzeigt. Unter Linux kann man lediglich hin und wieder den ipsec status Befehl ausführen. Aufgrund dieses Mankos und weil ich nicht mal ein kleines Widget unter KDE gefunden habe um den Status einer etablierten IPsec Verbindung anzuzeigen, habe ich mein eigenes, kleines IPsec-Status-Programm mit Hilfe von Qt geschrieben. Das Programm macht eigentlich nichts anderes, als jede Sekunde den Befehl ipsec status auszuführen, die Ausgabe zu analysieren und ein entsprechendes Icon im Systray anzuzeigen, ob eine Verbindung besteht oder nicht. Gleichzeitig schreibt es die Ausgabe des Status-Befehls in ein kleines Fenster, welches man aber auch minimieren kann wenn einen lediglich der Status interessiert und keine tiefergreifenden Informationen. Das Programm ipsec-status findet ihr unter dem Menüpunkt Programme in der Qt-Sektion.
Ein wichtiger Hinweis zum Programm: Damit es arbeiten kann, braucht es root-Rechte, da der ipsec status Befehl root-Rechte benötigt. Daher muß es unter KDE mittels des Befehls kdesu ipsec-status ausgeführt werden.


Verbindungs-Probleme: Webseiten öffnen sich nicht oder nicht vollständig

Das Problem besteht in der MTU (Maximum Transmission Unit) Größe, welche auf der Server Seite standardmäßig bei 1500 liegt. Diese Größe bietet Platz für 1460 Bytes an Daten pro Paket (Auch als die maximale Segmentgröße MSS bezeichnet).

IPsec fügt im Tunnel-Modus einen ESP-Header und einen zusätzlichen IP-Header für das Tunneling des Pakets hinzu (in der Regel mit einer zusätzlichen Größe von etwa 70-80 Byte). Wenn ein Paket nahezu die Größe der MTU hat und auf dieses dann noch der gekapselte Overhead dazu kommt, wird es wahrscheinlich die MTU der ausgehenden Verbindung überschreiten. Das ist dann der Moment wo IP-Fragmentierung aktiviert wird, welche zu Leistungseinbußen im VPN-Tunnel führen kann. Das geht dann soweit, daß sich manche Webseiten nur teilweise, andere gar nicht öffnen lassen.

Um dem entgegen zu wirken, kann man die maximale MTU Größe mittels einer iptables-Regel auf dem Server festlegen:

# iptables -t mangle -A FORWARD -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360

Um die Tabelle mit der Regel zur Überprüfung anzuzeigen zu lassen:
# iptables -t mangle -L

Um alle Regeln der Tabelle wieder zu löschen:
# iptables -t mangle -F   # (-F für flush)

Hinweis: iptables-Regeln sind flüchtig, d.h. sie sind nach einem Neustart des Rechners wieder weg. Will man sie dauerhaft erhalten, muß man sie in ein Skript packen, welches beim Start ausgeführt wird.