7.2. Automatisches Verschlüsseln

Im vorigen Abschnitt wurde die Verschlüsselung mit einfachen Shared Secrets konfiguriert. Um die Sicherheit zu gewährleisten, müssen wir unsere Verschlüsselungskonfiguration über einen vertrauenswürdigen Kanal übertragen. Wenn wir den Remote-Host über Telnet konfigurieren, würde jeder Dritte unsere geteilte Sicherheit (Shared Secrets) kennen und das Setup wäre nicht sicher.

Ferner, da die Sicherheit gemeinsam genutzt wird, ist es nicht geheim. Die Gegenseite kann nicht viel für unsere Sicherheit tun, wir müssen aber sicherstellen, dass wir eine andere Sicherheit bei der Kommunikation mit allen unseren Partnern benutzen. Dies erfordert eine große Anzahl an Schlüsseln, bei 10 Parteien sind das mindestens 50 verschiedenen.

Neben dem symmetrischen Schlüsselproblem gibt es auch die Notwendigkeit des Schlüsselaustauschs. Hat ein Dritter genug Traffic mitgeschnitten, kann er in der Lage sein, den Schlüssel mittels Reverse Engineering zu ermitteln. Das verhindert man, wenn jedes mal ein neuer Schlüssel verteilt wird, das ist aber ein Verfahren, welches automatisiert werden muss.

Problematisch bei der oben beschriebenen manuellen Eingabe ist, dass wir die Algorithmen und Schlüssellängen genau definieren haben, das benötigt viel Koordination mit der Gegenstelle. Wünschenswert ist es, die Möglichkeit zu haben, eine allgemeinere Schlüsselregel zu beschreiben "Wir können 3DES und Blowfish mit mindestens folgender Schlüssellängen benutzen".

Um diese Problem zu lösen, bietet IPSec Internet Key Exchange zum Generieren zufälliger Schlüssel, die per asymmetrischer Verschlüsselung übertragen werden, nachdem die Algorithmusinformationen ausgehandelt wurden.

Der Linux 2.5 IPSec-Implementierung arbeitet mit dem KAME 'racoon' IKE-Daemon. Ab 9. November kann die racoon-Version von Alexey's iptools compiliert werden, du musst nur in zwei Dateien #include <net/route.h> entfernen. Alternativ habe ich eine vorkompilierte Version erstellt.

Note

IKE benötigt Zugriff auf den UDP-Port 500, kontrolliere das iptables das nicht blockt.

7.2.1. Theorie

Wie bereits erläutert, macht uns die automatische Verschlüsselung eine Menge Arbeit. Es schafft Sicherheitszuordnungen im laufenden Betrieb. Es ist jedoch nicht die Regel, dass es genau für uns angepasst ist wie es eingestellt sein sollte.

Um von IKE zu profitieren, legen wir Regeln an, aber nicht jede SAs. Wenn der Kernel entdeckt, dass es eine IPSec-Richtlinie, aber keine Security Association gibt, wird der IKE-Daemon informiert und er versucht einen auszuhandeln.

Zur Erinnerung, eine Sicherheitsregel (Security Policy) legt fest WAS wir wollen; eine Security Association beschreiben WIE wir es wollen. Wenn wir automatische Verschlüsselung verwenden, können wir nur angeben, was wir wollen.

7.2.2. Beispiel

Kame racon kommt mit einer großen Vielzahl an Optionen, die meisten sind sehr gute Standardwerte, diese brauchen wir nicht anfassen. Wie oben beschrieben, muss der Betreiber einen Security Policy keine Security Associations definieren. Wir verlassen uns auf die Verhandlungen des IKE-Daemon.

Benutzen wir noch einmal unser Beispiel 10.0.0.11 und 10.0.0.216 um die Kommunikation abzusichern, aber dieses Mal mit Hilfe von racoon. Der Einfachheit halber benutzen wir die Konfiguration mit Pre-Shared Keys, den gefürchteten "Shared Secrets". X.509-Zertifikate werden in einem separaten Abschnitt beschrieben, siehe Section 7.2.3.

Wir bleiben fast auf der Standardkonfiguration, beide Hosts sind identisch:

path pre_shared_key "/usr/local/etc/racoon/psk.txt";

remote anonymous
{
 	exchange_mode aggressive,main;
 	doi ipsec_doi;
 	situation identity_only;

	my_identifier address;

	lifetime time 2 min;   # sec,min,hour
	initial_contact on;
	proposal_check obey;	# obey, strict or claim

	proposal {
	        encryption_algorithm 3des;
	        hash_algorithm sha1;
	        authentication_method pre_shared_key;
	        dh_group 2 ;
	}
}
 
sainfo anonymous
{
 	pfs_group 1;
 	lifetime time 2 min;
 	encryption_algorithm 3des ;
 	authentication_algorithm hmac_sha1;
		compression_algorithm deflate ;
}

Viele Einstellungen - ich glaube, es können noch mehr entfernt werden, um die Standardkonfiguration zu erhalten. Wir haben zwei anonyme Einstellungen für alle Gegenstellen konfiguriert, weitere Konfiguration werden dadurch vereinfacht. Es besteht hier keine Notwendigkeit fü,r pro-Host angaben, wenn wir nicht wollen.

Zusätzlich haben wir es eingerichtet, dass wir uns auf der Grundlage unserer IP-Adresse identifizieren ("my_identifier address") und geben bekannt, dass wir 3DES, SHA1 beherschen, und wir einen Pre-Shared-Key benutzen, in psk.txt befindlich.

In psk.txt haben wir nun zwei Einträge, die sich auf beiden Hosts unterscheiden. Auf 10.0.0.11:

10.0.0.216	password2
Auf 10.0.0.216:
10.0.0.11	password2
Prüfe bitte das die Dateien root gehören und der mode auf 0600 gesetzt ist, racoon wird dem Inhalt nicht anders zu vertrauen. Achte darauf, dass die Dateien untereinander gespiegelt sind.

Jetzt sind wir bereit, unser gewünschtes Regelsetup zu erstellen, das einfach genug ist. Auf Host 10.0.0.216:

#!/sbin/setkey -f
flush;
spdflush;

spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
	esp/transport//require;

spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
	esp/transport//require;
And on 10.0.0.11:
#!/sbin/setkey -f
flush;
spdflush;

spdadd 10.0.0.11 10.0.0.216 any -P out ipsec
	esp/transport//require;

spdadd 10.0.0.216 10.0.0.11 any -P in ipsec
	esp/transport//require;
Achte darauf diese Regeln zu spiegeln.

Wir sind nun bereit, racoon zu starten! Nach dem Start kommt der Moment der Verbindung von 10.0.0.11 zu 10.0.0.216 und umgekehrt, racoon startet die Aushandlung:

12:18:44: INFO: isakmp.c:1689:isakmp_post_acquire(): IPsec-SA
  request for 10.0.0.11 queued due to no phase1 found.
12:18:44: INFO: isakmp.c:794:isakmp_ph1begin_i(): initiate new
  phase 1 negotiation: 10.0.0.216[500]<=>10.0.0.11[500]
12:18:44: INFO: isakmp.c:799:isakmp_ph1begin_i(): begin Aggressive mode.
12:18:44: INFO: vendorid.c:128:check_vendorid(): received Vendor ID: 
  KAME/racoon
12:18:44: NOTIFY: oakley.c:2037:oakley_skeyid(): couldn't find
  the proper pskey, try to get one by the peer's address.
12:18:44: INFO: isakmp.c:2417:log_ph1established(): ISAKMP-SA
  established 10.0.0.216[500]-10.0.0.11[500] spi:044d25dede78a4d1:ff01e5b4804f0680
12:18:45: INFO: isakmp.c:938:isakmp_ph2begin_i(): initiate new phase 2 
  negotiation: 10.0.0.216[0]<=>10.0.0.11[0]
12:18:45: INFO: pfkey.c:1106:pk_recvupdate(): IPsec-SA established: 
  ESP/Transport 10.0.0.11->10.0.0.216 spi=44556347(0x2a7e03b)
12:18:45: INFO: pfkey.c:1318:pk_recvadd(): IPsec-SA established:
  ESP/Transport 10.0.0.216->10.0.0.11 spi=15863890(0xf21052)

Wenn wir jetzt setkey -D benutzen, was uns die Security Associations zeigt, sehen wir:

10.0.0.216 10.0.0.11 
	esp mode=transport spi=224162611(0x0d5c7333) reqid=0(0x00000000)
	E: 3des-cbc  5d421c1b d33b2a9f 4e9055e3 857db9fc 211d9c95 ebaead04
	A: hmac-sha1  c5537d66 f3c5d869 bd736ae2 08d22133 27f7aa99
	seq=0x00000000 replay=4 flags=0x00000000 state=mature 
	created: Nov 11 12:28:45 2002	current: Nov 11 12:29:16 2002
	diff: 31(s)	hard: 600(s)	soft: 480(s)
	last: Nov 11 12:29:12 2002	hard: 0(s)	soft: 0(s)
	current: 304(bytes)	hard: 0(bytes)	soft: 0(bytes)
	allocated: 3	hard: 0	soft: 0
	sadb_seq=1 pid=17112 refcnt=0
10.0.0.11 10.0.0.216 
	esp mode=transport spi=165123736(0x09d79698) reqid=0(0x00000000)
	E: 3des-cbc  d7af8466 acd4f14c 872c5443 ec45a719 d4b3fde1 8d239d6a
	A: hmac-sha1  41ccc388 4568ac49 19e4e024 628e240c 141ffe2f
	seq=0x00000000 replay=4 flags=0x00000000 state=mature 
	created: Nov 11 12:28:45 2002	current: Nov 11 12:29:16 2002
	diff: 31(s)	hard: 600(s)	soft: 480(s)
	last:                     	hard: 0(s)	soft: 0(s)
	current: 231(bytes)	hard: 0(bytes)	soft: 0(bytes)
	allocated: 2	hard: 0	soft: 0
	sadb_seq=0 pid=17112 refcnt=0
Diese Security Policies haben wir konfiguriert:
10.0.0.11[any] 10.0.0.216[any] tcp
	in ipsec
	esp/transport//require
	created:Nov 11 12:28:28 2002 lastused:Nov 11 12:29:12 2002
	lifetime:0(s) validtime:0(s)
	spid=3616 seq=5 pid=17134
	refcnt=3
10.0.0.216[any] 10.0.0.11[any] tcp
	out ipsec
	esp/transport//require
	created:Nov 11 12:28:28 2002 lastused:Nov 11 12:28:44 2002
	lifetime:0(s) validtime:0(s)
	spid=3609 seq=4 pid=17134
	refcnt=3

7.2.2.1. Probleme und bekannte Mängel

Wenn es nicht funktioniert, überprüfe ob alle Konfigurationsdateien root gehören und auch nur von root gelesen werden können. Um racoon im Vordergrund zu starten, verwende '-F'. Eine bestimmte Konfigurationsdatei, anstatt vom kompilierten Platz, erzwingt man mit "-f". Fü,r eine Unmenge an Details, erweitere die racoon.conf mit 'log debug;'.

7.2.3. Automatische Verschlüsselung mit X.509-Zertifikaten

Wie bereits erwähnt, ist die Verwendung von Shared Secrets schwer, weil sie nicht leicht verteilt und wenn verteilt, sie nicht mehr geheim sind. Glücklicherweise gibt es asymmetrische Verschlüsselungstechnologie.

Jeder IPsec-Teilnehmer erzeugt einen öffentlichen und einen privaten Schlüssel. Eine sicheres Kommunikations-Setup kann von beiden Parteien die Veröffentlichung ihrer öffentlichen Schlüssel sein und als Regel konfiguriert sein.

Der Aufbau eines Schlüssels ist relativ einfach, auch wenn es einiges an Arbeit erfordert. Das Folgenden basiert auf die 'openssl'-Tools.

7.2.3.1. Erstelle ein X.509-Zertifikat für deinen Host

OpenSSL hat eine grosse Infrastruktur für Schlüssel, auch für nicht von Zertifizierungsstellen signierte Schlüssel. Momentan müssen wir komplett die Infrastruktur umgehen und üben mit guter alter SnakeOil-Sicherheit (vorgetäuscht) und verzichten auf eine Zertifizierungsstelle.

Zuerst erstellen wir eine Zertifikatsanforderung (certificate request) für unseren Host, nennen wir ihn 'laptop':

$ openssl req -new -nodes -newkey rsa:1024 -sha1 -keyform PEM -keyout \
  laptop.private -outform PEM -out request.pem
Dazu müssen wir einige Fragen beantworten:
Country Name (2 letter code) [AU]:NL
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Delft
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Linux Advanced
Routing & Traffic Control
Organizational Unit Name (eg, section) []:laptop
Common Name (eg, YOUR name) []:bert hubert
Email Address []:ahu@ds9a.nl

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Es liegt in deinem Ermessen, wie vollständig du diese ausfüllen möchtest. Wenn du willst, kannst du den Hostnamen gesetzt, abhängig von deinen Sicherheitsanforderungen. In diesem Beispiel machen wir es.

Jetzt signieren wir den Request selbst:

$ openssl x509 -req -in request.pem -signkey laptop.private -out \
  laptop.public
Signature ok
subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic \
  Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl
Getting Private key
Die 'request.pm'-Datei kann nun verworfen werden.

Wiederhole diesen Vorgang für alle Hosts, fü die du einen Schlüssel benötigst. Die Datei '.public' kann unbedenklich verbreitet werden, aber die '.private' muss privat bleiben!

7.2.3.2. Konzept und Einsatz

Sobald wir einen öffentlichen und einen privaten Schlüssel für unsere Hosts haben, kann racoon mitgeteilt werden diese zu benutzen.

Kehren wir zu unserer vorherigen Konfiguration und den beiden Hosts zurück, 10.0.0.11 ('upstairs') und 10.0.0.216 ('laptop').

Die Datei racoon.conf auf 10.0.0.11, erweitern wir mit:

path certificate "/usr/local/etc/racoon/certs";

remote 10.0.0.216
{
 	exchange_mode aggressive,main;
	my_identifier asn1dn;
	peers_identifier asn1dn;

	certificate_type x509 "upstairs.public" "upstairs.private";

	peers_certfile "laptop.public";
	proposal {
                encryption_algorithm 3des;
		hash_algorithm sha1;
		authentication_method rsasig;
		dh_group 2 ;
	}
}
Dies sagt racoon, die Zertifikate befinden sich in /usr/local/etc/racoon/certs/. Zusätzlich beinhaltet sie Konfigurationselemente speziell für die Gegenseite 10.0.0.216.

Die 'asn1dn' Zeilen sagen racoon, mit welchem Kennzeichen des öffentlichen Schlüssels sowohl die lokale als auch die entfernte Stelle extrahiert werden. Diese ist 'subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic Control/OU=Laptop/CN=bert hubert/Email=ahu@ds9a.nl'.

Die certificate_type Linie konfiguriert den öffentlichen und privaten Schlüssel. Das peers_certfile-Statement konfiguriert racoon, wie der öffentliche Schlüssel von der Gegenstelle aus der Datei laptop.public zu lesen ist.

Die prosposal Stelle bleibt zum bereits gesehenen unverändert, einzige Ausnahme ist authentication_method die jetzt per rsasig die Authentifizierung durch RSA-public/private-Schlüssel an gibt.

Die zusätzliche Konfiguration von 10.0.0.216 ist nahezu identisch, mit Ausnahme der üblichen Spiegel:

path certificate "/usr/local/etc/racoon/certs";

remote 10.0.0.11
{
 	exchange_mode aggressive,main;
	my_identifier asn1dn;
        peers_identifier asn1dn;

        certificate_type x509 "laptop.public" "laptop.private";
 
 	peers_certfile "upstairs.public";

	proposal {
                encryption_algorithm 3des;
	        hash_algorithm sha1;
		authentication_method rsasig;
	        dh_group 2 ;
	}
}

Nun, da wir diese Aussagen auf beiden Hosts aufgenommen haben, brauchen wir nur noch die wichtigsten Dateien an Ort und Stelle zu schieben. Die 'upstairs'-Maschine benötigt upstairs.private, upstairs.public und laptop.public in /usr/local/etc/racoon/certs. Stelle sicher, dass dieses Verzeichnis dem Benutzer root gehört und den Modus 0700 hat, racoon könnte sich sonst weigern diese zu lesen!

Die 'laptop'-Maschine benötigt laptop.private, laptop.public und upstairs.public in /usr/local/etc/racoon/certs. Mit anderen Worten, jeder Host braucht seine eigenen öffentlichen und privaten Schlüssel und zusützlich den öffentlichen Schlüssel der Gegenstelle.

Überprüfe ob eine Sicherheitsregel vorhanden ist (die 'spadd'-Zeilen von Section 7.2.2 ausführen). Dann racoon starten und alles sollte funktionieren.

7.2.3.3. Wie macht man Tunnel sicher

Zum Einrichten von sicherer Kommunikation mit einem anderen Teilnehmer müssen die öffentlichen Schlüssel austauschen werden. Der öffentliche Schlüssel muß nicht geheimgehalten werden, im Gegenteil, nur so kann sichergestellt werden, dass es sich wirklich um einen unveränderten Schlüssel handelt. Mit anderen Worten, du musst sicher sein, dass es keinen Mitlauscher ('man in the middle') gibt.

Um dies zu erleichtern, bietet OpenSSL den 'verarbeiten'-Befehl (digest):

$ openssl dgst upstairs.public 
MD5(upstairs.public)= 78a3bddafb4d681c1ca8ed4d23da4ff1

Was wir jetzt tun müssen, ist zu prüfen, ob unser Remote-Partner den gleichen Digest sieht. Um abzusichern, dass die Gegenstelle wirklich die E-Mail mit dem Schlüssel gesendet hat, kann man sich im realen Leben oder vielleicht telefonisch darüber vergewissern.

Ein anderer Weg ist die Verwendung von einem vertrauenswürdigen Dritten, der eine Zertifizierungsstelle betreibt. Diese CA unterschreibt dann deinen Schlüssel, wir es bisher getan haben.