6.4. Austausch der SSH-Keys (DaSo)
Aber wie werden die Geräte verbunden? SSH funktioniert mit bestimmten Dateien, die sich normalerweise im Home-Verzeichnis des Benutzers unter “~/.ssh/” befinden. Die wichtigsten Dateien sind “authorized_keys” und “known_hosts”, sowie das kryptographische Schlüsselpaar “id_rsa” und “id_rsa.pub”. Anhand dieser 4 Dateien lässt sich ein SSH-Netzwerk beschreiben und das Aufbauen des Netzwerks erfordert lediglich das richtige Befüllen der Dateien.
Im normalen Betrieb ist tatsächlich keine der oben genannten Dateien notwendig. Es reicht vollkommen aus, eine SSH-Sitzung aufzubauen, ohne jemals eine dieser Dateien erstellt oder ausgefüllt zu haben, solange auf dem Host ein SSH-Service läuft und er im Netzwerk erreichbar ist. Allerdings werden bei diesem Ansatz einige zusätzliche Anforderungen an den Anwender gestellt. Die erste Hürde ist das Akzeptieren des Fingerprints der Host-Maschine. Dies beugt dem Risiko einer Man-in-the-Middle Attacke entgegen, indem die IP des Host mit einer eindeutigen Identifikation assoziiert und in “known_hosts” abgelegt wird. Nachdem die Schulgeräte sich automatisiert, mit möglichst wenig Nutzerinteraktion verbinden sollen, sollte das Beschreiben der “known_hosts” nicht durch den Benutzer erfolgen. Nachdem dies aber geschehen ist, muss man nun das Passwort des Benutzers auf der Host-Maschine eingeben. Im Kontext unserer Geräte- und Betriebssystemeigenschaften ist unser Standardbenutzer “edu” allerdings nicht passwortgeschützt. Dies würde es jedem der sich in dem gleichen Netzwerk wie der Host befindet ermöglichen, sich zu verbinden und allerlei unbefugte Operation durchzuführen. Um dieses Risiko zu verhindern, müssen Verbindungen und Authorisierungsversuche durch ein Passwort unterdrückt werden. Dies geschieht durch die Einstellung “PasswordAuthentication no” in “/etc/ssh/sshd_config”. Somit sollen nur zusammengehörende Schlüsselpaare als Autorisierung akzeptiert werden. Hier kommen “authorized_keys”, “id_rsa”, und “id_rsa.pub” ins Spiel.
“id_rsa” ist der Private-Key. Dieser sollte niemals weitergegeben werden.
“id_rsa.pub” ist der Public-Key. Dieser muss an Hosts weitergegeben werden.
In “authorized_keys” stehen Public-Keys der Clients. Besitzt ein Client den passenden Private-Key zu einem Eintrag in der “authorized_keys”, so wird die Verbindung zugelassen.
Was also geschehen muss, um eine nahtlose Verbindung aufbauen zu können ist:
Kryptographisches Schlüsselpaar generieren
Validen “known_hosts” Eintrag von allen Geräten auf allen Geräten erstellen
Hier stehen dann bereits die IP-Adressen aller Geräte, um diese später ausfindig zu machen
Public-Keys aller Geräte in die “authorized_keys” aller Geräte eintragen
SSH bietet bereits einige Tools zum Lösen der Aufgaben.
“ssh-keygen” kann benutzt werden um das Schlüsselpaar zu generieren.
“ssh-keyscan” kann benutzt werden um einen “known_hosts” Eintrag anhand der IP des anderen Gerätes zu erstellen.
Im Rahmen dieses Projekts wurde außerdem ein Tool erstellt, welches mithilfe einiger Pythonskripte die oberen Anforderungen abarbeitet. Dieses ist als Debianpaket in der Distribution vorhanden und wird mit dem Kommando “edux-com” gesteuert.
Um zwei Geräte miteinander zu verbinden, werden zwei verschiedene Skripte benötigt. Das Austauschen der Public-Keys wird durch einen Webserver realisiert. Dazu muss eins der Geräte die Rolle des Servers und das andere die Rolle des Clients übernehmen. Mithilfe eines HTTP-Post Requests wird hier der Public-Key des Client an den Server und der Public-Key des Servers per Response an den Client gesendet. Dies erfordert natürlich das übergeben der Server-IP an den Client, was durch den Anwender geschehen muss. Die zugehörigen “known_hosts” Einträge werden mit der durch den Request bekannten IP-Adresse erstellt.
Im Hinblick darauf, dass jedes Gerät jedes andere direkt kennen, also Public-Keys ausgetauscht und “known_hosts” Einträge erstellt haben soll, werden bei Request und Response nicht nur die eigenen Public-Keys, sondern alle bereits bekannten Keys und “known_hosts” mitgegeben. Diese werden beim gegenüber mit den dort bereits bekannten verglichen und bei Bedarf hinzugefügt. Außerdem kann der Server bereits bekannten Geräten die Information per SSH mitteilen.
Der komplette Ablauf der Skripte:
Server |
Client |
---|---|
1. Schlüsselpaar generieren (“ssh-keygen”), wenn nicht bereits geschehen |
1. Schlüsselpaar generieren (“ssh-keygen”), wenn nicht bereits geschehen |
2. Webserver hochfahren |
|
3. POST “authorized_keys” incl. eigenen Public-Key. (Hier wird die IP des Servers benötigt) |
|
4. Erhaltene “authorized_keys” sich selbst hinzufügen. Duplikate streichen. |
|
5. Per SSH allen bekannten Geräten die neuen Keys eintragen |
|
6. RESPONSE “authorized_keys” incl. eigenen Public-Key |
|
7. Erhaltene “authorized_keys” sich selbst hinzufügen. Duplikate streichen. |
|
8. POST “known_hosts” |
|
9. “known_hosts” Eintrag anhand der IP des Senders generieren (“ssh-keyscan”) |
|
10. Erhaltene “known_hosts” sich selbst hinzufügen. Duplikate streichen. |
|
11. Per SSH allen bekannten Geräten die neuen “known_hosts” Einträge eintragen |
|
12. RESPONSE “known_hosts” |
|
13. Server herunterfahren |
13. “known_hosts” Eintrag anhand der IP des Serversgenerieren (“ssh-keyscan”) |
14. Erhaltene “known_hosts” sich selbst hinzufügen. Duplikate streichen. |
Nach dem im besten Fall Ablaufen der Skripte, besitzt jedes Gerät im Netzwerk nun den neuen Client oder sogar das komplette Netzwerk, in dem der Client bereits verbunden war. Allerdings lässt es sich nicht realistisch garantieren, dass ausnahmslos jedes Gerät zur Zeit der Ausführung auch online und erreichbar für die SSH Verbindungen des Servers war und die neuen Information erhalten hat. Aus diesem Grund existiert ein “Update”-Skript, welches auf einem Gerät ausgeführt werden kann, um Neuerungen in der Netzwerkstruktur zu erkennen und entsprechend sich die nötigen Informationen zu holen. Realisiert wird dies durch das iterative “Nachschauen” bei allen bereits bekannten Hosts, ob diese noch unbekannte “authorized_keys” oder “known_hosts” Einträge besitzen und solche sich selbst hinzuzufügen, wenn man sie noch nicht kennt.
Dieses Update-Skript skaliert schlecht mit größeren Netzwerken bezüglich der Laufzeit, da von jedem im Netzwerk jeder Eintrag mit jedem eigenen Eintrag verglichen werden muss. Das ganze zweimal für “authorized_keys” und “known_hosts”. Hinzu kommt, dass die Dateien mit ihren Einträgen, auf Grund des “jeder kennt jeden” Prinzip, sehr lang werden. Das Skript eignet sich also mehr als “einmal beim Boot” oder “erster Fix” falls etwas im Netzwerk schief geht.
Diese drei Skripte reduzieren die am Anfang genannten Anforderungen lediglich auf die Beigabe der IP-Adresse des Gerätes, welches die Rolle des Servers übernimmt. Dieses Problem wird im Frontend der Welcome-Page, durch eine Codierung der IP in eine leicht lesbare Zeichenfolge, behandelt. Im Anschluss können nun die Geräte frei miteinander kommunizieren, solang sie im Netzwerk erreichbar sind.
Des Weiteren ist noch anzumerken, dass der Verbindungsprozess ein Sicherheitsrisiko birgt. Es werden ohne weitere Kontrolle “known_hosts” und Public-Keys überall eingetragen und als sicher abgestempelt. Würde ein böswilliges Gerät sich während diesem Prozess verbinden, könnte dieses über SSH Schaden an jedem Gerät im Netz anrichten. Aufgrunddessen ist es wichtig, dass der Zugang zum Starten des Servers durch ein Passwort (in diesem Projekt durch das Lehrerpasswort) geschützt ist.