Opportunistic Encryption: Difference between revisions

From
Jump to navigation Jump to search
No edit summary
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==Hardware==
=Hardware=
Beliebige Rechner, auf denen Linux mit Kernel 2.4 oder 2.6 drauf läuft.
Beliebige Rechner, auf denen Linux mit Kernel 2.4 oder 2.6 drauf läuft.


==Software==
=Software=


FreeSwan auf mindestens zwei verschiedenen Rechnern und einen DNS-Server.
FreeS/WAN auf mindestens zwei verschiedenen Rechnern und einen DNS-Server.


Wir haben für unsere Installation Debian Sarge verwendet mit Kernel 2.6.
Wir haben für unsere Installation Debian Sarge verwendet mit Kernel 2.6.
Line 14: Line 14:
</pre>
</pre>


Das eigentlich aktuellere OpenSwan in derzeit für OE leider nicht geeignet.
Das eigentlich aktuellere OpenS/WAN in derzeit für OE leider nicht geeignet.
Zumindest bei kernel-2.6.8 besteht das Problem, dass die folgende Fehlermeldung kommt:
Zumindest bei kernel-2.6.8 besteht das Problem, dass die folgende Fehlermeldung kommt:


Line 23: Line 23:
Im Verzeichnis openswan-*/doc/2.6.known-issues steht das zumindest unter CURRENT ISSUES.
Im Verzeichnis openswan-*/doc/2.6.known-issues steht das zumindest unter CURRENT ISSUES.


'''Achtung:''' Das Initskript hat unter Debian Probleme damit, den pluto-daemon ordnungsgemäß zu beenden. Am einfachsten fügt man daher in <tt>/etc/init.d/ipsec</tt> an passender Stelle (''FIXME'') die Zeile
killall _plutorun pluto _plutoload _pluto_adns
ein.

'''Debugging-Hinweis:''' Bei Debian landen die Logs von pluto in der Datei <tt>/var/log/auth.log</tt>, wo man sie intuitiv eher nicht vermuten würde. Fehlersuche gestaltet sich aber leicher, wenn man die Logs hat ;-).


=Keys erzeugen=
=Keys erzeugen=


Es gibt zwei unterschiedliche Varianten von OE:

Full Opportunism - beide Rechner können eine verschlüsselte Verbindung initiieren. Dazu müssen beide Rechner TXT-Records im Reverse-DNS haben. (Man muss also sein IP-Subnetz DNS-seitig unter Kontrolle haben).

Initiate-only Opportunism - es muss nur der Rechner Reverse-DNS haben, der verschlüsselte Verbindungen entgegennimmt. Der Andere darf einen Forward-DNS-Eintrag haben.


==Full Opportunism==
Um DNS-Einträge mit Schlüsseln zu erzeugen nimmt man ipsec mailkey. Dieses Tool generiert eine ausführbare Datei in der die TXT Records stehen, die man in das Reverse-DNS eintragen muss.
Um DNS-Einträge mit Schlüsseln zu erzeugen nimmt man ipsec mailkey. Dieses Tool generiert eine ausführbare Datei in der die TXT Records stehen, die man in das Reverse-DNS eintragen muss.


ipsec mailkey --me <var>test@localhost</var> --reverse <var>10.0.23.2</var>
<pre>
ipsec mailkey --me test@localhost --reverse 10.0.23.2
</pre>


In der Datei befindet sich dann der DNS-Record:
In der Datei befindet sich dann der DNS-Record:


--DNS_RESOURCE_RECORDS--
<pre>
--DNS_RESOURCE_RECORDS--
<var>2.23.0.10.in-addr.arpa. IN TXT "X-IPsec-Server(10)=10.0.23.2" "lakdfklajsdfoiweruo82347.... "</var>
--DNS_RESOURCE_RECORDS--


2.23.0.10.in-addr.arpa. IN TXT "X-IPsec-Server(10)=10.0.23.2" "lakdfklajsdfoiweruo82347.... "


==Initiation Only==
--DNS_RESOURCE_RECORDS--
</pre>


Diesmal den Server wie oben. Und beim Client(der Rechner, der die Initiierte Verbindung initiiert) wie folgt:
Wenn man nun die Rechner die Records eingetragen hat, muss man noch dafür sorgen, dass DNS-Anfragen beim Aushandeln der Schlüssel nicht der OE zum Opfer fällt. Dazu trägt man am besten den DNS-Server in
die Datei


ipsec mailkey --me <var>test@localhost</var> --forward <var>host.domain.tld</var>
<pre>
/etc/ipsec.d/policies/clear
</pre>


Der Eintrag sieht dann ungefähr so aus:
in Form von


<pre>
a.b.c.d/32
</pre>




--DNS_RESOURCE_RECORDS--
<var>chunk. IN TXT "X-IPsec-Server(10)=@chunk.snug.local"
" AQOC8IcGKBb6y8+7P3WFMGSdJvkVH........"</var>
--DNS_RESOURCE_RECORDS--


Dies jetzt zu den forward DNS-Einträgen packen.

=DNS freigeben=

Wenn man nun die Rechner die Records eingetragen hat, muss man noch dafür sorgen, dass DNS-Anfragen beim Aushandeln der Schlüssel nicht der OE zum Opfer fällt. Dazu trägt man am besten den DNS-Server in
die Datei <tt>/etc/ipsec.d/policies/clear</tt> in Form von
<var>a.b.c.d</var>/32
ein.
ein.


Falls der DNS-Server lokal läuft sollte man Verschlüsselung auf dem lo-Deviceverbieten, indem man folgendes in die /etc/ipsec.conf einträgt.
Falls der DNS-Server lokal läuft sollte man Verschlüsselung auf dem lo-Device verbieten. Der übliche Weg dazu wäre, in die <tt>/etc/ipsec.d/policies/clear</tt>
127.0.0.0/8
(Steht auch im doc/* drin.)
einzutragen. Das führt leider dazu, dass FreeS/WAN völlig abstruse Routen setzt. (Eine Kopie der Default-Route, aber für 127.0.0.0/8, also sowas wie <tt>127.0.0.0/8 via 10.0.23.1 dev eth0</tt>.)


Ausserdem wird der lokale DNS-Server selbst DNS-Anfragen absetzen wollen (zum Beispiel, wenn FreeS/WAN versucht, herauszufinden ob für die eigene IP wirklich ein korrekter TXT-RR existiert) was zu einer Henne-und-Ei-Situation führt: Zum Nachschlagen der Schlüssel ist DNS erforderlich, für jedweden Netzwerkverkehr müssen aber Schlüssel nachgeschlagen werden.
<pre>

conn exclude-lo
Die Policy-Groups von FreeS/WAN können Verkehr leider nur nach IP-Adressen einordnen und unterstützen keine weiteren Kriterien wie etwa Portnummern oder gar Paketfilter-Tags, obwohl das darunterliegende Kernel-IPsec das durchaus kann. Workaround: Man setzt die passenden Policyregeln manuell mit setkey. Dazu muss man ein setkey-Skript (zum Beispiel <var>/usr/local/bin/dnsclear</var>) erzeugen mit folgendem Inhalt (<var>a.b.c.d</var> durch die eigene IP-Adresse ersetzen):
authby=never
#!/usr/sbin/setkey -f
left=127.0.0.1
leftsubnet=127.0.0.0/8
spdadd <var>a.b.c.d</var>/32 0.0.0.0/0[53] udp -P out none;
right=127.0.0.2
spdadd <var>a.b.c.d</var>/32 0.0.0.0/0[53] tcp -P out none;
rightsubnet=127.0.0.0/8
type=passthrough
spdadd 0.0.0.0/0[53] <var>a.b.c.d</var>/32 udp -P in none;
auto=route
spdadd 0.0.0.0/0[53] <var>a.b.c.d</var>/32 tcp -P in none;
</pre>

Dieses Skript trägt man dann in <var>/etc/ipsec.conf</var> im Abschnitt <tt>config setup</tt> als <tt>prepluto="<var>/usr/local/bin/dnsclear</var>"</tt> ein. Das Skript sollte natürlich ausführbar sein (<tt>chmod a+x <var>/usr/local/bin/dnsclear</var></tt>).

An dieser Stelle sollte man dann auch besser die Policy für das Loopbackdevice eintragen, indem man zu dem Skript noch
spdadd 127.0.0.0/8 127.0.0.0/8 any -P in none;
spdadd 127.0.0.0/8 127.0.0.0/8 any -P out none;
hinzufügt (und dann die 127.0.0.0/8 <em>nicht</em> in <tt>/etc/ipsec.d/policies/clear</tt> einträgt).

<!--
Die Angabe der Priorität ist notwendig damit die neuen Regeln die von Pluto (mit einer irrwitzig hohen Priorität) erstellten Regeln überdecken, funktioniert jedoch laut manpage von setkey nur mit Kerneln ab 2.6.6.
-->

=Probleme=
Leider ist Opportunistic Encryption so quasi unbrauchbar, zumindest mit dem Kernel-IPsec. Wenn nämlich erstmals eine Verbindung zu einer Adresse aufgebaut werden soll, für die zur Zeit kein Policy-Eintrag existiert (also weder eine Security Association besteht, noch ein Vermerk dass der Empfänger kein IKE spricht und vorerst kein IPsec mit ihm versucht werden soll), dann erhält die auslösende Applikation für ihren <tt>connect()</tt>-Aufruf den Fehlercode <tt>EAGAIN (Resource temporarily unavailable)</tt>. Das 'temporarily' ist zwar durchaus ernst gemeint, denn wenige Sekunden später würde der Aufruf glatt durchgehen, dennoch brechen die meisten Programme an dieser Stelle mit einer Fehlermeldung ab:
henryk@gleam ~ $ ping www.spiegel.de
connect: Resource temporarily unavailable
oder
henryk@gleam ~ $ lynx http://www.hu-berlin.de/
Suche nach www.hu-berlin.de
HTTP-Verbindung zu www.hu-berlin.de wird aufgebaut.
Obacht: Verbindung zum remote Host konnte nicht hergestellt werden.
lynx: Unzugängliche Startdatei http://www.hu-berlin.de/
etc. pp.

(Das gleiche Problem tritt zwar prinzipiell auch mit 'normalem' IPsec, etwa mit X.509-Zertifikaten auf, da es dort aber nur wenige Gegenstellen betrifft, und auch die nur ein einziges mal nach jedem Reboot, wiegt es dort weniger schwer.)

=Links=
[http://www.usenix.org/publications/login/1999-12/features/harmful.html IKE/ISAKMP considered harmful]

Latest revision as of 04:28, 17 October 2005

Hardware

Beliebige Rechner, auf denen Linux mit Kernel 2.4 oder 2.6 drauf läuft.

Software

FreeS/WAN auf mindestens zwei verschiedenen Rechnern und einen DNS-Server.

Wir haben für unsere Installation Debian Sarge verwendet mit Kernel 2.6.

Mit Debian reicht ein

apt-get install freeswan

Das eigentlich aktuellere OpenS/WAN in derzeit für OE leider nicht geeignet. Zumindest bei kernel-2.6.8 besteht das Problem, dass die folgende Fehlermeldung kommt:

Sep  9 09:17:45 localhost pluto[13449]: %hold otherwise handled during DNS lookup for Opportunistic Initiation for 10.0.42.2 to 10.0.23.2

Im Verzeichnis openswan-*/doc/2.6.known-issues steht das zumindest unter CURRENT ISSUES.

Achtung: Das Initskript hat unter Debian Probleme damit, den pluto-daemon ordnungsgemäß zu beenden. Am einfachsten fügt man daher in /etc/init.d/ipsec an passender Stelle (FIXME) die Zeile

killall _plutorun pluto _plutoload _pluto_adns

ein.

Debugging-Hinweis: Bei Debian landen die Logs von pluto in der Datei /var/log/auth.log, wo man sie intuitiv eher nicht vermuten würde. Fehlersuche gestaltet sich aber leicher, wenn man die Logs hat ;-).

Keys erzeugen

Es gibt zwei unterschiedliche Varianten von OE:

Full Opportunism - beide Rechner können eine verschlüsselte Verbindung initiieren. Dazu müssen beide Rechner TXT-Records im Reverse-DNS haben. (Man muss also sein IP-Subnetz DNS-seitig unter Kontrolle haben).

Initiate-only Opportunism - es muss nur der Rechner Reverse-DNS haben, der verschlüsselte Verbindungen entgegennimmt. Der Andere darf einen Forward-DNS-Eintrag haben.


Full Opportunism

Um DNS-Einträge mit Schlüsseln zu erzeugen nimmt man ipsec mailkey. Dieses Tool generiert eine ausführbare Datei in der die TXT Records stehen, die man in das Reverse-DNS eintragen muss.

ipsec mailkey --me test@localhost --reverse 10.0.23.2

In der Datei befindet sich dann der DNS-Record:

--DNS_RESOURCE_RECORDS--

2.23.0.10.in-addr.arpa. IN      TXT     "X-IPsec-Server(10)=10.0.23.2" "lakdfklajsdfoiweruo82347.... "

--DNS_RESOURCE_RECORDS--


Initiation Only

Diesmal den Server wie oben. Und beim Client(der Rechner, der die Initiierte Verbindung initiiert) wie folgt:

ipsec mailkey --me test@localhost --forward host.domain.tld

Der Eintrag sieht dann ungefähr so aus:



--DNS_RESOURCE_RECORDS--

chunk.  IN      TXT     "X-IPsec-Server(10)=@chunk.snug.local" 
" AQOC8IcGKBb6y8+7P3WFMGSdJvkVH........"

--DNS_RESOURCE_RECORDS--


Dies jetzt zu den forward DNS-Einträgen packen.

DNS freigeben

Wenn man nun die Rechner die Records eingetragen hat, muss man noch dafür sorgen, dass DNS-Anfragen beim Aushandeln der Schlüssel nicht der OE zum Opfer fällt. Dazu trägt man am besten den DNS-Server in die Datei /etc/ipsec.d/policies/clear in Form von

a.b.c.d/32

ein.

Falls der DNS-Server lokal läuft sollte man Verschlüsselung auf dem lo-Device verbieten. Der übliche Weg dazu wäre, in die /etc/ipsec.d/policies/clear

127.0.0.0/8

einzutragen. Das führt leider dazu, dass FreeS/WAN völlig abstruse Routen setzt. (Eine Kopie der Default-Route, aber für 127.0.0.0/8, also sowas wie 127.0.0.0/8 via 10.0.23.1 dev eth0.)

Ausserdem wird der lokale DNS-Server selbst DNS-Anfragen absetzen wollen (zum Beispiel, wenn FreeS/WAN versucht, herauszufinden ob für die eigene IP wirklich ein korrekter TXT-RR existiert) was zu einer Henne-und-Ei-Situation führt: Zum Nachschlagen der Schlüssel ist DNS erforderlich, für jedweden Netzwerkverkehr müssen aber Schlüssel nachgeschlagen werden.

Die Policy-Groups von FreeS/WAN können Verkehr leider nur nach IP-Adressen einordnen und unterstützen keine weiteren Kriterien wie etwa Portnummern oder gar Paketfilter-Tags, obwohl das darunterliegende Kernel-IPsec das durchaus kann. Workaround: Man setzt die passenden Policyregeln manuell mit setkey. Dazu muss man ein setkey-Skript (zum Beispiel /usr/local/bin/dnsclear) erzeugen mit folgendem Inhalt (a.b.c.d durch die eigene IP-Adresse ersetzen):

#!/usr/sbin/setkey -f

spdadd a.b.c.d/32 0.0.0.0/0[53] udp -P out none;
spdadd a.b.c.d/32 0.0.0.0/0[53] tcp -P out none;

spdadd 0.0.0.0/0[53] a.b.c.d/32 udp -P in none;
spdadd 0.0.0.0/0[53] a.b.c.d/32 tcp -P in none;

Dieses Skript trägt man dann in /etc/ipsec.conf im Abschnitt config setup als prepluto="/usr/local/bin/dnsclear" ein. Das Skript sollte natürlich ausführbar sein (chmod a+x /usr/local/bin/dnsclear).

An dieser Stelle sollte man dann auch besser die Policy für das Loopbackdevice eintragen, indem man zu dem Skript noch

spdadd 127.0.0.0/8 127.0.0.0/8 any -P in none;
spdadd 127.0.0.0/8 127.0.0.0/8 any -P out none;

hinzufügt (und dann die 127.0.0.0/8 nicht in /etc/ipsec.d/policies/clear einträgt).


Probleme

Leider ist Opportunistic Encryption so quasi unbrauchbar, zumindest mit dem Kernel-IPsec. Wenn nämlich erstmals eine Verbindung zu einer Adresse aufgebaut werden soll, für die zur Zeit kein Policy-Eintrag existiert (also weder eine Security Association besteht, noch ein Vermerk dass der Empfänger kein IKE spricht und vorerst kein IPsec mit ihm versucht werden soll), dann erhält die auslösende Applikation für ihren connect()-Aufruf den Fehlercode EAGAIN (Resource temporarily unavailable). Das 'temporarily' ist zwar durchaus ernst gemeint, denn wenige Sekunden später würde der Aufruf glatt durchgehen, dennoch brechen die meisten Programme an dieser Stelle mit einer Fehlermeldung ab:

henryk@gleam ~ $ ping www.spiegel.de
connect: Resource temporarily unavailable

oder

henryk@gleam ~ $ lynx http://www.hu-berlin.de/

Suche nach www.hu-berlin.de
HTTP-Verbindung zu www.hu-berlin.de wird aufgebaut.
Obacht: Verbindung zum remote Host konnte nicht hergestellt werden.

lynx: Unzugängliche Startdatei http://www.hu-berlin.de/

etc. pp.

(Das gleiche Problem tritt zwar prinzipiell auch mit 'normalem' IPsec, etwa mit X.509-Zertifikaten auf, da es dort aber nur wenige Gegenstellen betrifft, und auch die nur ein einziges mal nach jedem Reboot, wiegt es dort weniger schwer.)

Links

IKE/ISAKMP considered harmful