Verschlüsselte Datenübertragung mit spiped

Einführung in den Secure Pipe Daemon

Zur sicheren Datenübertragung einzelner Nachrichten hat sich PGP/GPG etabliert. Für gesicherte, d.h. verschlüsselte Verbindungen gibt es SSH. Eine SSH-Sitzung wird jedoch unterbrochen, wenn die TCP-Verbindung abbricht. Der Secure Pipe Daemon (spiped) arbeitet als Daemon, wodurch man es mit einer beständigen, verschlüsselten Datenverbindung zu tun hat.

Im Gegensatz zu GPG und SSH kommt jedoch bei spiped eine symmetrische Verschlüsselung zum Einsatz. Der gemeinsame Schlüssel muss also vor Verbindungsaufnahme über einen sicheren Kanal ausgetauscht werden. Da spiped aus dem tarsnap-Projekt ‒ einer Online-Backup-Lösung ‒ stammt, ist es offenbar für grössere Datenmengen ausgelegt. Und hierzu ist eine symmetrische Verschlüsselung wesentlich effizienter als eine asymmetrische.

Beispiel: Sichere Datenübertragung in Mittelerde

Die Königreiche Rohan und Gondor haben Leuchtfeuer eingerichtet, um einander im Ernstfall alarmieren zu können. Leider kann mit dieser Form der Kommunikation nur wenig Inhalt ausgetauscht werden. Werden die Leuchtfeuer entfacht, weiss das andere Königreich nur, dass es ein Problem gibt, und man zur Hilfe eilen soll.

Sauron ist bekannterweise besiegt worden, und in Rohan und Gondor beschäftigt man sich nun mit dem Wiederaufbau. Hierzu möchte man gerne schnell und sicher Informationen miteinander austauschen können. Nicht nur Textnachrichten, sondern vielleicht auch Konstruktionspläne im PDF-Format.

Der symmetrische Schlüssel soll über einen berittenen Boten ausgetauscht werden. Am Terminal sitzen Eomer (Rohan) und Faramir (Gondor). Eine stabile TCP-Verbindung ist über Glasfaser gewährleistet. (Für die Fertigung der Kabel hat sich Legolas eigens eine Glatze rasiert, aber das war es ihm Wert.)

Auf zu Tod und Terminal!

Schlüsselgenerierung

Zuerst erstellt Eomer einen symmetrischen Schlüssel, wozu er /dev/urandom verwendet. 32 Bytes sollten genügen. Diese werden base64-codiert, damit man den Schlüssel besser auf Pergament schreiben kann (ja, in Mittelerde wurde aus Kompatibilitätsgründen mitlerweile auch ASCII eingeführt):

$ dd if=/dev/urandom of=/dev/stdout bs=1 count=32 2>/dev/null | base64 | tee secret.key
jZNVa1at1EBA+Kqk7Xx7mD5N9X2KZCZ61uUv594qen4=

Dieser Schlüssel wurde nun nach Gondor überbracht, sodass es auf beiden Seiten ein secret.key mit dem gleichen Inhalt gibt.

spiped starten

Wir benötigen zwei Kanäle:

  1. einen verschlüsselnden Kanal von Rohan nach Gondor
  2. einen entschlüsselnden Kanal innerhalb von Gondor

Wir beschränken uns auf die Einweg-Kommunikation von Rohan nach Gondor. Der Rückweg erfolgt analog dazu.

Den verschlüsselnden Kanal öffnen

Der verschlüsselnde Kanal wird folgendermassen aufseiten von Rohan eingerichtet (Voraussetzung: spiped ist installiert):

eomer@rohan:~$ spiped -e -s 0.0.0.0:2000 -t gondor:3000 -k secret.key

Der Parameter -e steht für “encrypt” (“verschlüsseln”). Die Parameter -s und -t stehen für “source” (“Quelle”) und “target” (“Ziel”). Mit -k wird die Datei mit dem Schlüssel (“key”) angegeben. Der Prozess wurde automatisch als Daemon in den Hintergrund verschoben.

Aufseiten von Gondor könnte nun auch der entschlüsselnde Kanal eingerichtet werden. Zuerst soll aber einmal die Verschlüsselung getestet werden.

Daten mit netcat übertragen

Für die Datenübertragung benötigt man ein Werkzeug wie netcat, das bei einer Debian-Standardinstallation unter netcat-traditional schon dabei sein sollte.

Versuchen wir zuerst einmal eine Übertragung ohne Entschlüsselung, um sicherzustellen, dass kein Klartext ankommt, und dass die Verbindung steht. Hören wir also aufseiten von Gondor auf Port 3000:

faramir@gondor:~$ nc -l -p 3000

Dieser Befehl (-l steht für “listen”, d.h. “horchen”, mit -p definiert man den Port) wartet nun blockierend auf Nachrichten, die auf Port 3000 ankommen.

Aufseiten von Rohan wird nun eine Nachricht geschickt:

eomer@rohan:~$ echo 'Mir hen koi Leberkäs me.' | nc localhost 2000

Die dann ungefähr folgendermassen aufseiten von Gondor eintrifft:

��16�����O����(�0       訣R��▒�n���

(Tipp: Mit reset kann das Terminal zurückgesetzt werden, falls es durch bestimmte Bytes etwas irritiert worden ist.)

Den entschlüsselnden Kanal öffnen

Die Verschlüsselung funktioniert offenbar. Jetzt wollen wir aber die Meldungen auch entschlüsseln können. Aufseiten von Gondor wird nun der entschlüsselnde Kanal geöffnet:

faramir@gondor:~$ spiped -d -s 0.0.0.0:3000 -t 127.0.0.1:4000 -k secret.key

Und wieder horcht man in Gondor aufmerksam, nun aber auf Port 4000:

faramir@gondor:~$ nc -l -p 4000

In Rohan sendet man einen weiteren Notruf aus:

echo 'Auch d Herrgottsbscheisserle sind ausgange.' | nc 127.0.0.1 2000

Der nun in Gondor entschlüsselt werden kann:

Auch d Herrgottsbscheisserle sind ausgange.

Eine Datei übertragen

Da man in Gondor nicht genau verstanden hat, was da in Rohan ausgegangen ist, schickt man kurzerhand eine Abbildung vom gewünschten Gut (leberkaes.jpg):

In Gondor horcht man schon gespannt:

faramir@gondor:~$ nc -l -p 4000 > leberkaes.jpg

Und in Rohan macht man sich an die Übertragung:

eomer@rohan:~$ nc -q 1 127.0.0.1 2000 <leberkaes.jpg

Das hat geklappt!

faramir@gondor:~$ file leberkaes.jpg
leberkaes.jpg: JPEG image data […]

Die sichere Verbindung steht. Jetzt braucht es nur noch einen sicheren Transportweg für Waren. Aber das ist nicht mehr unsere Abteilung…

Ports öffnen

Falls das obige Beispiel nicht wie geschildert funktioniert, liegt es möglicherweise daran, dass Port 3000 aufseiten von Gondor nicht geöffnet ist. Mithilfe von ufw kann das folgendermassen bewerkstelligt werden:

faramir@gondor:~$ sudo su -
# root@gondor:~# ufw allow 22/tcp
# root@gondor:~# ufw allow 3000/tcp
# root@gondor:~# ufw enable

Port 22 (SSH) wurde sicherheitshalber auch gleich mitgeöffnet, um ein Aussperren vom Server beim nächsten SSH-Verbindungsversuch zu verhindern.

Übungen

In diese Beitrag wurde v.a. der grundlegenden Mechanismus erklärt. Rein praktisch gibt es sicherlich noch Diskussionsbedarf: Ist die Schlüsselgenerierung sinnvoll? Wie könnte man sonst noch Daten übertragen, d.h. nicht mit nc, sondern etwas komfortabler? Wie macht man das mit der Firewall? Warum nutzt man nicht einfach scp? Gibt es weitere Verwendungszwecke für spiped?