SSH-Agenten auf Headless-Servern automatisch starten
Auf Headless-Servern1 ist üblicherweise kein SSH-Agent vorinstalliert. Wer SSH-Schlüssel bei der Arbeit am Server im Arbeitsspeicher vorhalten möchte, muss daher den SSH-Agenten manuell starten. Die Lebenszeit des SSH-Agenten ist allerdings nicht an die Zeit der aktuellen Sitzung gebunden, das heißt, er besteht nach Beenden der Sitzung fort. Die Verbindungsdaten hingegen gehen bei naiver Verwendung nach der Sitzung verloren, wenn sie lediglich in Umgebungsvariablen gespeichert wurden. Des weiteren ist die Verwendung mehrerer Instanzen des SSH-Agenten ggf. unerwünscht, da jede Instanz ggf. unterschiedliche Schlüssel in den Speicher geladen hat und eine Passworteingabe mehrfach vonnöten ist.
In diesem Artikel erläutere ich daher wie der SSH-Agent auf einem Headless-Server verwendet werden kann, ohne bei jeder neuen Sitzung manuell eine neue Instanz starten zu müssen.
Die Konfiguration von SSH mit kryptographischen Schlüsseln erläutere ich näher in meinem Artikel Tipps und Tricks: SSH.
Benutzungsmodi von ssh-agent
Der SSH-Agent wird mit dem Befehl ssh-agent
gestartet. Generell bietet die Anwendung zwei Nutzungsvarianten:
ssh-agent
startet einen permanent laufenden Hintergrunddienst, gibt die Verbindungsparameter auf der Konsole aus und terminiert.ssh-agent command [arg ...]
startet einen SSH-Agenten im Hintergrund und führt den Befehlcommand
mit den gegebenen Argumenten aus. Dieser gestartete Kindprozess erhält die die zur Verbindungsaufnahme nötigen Umgebungsvariablen. Der SSH-Agent terminiert, sobaldcommand
terminiert.
Nutzung von ssh-agent
als Hintergrunddienst
Wie im folgenden Sitzungsprotokoll zu sehen, startet ssh-agent
den SSH-Agenten-Dienst im Hintergrund, gibt ssh-agent
die Verbindungsparameter auf der Kommandozeile aus und gibt den Kontrollfluss sofort wieder dem Benutzer zurück.
|
|
Dieser Modus ist laut dem Handbuch für Login-Sitzungen gedacht. Die Ausgabe von ssh-agent
ist valider Shell-Code und kann mittels des Builtin eval
ausgeführt werden, wodurch die Verbindungsparameter als Umgebungsvariablen der aktuellen Sitzung zur Verfügung gestellt werden.
Nutzung von ssh-agent
als Elternprozess
Für die Verwendung als Elternprozess einer X-Sitzung gedacht ist die Verwendung von ssh-agent
mit Argumenten. Wird dem Befehl ein Argument übergeben, so startet ssh-agent
einen SSH-Agenten im Hintergrund, setzt die zur Verbindungsaufnahme nötigen Parameter als Umgebungsvariablen und führt ssh-agent
das übergebene Programm aus. Das als Kindprozess von ssh-agent
gestartete Programm kann auf die Umgebungsvariablen mit den Verbindungsparametern zugreifen.
Dieses Verhalten wird aus folgendem Sitzungsprotokoll ersichtlich. Da der Befehl ssh-agent
mit dem Programm bash
gestartet wird, öffnet sich eine neue interaktive Shell. Deshalb unterscheiden sich die Prozess-IDs vor und nach der Ausführung von ssh-agent bash
. Innerhalb dieser interaktiven Shell sind die nötigen Verbindungsparameter des SSH-Agenten verfügbar und der Prozess des SSH-Agenten ist aktiv. Nach dem Schließen dieser Sitzung befindet sich der Nutzer wieder in der ursprünglichen Sitzung, die Umgebungsvariablen mit den Verbindungsparametern sind nicht mehr verfügbar und auch der SSH-Agenten ist terminiert.
|
|
Systemkonfiguration
In diesem Kapitel möchte ich mögliche Systemkonfigurationen vorstellen, die
- den SSH-Agenten ohne Zutun im Hintergrund starten, und
- pro Benutzer/Sitzung maximal einen einzigen SSH-Agenten-Prozess verwenden.
Skript zum Starten einer Instanz von ssh-agent
Die grundlegende Idee des Skriptes ist es die Verbindungsdaten für den SSH-Hintergrunddienst in einer Datei abzuspeichern und beim Öffnen einer neuen Sitzung diese Datei zunächst zu überprüfen. Da die darin enthaltenen Sitzungsdaten u.U. ungültig sein können, sind einige Überprüfungen nötig. Der folgende Code-Block enthält eine mögliche Implementierung dieser Idee.
|
|
Dieser Code liest die Verbindungsdaten des SSH-Agenten standardmäßig aus der Datei ~/.local/state/ssh/ssh_agent_env
aus. Falls diese Datei nicht existiert oder die darin angegebene Prozess-ID des SSH-Agenten ungültig ist, wird ein neuer Agenten-Prozess gestartet und die Verbindungsdaten in obiger Datei abgelegt. Abschließend werden die konfigurierten Schlüssel geladen, falls der Wert der Einstellung AddKeysToAgent
nicht yes
ist.
Es empfiehlt sich, diesen Code in einem Shell-Skript abzuspeichern und in ~/.bashrc
zu laden, damit der SSH-Agent in jedem Kommandozeilensitzung vorhanden ist.
Die Konfiguration AddKeysToAgent yes
in der Benutzer- oder Systemkonfiguration (siehe “Konfiguration des SSH-Clients”) bewirkt ein automatisches Laden eines Schlüssel in den Agenten, sobald dieser verwendet wird. In dem Falle ist die vorherige Ausführung von ssh-add
nicht mehr vonnöten.
SSH-Agent als System-Dienst
Anstatt ssh-agent
mit dem oben beschriebenen Skript in der ~/.bashrc
zu laden, kann der SSH-Agent auch mittels systemd gestartet und verwaltet werden. systemd ist ein Systemprogramm, welches bei der Mehrheit der aktuellen Linux-Distributionen u.a. die Verwaltung von Hintergrunddiensten übernimmt.
Die Registrierung eines Dienstes bei systemd erfolgt mittels einer Konfigurationsdatei. Systemdienste werden üblicherweise vom Systemverwalter im Verzeichnis /etc/systemd/system
abgelegt. Da einfache Benutzer auf dem System üblicherweise keine Schreibrechte auf Systemverzeichnisse haben (sollten), können sie alternativ die Konfigurationsdatei im Verzeichnis ~/.config/systemd/user
speichern. Dieses Verzeichnis muss ggf. zunächst erstellt werden.
Der folgende Shell-Code konfiguriert einen SSH-Agenten als systemd-Dienst:
|
|
Hierin wird dem Dienst ssh-agent
ein eindeutig bestimmter Pfad für den Socket übergeben. %t
wird dabei durch das Verzeichnis ersetzt, in dem dem Benutzer zugehörige Laufzeitdateien abgelegt werden. Dieses entspricht dem Wert der Umgebungsvariable $XDG_RUNTIME_DIR
. Der Dienst wird automatisch bei Anmeldung des Benutzers gestartet und die Laufzeit des Hintergrunddienstes kann mittels der durch systemd zur Verfügung gestellten Befehle gesteuert werden.
Anschließend muss der Benutzer manuell den Wert von $SSH_AUTH_SOCK
setzen, damit SSH-Clients die Verbindung zum Agenten aufnehmen können. Eine Möglichkeit hierzu ist:
|
|
Die Dateien im Verzeichnis environment.d enthalten Definition von Umgebungsvariablen und werden von systemd beim Start eingelesen. Nach einem Neuladen der systemd-Dienste kann der neue Dienst gestartet werden:
|
|
Diese Lösung wurde StackExchange Unix&Linux vorgestellt.
Sicherheit
Um die Wahrscheinlichkeit eines Missbrauchs zu reduzieren, empfiehlt es sich, einen Timeout für die Schlüssel zu setzen. Die Anwendungen ssh-agent
und ssh-add
bieten hierzu die Option -t
, mit welcher eine Zeit in Sekunden definiert werden kann, die die entsperrten Schlüssel maximal im Speicher verweilen können.
Ein Server ohne graphische Oberfläche ↩︎