Dienstag, 1. April 2008

VPN with IPv6 via strongSwan

Hallo,
diesmal schreibe ich eine kurze Einleitung in die Benutzung von strongSwan, um ein kleines VPN (virtuelles privates Netzwerk) aufzubauen.

Versuchsaufbau:
- ein Hostcomputer mit VMware 1.0.4
- Basis SLES 10 SP1, alternativ auch neuere Service Pack Versionen oder OpenSUSE 10.3 verwenden
- strongswan, die "the OpenSource IPsec-based VPN Solution for Linux"

Aufsetzen:
- VMWare installieren und zwei virtuelle Rechner ebenfalls mit SLES 10 SP 1 installieren
- auf dem Hostsystem die bridge-utils installieren (z.B. yast -i bridge-utils
- zusätzlich in den virtuellen Instanzen das Paket "strongswan" via YaST installieren (z.B. yast -i strongswan)
- mittels der "VMWare Server Console" die Instanz A (gemeint ist die erste virtuelle Installation) an das "/dev/vmnet1" binden (Tipp: über den Dialog "Virtual Machine Settings"->"Hardware"->"Network Connection"->"Custom Specific virtual network"->"/dev/vmnet1");
den selben Schritt für die Instanz B erledigen, allerdings diese Instanz B an das "/dev/vmnet8" binden
- nun wird die Bridge auf dem Host eingerichtet:
* Bridge erstellen: brctl addbr br0
* Netzwerk Schnittstellen hinzufügen: brctl addif br0 vmnet1;brctl addif br0 vmnet8
* Bridge Einstellungen verifizieren: brctl show
* Bridge aktiv markieren: ifconfig br0 up
* ein kleiner Tipp, die Bridge braucht eine Weile bis diese aufgebaut ist, nicht wundern wenn im ersten Moment der ping-Versuch in den Instanzen nicht klappen sollte
* Ziel ist es die beiden Instanzen in einem eigenen Netz zu haben, um den Netzwerkverkehr nicht zu verunreinigen
- Wir führen nun die Definition ein:
* die Instanz A (die erste Installation) wird nun im folgenden Kontext als "sun" referenziert
* die Instanz B (die zweite Installation) wird nun im folgenden Kontext als "moon" referenziert

- Auf der Instanz A der Einfachheit halber den Dienst dhcp deaktivieren und manuell eine IP-Adresse festlegen, entweder via yast lan oder manuell mit killall dhcpcd; ifconfig eth0 192.168.1.1/24 up. Die IPv6 Adresse wird manuell mit "ifconfig add FD53:7553:4500::1/48" festgelegt, der Grund folgt.
- Auf der Instanz B ebenfalls der Einfachheit halber den Dienst dhcp deaktivieren und manuell eine IP-Adresse festlegen, entweder via yast lan oder manuell mit killall dhcpcd; ifconfig eth0 192.168.1.2/24 up. Die IPv6 Adresse wird manuell mit "ifconfig eth0 add FD53:7553:4500::2/48" festgelegt, der Grund folgt.

Zertifikate
Nun werden mittels Yast2 die benötigten Zertifikate (Public/Private Key) erzeugt. Die Zertifikate werden für die Protokolle IKEv1 sowie IKEv2 benötigt.
- auf der Instanz A yast ca-mgm aufrufen
- falls noch keine CA (Certificate Authority; hier Root-CA) existiert, eine neue erstellen
- der CA-Name kann z.B. mit "ipsec-test-ca" belegt werden, eine Email Adresse muss ebenfalls festgelegt werden sowie der allgemeine Name, vorteilhaft ist es auch das Land, die Firma sowie die Abteilung mit Daten zu füllen
- im folgenden Dialog das Passwort festlegen und noch zwei mal bestätigen
- nun wird man wieder zum CA-Baum zurückgeleitet
- die erzeugte "ipsec-test-ca" betreten
- dieses CA muss nun exportiert werden; via "Erweitert"->"In Datei exportieren"
* dazu das Format "Nur das Zertifikat in PEM-Format" auswählen und nach "/root/ipsec-test-ca.pem" speichern.
(Hinweis; dieses Zertifikat müssen alle Teilnehmer bekommen, dazu später)
- es werden die einzelnen Host Zertifikate für die Teilnehmer erstellt:
* im Yast "Zertifikate" auswählen, "Hinzufügen"->"Server-Zertifikat hinzufügen" wählen
* der folgende Dialog benötigt einen allgemeinen Namen (hier den Hostnamen wählen, z.B. "d169") und die Email Adresse eingeben, danach das Passwort festlegen und final bestätigen
* in der Übersicht erscheint nun ein neues Zertifikat, welches Yast auch schon mit dem Root-CA signiert hat
* das erstellte Zertifikat nun nach "/root/d169.pem" exportieren, diesmal in dem Dialog "Zertifikat und Schlüssel nicht verschlüsselt im PEM-Format" auswählen (die Begründung folgt später)
* für jeden Host nun diese oben gezeigte Prozedur wiederholen, d.h. für jeden Host ein Zertifikat erstellen

ipsec Konfiguration
In diesem Kontext gehen wir von einer Host-Host Verbindung aus.
- im vorigen Schritt wurde das CA Zertifikat (hier "/root/ipsec-test-ca.pem") erstellt, dieses muss nun auf die teilnehmenden Instanzen verteilt werden und dort in dem Verzeichnis /etc/ipsec.d/cacerts/ abgelegt werden.
- die jeweiligen Host Zertifikate (welche von mittels Yast erstellt worden) müssen nun zerlegt werden, am Beispiel von dem "/root/d169.pem", wie man sieht enthält diese Datei einen "CERTIFIKATE" und einen "RSA PRIVATE KEY" Abschnitt, diese müssen getrennt werden:
* der "RSA PRIVATE KEY" Abschnitt wird ausgeschnitten und in eine zweite Datei gespeichert ("d169.pem.2"), es handelt sich wie der Name schon sagt um den Private Key, der gemäß der ipsec Konfiguration in das "/etc/ipsec.d/private/" Verzeichnis kopiert cp /root/d169.pem.2 /etc/ipsec.d/private/d169.pem werden muss, Tipp der Name muss gleich sein, die Namesendung kann beliebig sein.
* der "CERTIFICATE" Abschnitt wurde in der "d169.pem" Datei belassen, diese Datei muss dann nach "/etc/ipsec.d/certs/" kopiert werden cp /root/d169.pem /etc/ipsec.d/certs/
* die eben genannte Prozedur muss nun auch für das zweite erstelle Zertifikat (also für Instanz B) erledigt werden

- Konfiguration der "/etc/ipsec.secret" auf Instanz A:

#
# ipsec.secrets
#
# This file holds the RSA private keys or the PSK preshared secrets for
# the IKE/IPsec authentication. See the ipsec.secrets(5) manual page.
#
: RSA d169.pem ""


- Konfiguration der "/etc/ipsec.secret" auf Instanz B erfolgt ähnlich lediglich muss der Zertifikatsname "d169.pem" angepasst werden.

- Konfiguration der "/etc/ipsec.conf" auf Instanz A:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=192.168.1.1
leftcert=d169.pem
right=192.168.1.2
rightid="C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de"
auto=add

- Hierbei gilt es zu beachten das "left" sich immer auf die lokale Maschine bezieht und "right" auf die entfernte
- die "rightid" muss dem subject des entfernten Keys (der Instanz B) entsprechen, Tipp: zum anschauen des subjects openssl x509 -noout -text -in /etc/ipsec.d/certs/d169.pem, es dürfen z.B. nicht die Wertezuordnungen vertauscht werden

- Konfiguration der "/etc/ipsec.conf" auf Instanz A:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn home
keyexchange=ikev1
left=192.168.1.2
leftcert=g20.pem
right=192.168.1.1
rightid="C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de"
auto=add


Testen
- andere Netzwerkdienste deaktieren (z.B. novell-zmd, postfix), da diese den vereinfachten Test beeinflussen könnten (bzw. den tcpdump unnötig aufblähen)
- ipsec start auf beiden Instanzen
- am besten mit tail -f /var/log/messages den Startprozess beobachten und nach Fehler suchen:
* essentiell ist es, dass "loaded private key file" und "loaded host cert file" zu lesen ist und keinerlei Fehler folgt
* weiterhin muss eine Nachricht:

added configuration 'test': 192.168.1.1[C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de]..
.192.168.1.2[C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de]
zu finden sein

- der Test wird mit ipsec up test gestartet und sollte für dieses Beispiel so aussehen (Ausgabe von ipsec statusall):

000 "test": 192.168.1.2[C=DE, O=ORGA, OU=QA, CN=g22, E=email@domain.de]...192.16
8.1.1[C=DE, O=ORGA, OU=QA, CN=d169, E=mail@domain.de]; erouted; eroute owner: #
4
000 "test": CAs: 'C=DE, O=ORGA, OU=QA, CN=ipsec-test-ca, E=email@domain.de'...
'%any'
000 "test": ike_life: 10800s; ipsec_life: 3600s; rekey_margin: 540s; rekey_fuz
z: 100%; keyingtries: 3
000 "test": policy: RSASIG+ENCRYPT+TUNNEL+PFS+UP+MOBIKE; prio: 32,32; interfac
e: eth0;
000 "test": newest ISAKMP SA: #3; newest IPsec SA: #4;
000 "test": IKE algorithms wanted: 7_128-2-14,
000 "test": IKE algorithms found: 7_128-2_160-14,
000 "test": IKE algorithm newest: AES_CBC_128-SHA-MODP2048
000 "test": ESP algorithms wanted: 12_128-2, 3_000-1,
000 "test": ESP algorithms loaded: 12_128-2_160, 3_192-1_128,
000 "test": ESP algorithm newest: AES_128-HMAC_SHA1; pfsgroup=
000
000 #4: "test" STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE
in 2532s; newest IPSEC; eroute owner
000 #4: "test" esp.271da22c@192.168.1.1 (0 bytes) esp.91c42a79@192.168.1.2 (0 by
tes); tunnel
000 #3: "test" STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 10205s
; newest ISAKMP
000
Performance:
worker threads: 10 idle of 16, job queue load: 0, scheduled events: 0
Listening IP addresses:
192.168.1.2
fd53:7553:4500::2

- sollte man den Fehler "INVALID_ID_INFORMATION" in /var/log/messages lesen, so sollte man die Konfiguration prüfen (im Besonderen den rightid String auf Schreibfehler prüfen und vor allem mit dem subject String des Zertifikates vergleichen [siehe oben, openssl Befehl])
- folgend die Konfiguration mit IPv6 Adressen:
* dabei sind eigentlich nur auf Instanz A und B in der "/etc/ipsec.conf" die Tags left und right mit den jeweiligen IP-Adressen zu versehen:
* Instanz A, "/etc/ipsec.conf":

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=FD53:7553:4500::1
leftcert=d169.pem
right=FD53:7553:4500::2
rightid="C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de"
auto=add

* Instanz B, "/etc/ipsec.conf":

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=FD53:7553:4500::2
leftcert=g20.pem
right=FD53:7553:4500::1
rightid="C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de"
auto=add

* in diesem Beispiel muss ipsec neu gestartet werden ipsec stop; ipsec start, danach sollte die Kommunikation auch über die IPv6 Adresse funktionieren:

IKE_SA 'test' established between C=DE, O=ORGA, OU=QA, CN=g22, E=email@domain.de
[fd53:7553:4500::2]...[fd53:7553:4500::1]C=DE, O=ORGA, OU=QA, CN=d169, E=email
@domain.de
CHILD_SA 'test' established successfully

* Hinweis: die Ausgabe von ifconfig eth0 auf den Instanzen gibt schon eine vordefinierte IPv6 Adresse aus, diese ist allerdings link lokal. Es muss für diesen IPv6-Test eine globale Adresse gewählt werden um den Verbindung erfolgreich durchführen zu können (obwohl die link lokalen IPv6 Adressen untereinander [zwischen den Instanzen A und B] ping-bar sind).

Zum Abschluss noch den Verweis auf die strongSwan Dokumentation:
Host zu Host
IPv6 Results

Keine Kommentare: