Impressum Kontakt

IPsec verstehen und nutzen

(balle)

Um IPsec verstehen zu können, solltest Du wenigstens Grundkenntnisse über Verschlüsselungsverfahren und über Netzwerke und das ISO/OSI Schichtenmodell haben. Falls Du die nicht drauf hast, lies am besten mal folgende Artikel:

IPsec bietet Möglichkeiten Netzwerktraffic auf IP Ebene (Layer 3) zu verschlüsseln und zu authentifizieren. D.h. alle Transport- bzw. Applicationlayerprotokolle höherer Ebene wie z.B. TCP/UDP (für die Transportschicht) oder FTP, SMTP usw. (für die Anwendungsschicht) können mit IPsec abgesichert werden.

Das bietet mehr Sicherheit als z.B. ein unsicheres Plain Protokoll der Anwendungsschicht (SMTP) mit einem sicheren Protokoll der gleichen Schicht (SSH) zu tunneln, weil im Falle von IPsec auch garantiert wird, dass die Header der Transport- und Vermittlungsschicht nicht manippalawanert wurden (Beispiel: IP Spoofing, Man-in-the-middle Attack). Bei IPsec handelt es sich keineswegs um ein einzelnes Protokoll, sondern um eine ganze Protokollsammlung. Und es ersetzt auch nicht das IPv4 Protokoll, sondern ergänzt es!

Zur Authentifizierung und Verschlüsselung kann IPsec zwei unterschiedliche Protokolle verwenden: AH (Authentication Header) oder ESP (Encapsulating Security Payload).

Bei der Verwendung von AH wird nur sicher gestellt, dass an den Headern der höheren Schichten nichts manippalawanert wurde. Verschlüsselung des Payloads kommt erst bei der Verwendung von ESP ins Spiel! Wahlweise kann man ESP auch ohne Authentifizierung bzw. Verschlüsselung verwenden, aber erst beide Features zusammen garantieren einem maximale Sicherheit!

AH und ESP werden bei FreeS/WAN durch KLIPS (Kernel IPsec) direkt in den Kernel implementiert.

Dann kommt bei IPsec noch ein weiteres Protokoll zum tragen: IKE (Internet Key Exchange). Wie der Name schon sagt wird dieses Protokoll für den automatischen Austausch von Schlüsseln und anderen Verschlüsselungsoptionen wie z.B. der Frage wird AH oder ESP verwendet oder welcher Verschlüsselungs- typ bzw. -algorythmus wird mit welcher Schluessellänge verwendet, wie lang ist die Lebensdauer der Schlüssel usw.

Das IKE Protokoll wird bei FreeS/WAN durch den PLUTO Daemon implementiert. Diese ganzen Verschlüsselungsoptionen werden von IPsec separat fuer jede Verbindung als sogenannte SA (Security Association) in einer SAD (Security Association Database) gespeichert. Das heisst auf gut Deutsch: Man kann für jede Verbindung zwischen zwei oder mehr Rechnern / Netzen verschiedene Verschlüsselungsoptionen verwenden.

Dann kann es noch sein, dass man im Zusammenhang mit IPsec oder IKE etwas von dem Protokoll ISAKMP (Internet Security Association Key Management Protocol) liest. Hier sei nur kurz erwähnt, dass dieses Protokoll für das Management der SAs zuständig ist und vom IKE Protokoll verwendet wird. Für mehr Informationen über den Aufbau von IPsec lies am besten folgendes:

In den meisten Fällen wird IPsec dazu verwendet VPNs zu realisieren. Ein VPN (Virtual Private Network) ist ein sicherer (verschlüsselter und authentifizierter) Zusammenschluss von mehreren Rechnern / Netzen über ein als unsicher klassifiziertes Netz (z.B. das Internet). Oder auf gut Deutsch: Du "stöpselst" zwei Kisten / Netze sicher zusammen und benutzt sie als eins... Für mehr Informationen über VPNs lies am besten die VPN FAQ.

Mit IPsec kann man allerdings auch im internen Netz den Traffic absichern, indem jeder Rechner ausschliesslich IPsec zur Kommunikation verwendet. IPsec ist ebenfalls eine gute Wahl, wenn man dem unsicheren WEP nicht zutraut das WLAN zu schützen oder um einem Aussendienstmitarbeiter sicheren Zugangs ins Firmennetz zu gewähren.

So voll geschmissen mit allen möglichen Abkürzungen, Theorie und Definitions- krempel kommt jetzt endlich der praktische Part! Also kurz in die Haende spucken, nen Bier oder ne Jolt holen und los geht's! Lade Dir die Sourcen von freeswan.org und entpacke sie.

Danach führst Du den Befehl make menugo aus, um die Userspace Tools zu installieren und die Kernel Sourcen zu patchen und neu zu compilieren. Wenn Du die Fehlermeldung "Cannot find gmp.h" oder so bekommst, dann musst Du noch die GMP Library installieren. Die Library bekommst Du hier Nach der Installation und dem Reboot mit dem neuen Kernel kann man folgendermaßen testen ob IPsec im Kernel funktioniert: ipsec verify. Du solltest jetzt auch ein paar IPsec Informationen des Kernels unter /proc/net finden...

Für FreeS/WAN gibt es zwei Configfiles: ipsec.conf und ipsec.secrets. In ipsec.secrets befindet sich nach der Installation ein frisch generiertes RSA Schlüsselpaar, das für die Authentifikation verwendet wird. In ipsec.conf konfiguriert man alle FreeS/WAN Einstellungen sowie die gewünschten Verbindungen.

Eine Beispiel Konfiguration, um einen internen Rechner via IPsec mit dem Gateway zu verbinden, sieht so aus:

# basic configuration
config setup
interfaces="ipsec0=eth0"
plutodebug=none
klipsdebug=none
syslog=NOTICE
plutoload=example
plutostart=example
plutowait=no
# Example Connection
conn example
auto=start
type=tunnel
authby=rsasig
left=192.168.3.34
leftsubnet=192.168.3.34/32
leftrsasigkey=left-rsa-key
leftid=192.168.3.34
right=192.168.3.32
rightsubnet=0.0.0.0/0
rightrsasigkey=right-rsa-key
rightid=192.168.3.32
keyexchange=ike
keylife=900s
ikelifetime=1200s
keyingtries=5
rekeymargin=150s

In der Sektion setup konfiguriert man generelle Einstellungen. interfaces="ipsec0=eth0" gibt an, dass das erste IPsec Interface eth0 sein soll. Weitere trennt man via Leerzeichen. Oder man verwendet %defaultroute, wenn man die Verbindungen über das Device, über das die Defaultroute geht, benutzen möchte.

plutodebug=none, klipsdebug=none, syslog=NOTICE dient dem Logging. Wenn man statt none all einträgt, dann findet man unter /var/log/messages jede Menge Debugmeldungen des Plutodaemon und der Kernel Ipsec Architektur.

plutoload=example, plutostart=example, plutowait=no gibt an, dass der Pluto Daemon die Verbindung example sofort laden und starten soll ohne zu warten. Verwendet man das Schlüsselwort %search, dann startet der Pluto Daemon automatisch alle Verbindugen, die auto=start (siehe weiter unten) definiert haben.

Mit dem Parameter conn configuriert man eine Verbindung. Wird als Verbindungsname %default angegeben, gelten die nachfolgenden Einstellungen für alle Verbindungen. Der Verbindungsname ist ansonsten frei wählbar. Genauso kann man eine Verbindung definieren, deren Einstellungen nur für mehrere andere Verbindungen gelten soll. Dann muss man diese Einstellungen in der gewünschten Verbindung mit also=Verbindungsname laden.

auto=start gibt an, dass die Verbindung automatisch gestartet werden soll. Falls einer der Kommunikationspartner nicht immer am Netz sein sollte, kann man die Verbindung nicht automatisch aufbauen lassen. In diesem Fall benutzt man auf dem VPN Gateway, das immer online ist das Schlüsselwort add, welches angibt, dass die Gegenseite die Verbindung aufbaut. Eine Verbindung wird über den Befehl ipsec auto --add Verbindungsname geladen und über ipsec auto --up Verbindungsname initiiert (über den Parameter --down wird die Verbindung dann wieder geschlossen).

type=tunnel gibt den Typ der Verbindung an. Man verwendet den Verbindungstyp Tunnel, wenn die Verbindung zwischen zwei Gateways aufgebaut werden soll, die den Traffic an das jeweilige Subnet weiter leiten sollen (Host to subnet oder Subnet to subnet Verbindungen). Bei Host to Host Verbindungen verwendet man den Typ Transport.

authby=rsasig signalisiert, dass die Authentifikation über RSA geschehen soll. Falls man für die Authentifikation Preshared Keys verwenden möchte, wählt man statt rsasig secret. Mehr dazu im Abschnitt Keying weiter unten.

left=192.168.3.34, leftsubnet=192.168.3.34/32 definiert den lokalen Rechner und das dahinter liegende Subnet. In diesem Fall gibt es kein dahinter liegendes Subnet, weil der lokale Rechner kein Router ist!

leftrsasigkey=left-rsa-key, leftid=192.168.3.34 konfiguriert den lokalen RSA Key und ID. Dazu gleich mehr...

Das selbe wird jetzt noch für die remote Seite mit right statt left eingestellt. Die Remote Seite ist in diesem Beispiel ein Gateway. Das sieht man an dem Parameter rightsubnet=0.0.0.0/0. Also das "Subnet" was hinter diesem Gateway liegt, ist das komplette Internet. Man kann statt IP Adressen auch Hostnamen eintragen, allerdings muss DNS dann natürlich einwandfrei zwischen den Verbindungspartner funktionieren und das auflösen mindert auch ein wenig die Geschwindigkeit... Sollte die IP und das Subnet eines Verbindungspartners egal sein oder kennt man es schlicht weg nicht, weil es sich um eine dynamische IP handelt, dann verwendet man das Schlüsselwort %any.

Die Einstellungen ab keyexchange=ike konfigurieren wie die Schlüssel für die Verschlüsselung und Authentifikation der Verbindung generiert und ausgetauscht werden sollen und wie oft neue Schlüsselpaare generiert werden.

Mit der Konfiguration wie oben beschrieben gibt es allerdings noch ein kleines Problem... Die Remote (right) Seite, also der VPN Gateway, ist eine Firewall, die auch NAT verwendet. Mit der obigen Konfiguration funktioniert zwar das Weiterleiten der Pakete in die weite Welt, wenn man allerdings versucht auf den Gateway selbst zu zu greifen z.B. für DNS, dann wird das fehlschlagen! Dazu gibt es aber auch noch einen Parameter: left bzw rightfirewall=yes je nachdem welche Seite eine Firewall ist. NAT darf übrigens nicht nach dem VPN Gateway statt finden, weil sonst die Authentifikation der Datenpakete auf der Gegenseite fehl schlagen wird, weil irgendwelche Adressen umgeschrieben wurden! Natürlich muss die Firewall den für IPsec nötigen Traffic auch durch lassen. Für die hier vorgestellte Konfiguration muss man folgende IPtables Regeln implementieren:

# IKE
iptables -A INPUT  -p udp --dport 500 -j ACCEPT
iptables -A OUTPUT -p udp --sport 500 -j ACCEPT

# ESP
iptables -A INPUT -p 50 -j ACCEPT
iptables -A OUTPUT -p 50 -j ACCEPT

Die erforderlichen IPtables Regeln können auch automatisch vor dem Verbindungsaufbau geladen und nach dem Verbindungabbau wieder entfernt werden. Dazu verwendest Du die beiden Befehle prepluto und postpluto und schreibt die Regeln in ein kleines Bashscript. prepluto=ipsec_rules.sh Wenn IPtables Regelsätze nur für eine bestimmte Verbindung automatisch geladen werden sollen, dann verwendet man in der conn Sektion die Parameter leftupdown bzw. rightupdown=script. Die kann man allerdings nicht mit dem Parameter left- bzw. rightfirewall kombinieren! Last but not least: Optional kann man auch noch den gesamten Datenverkehr komprimieren. Dies geschieht ganz einfach ueber den Parameter compress=yes.

Wie kommt man nun an die Einträge für leftrsasigkey und rightrsasigkey? RSA basiert auf dem Public Key Verfahren, d.h. man hat einen geheimen und einen öffentlichen Schlüssel. Das VPN Gateway muss ein Schlüsselpaar generieren und den public Key sicher an seine Clients verteilen. Jeder Client muss auch wiederum ein RSA Schlüsselpaar generieren und den Public Key dem VPN Gateway bekannt geben.

Sollte man auf dem Client oder VPN Gateway noch kein Schlüsselpaar unter /etc/ipsec.secrets finden, kann man mit ipsec newhostkey --output /etc/ipsec.secrets einen generieren. Dies erzeugt ein 2192 Bit RSA Schlüsselpaar. Mit dem Parameter --bits kann man das natürlich auch anpassen. Und mit dem Parameter --hostname kann man auch noch angeben für welchen Rechner das Schlüsselpaar generiert werden soll.

Über ipsec showhostkey --left > public.key extrahiert man den öffentlich Key in die Datei public.key. Dieser Key wird direkt in dem richtigen Format als leftrsasigkey für die ipsec.conf raus gespuckt.

Mit ipsec showhostkey --right > public.key bekommt man den Public Key im rightrsasigkey Format.

Diesen Key trägt man lokal als leftrsasigkey ein und überträgt ihn zum anderen Verbindungspartner, der ihn dann als rightrsasigkey eintragen muss. Das hier verwendete Verfahren basiert auf einem automatischen Schlüsselaustausch Verfahren mit einem asymmetrischen Verschlüsselungsalgorytmus (Public Key Verfahren). Es gibt auch die Möglichkeit des manuellen Schlüsselaustausches oder des automatischen mit symmetrischer Verschlüsselung, doch beide andere Verfahren sind unsicherer als das hier benutze. Wenn die Performance zu sehr leiden sollte, dann verwendet man am besten automatischen Schlüssel- austausch mit symmetrischer Verschluesselung (Preshared Keys genannt in der FreeS/WAN Doku). Von manuellem Schlüsselaustausch ist abzuraten und dient höchstens dem Debugging oder wenn die Gegenseite keinen automatischen Schlüsselaustausch unterstützt.

Einen neuen Preshard Key erzeugt man mit dem Befehl ipsec ranbits und teilt ihm über den --bytes Parameter die Schlüssellaenge mit. Preshared Keys werden im Gegensatz zu den Public Keys in der Datei /etc/ipsec.secrets nach folgendem Schema eingetragen: left right: PSK "key" Hier ein Beispiel:

10.0.0.1 11.0.0.1 : PSK "jxTR1lnmSjuj33n4W51uW3kTR55luUmSmnlRUuWnkj" Der Preshared Key muss genau wie der Public Key beiden Kommunikationspartner sicher bekannt gemacht werden! Also z.B. über eine mit PGP / GnuPG verschlüsselte E-Mail oder via scp.

Auf beiden Seiten muss IP Forwarding aktiviert sein! Und es darf kein Source Validation im Kernel aktiv sein! Das erreicht man mit folgenden Veränderungen im /proc Dateisystem:

echo 1 > /proc/sys/net/ipv4/conf/ip_forward
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter

Man kann IP Forwarding auch von IPsec automatisch einstellen lassen, indem man in der Configdatei /etc/ipsec.conf in der Setup Sektion den Parameter forwardcontrol=yes verwendet. Das ist per Default ausgestellt. Und /etc/init.d/ipsec start wird fehlschlagen, wenn man Source Validation noch aktiviert hat!

Unter Debian wird das normalerweise beim Booten angeschaltet und kann in der Datei /etc/network/options abgewürgt werden. Hier noch ein paar typische Fehlermeldungen auf die man stossen könnte:

route-host command exited with status 7

Dann solltest Du mal Deine Subnetparameter überprüfen.

route-client command exited with status 7

Kann es sein, dass Du einen *nexthop Eintrag vergessen hast? Das kann auf dem ersten Blick für etwas Verwirrung sorgen... Wenn Du z.B. wie ich einen Dialup Host mit einem anderen Rechner, der über ne DSL Flat online ist, zusammen schalten willst, dann connecten sich die beiden Rechner nicht direkt zueinander, sonder immer über den entsprechenden Default Router des Providers! Und den musst Du als leftnexthop eintragen!

[subnet]----[dial-up]--->[router_des_providers]--->{ Internet }--->[dsl-flat]----[subnet]

leftsubnet left leftnexthop right rightsubnet

Wenn Du über eine dynamische IP ans Netz angebunden bist, dann trage als leftnexthop am besten %defaultroute ein.

up-client command exited with status 127

Diese Fehlermeldung bedeutet, dass das _updown Script, welches ausgeführt wird, wenn Du leftfirewall oder rightfirewall auf yes gesetzt hast, nicht die entsprechenden Firewall Regeln eintragen konnte. Das Script funktioniert nur für ipfwadm und ipchains! Wenn Du z.B. IPtables verwendest, dann kommentiere die entsprechenden Zeilen aus /usr/local/lib/ipsec/_updown aus und trage sie selbst in Deine Firewall Regeln ein wie oben beschrieben!

Mit dem Befehl ipsec look Verbindung bekommt man einige Informationen über die Verbindung wie z.B. die Routingtabelle und über ipsec auto --status minimale Debugmeldungen des Schlüsseldaemons Pluto. Für mehr Debugmeldungen verwendet man den Befehl ipsec barf oder stellt die Debugging Meldungen von KLIPS und dem Pluto Daemon in /etc/ipsec.conf auf all.

Ein Blick in /var/log/messages oder ins Proc Dateisystem unter /proc/net kann auch nicht schaden...

Ansonsten testet man die Verbindung wie jede andere Netzwerkverbindung auch via ping, traceroute oder Sniffer usw.