Da auf meinen Servern mittlerweile doch so einiges an wichtigen Daten herumliegt möchte ich mein SSH Login dort stärker absichern.
Hierbei kam mir der Gedanke, ob es nicht möglich ist, den SSH Schlüssel auf ein Hardwaregerät auszulagern.
Wichtig war mir, dass ich die SSH Schlüssel auf Linux und Windows Rechnern sowie auch innerhalb einerWSL2 Umgebung auf Windows verwenden kann.
Mit dem Yubikey 5 NEO [1] hatte ich hierfür auch bereits ein scheinbar geeignetes Device herumliegen.
Schlüsselerzeugung
Für die Verwendung als SSH Schlüssel wird die Smartcard Funktion des Yubikey verwendet. Hierfür muss auf dem Gerät ein Zertifikat erzeugt werden. Der private Schlüssel bleibt dabei dauerhaft auf dem Yubikey und verlässt diesen niemals.
Als Werkzeuge hierfür wird die Yubikey Manager Applikation [2] sowie unter Windows zusätzlich der SmartCard Treiber benötigt.
Alternativ zu der hier beschriebenen Vorgehensweise erklärt das WinCryptSSHAgent WSL Tutorial [4]
Der Yubikey besteht intern aus mehreren Applikationen. In diesem Falle verwenden wir die Applikation „PIV“.
PIN / PUK und Management Key sind idealerweise bereits gesetzt.
Die Zertifikate (und damit auch unser zukünftiger SSH Key) befinden sich unter den Punkt „Certificates“.
Für die SSH Anmeldung benötigen wir ein Zertifikat vom Typ „Authentication“, dieses wird den SSH Schlüssel enthalten.
Da das Zertifikat für den Schlüssel nur ein Container ist, reicht hier ein Self-Signed certificate
Der Yubikey kann RSA und ECCP Schlüssel erzeugen, beide können als SSH Schlüssel verwendet werden.
Da RSA Schlüssel nur mit einer Länge von 2048 erzeigt werden, entscheide ich mich für einen ECCP Schlüssel mit der maximal angebotenen Länge.
Hierdurch wird ein SSH Schlüssel vom Typ „ecdsa-sha2-nistp384“ erzeugt.
Das Subject ist ein lesbarer Bezeichner für den Schlüssel. Dieser Bezeichner taucht später auch mit in dem SSH Schlüssel auf.
Da SSH-Schlüssel im Gegensatz zu Zertifikaten kein Ablaufdatum kennen, macht es auch keinen Sinn, wenn das Zertifikat ausläuft.
Nach dieser Zusammenfassung müssen dann noch der Management Key und die PIN eingegeben werden, anschließend wird das Zertifikat erzeugt.
Windows
Unter Windows werden di folgenden beiden Komponenten benötigt:
- Der SmartCard Treiber von Yubibo [2]
- Das Tool WinCryptSSHAgent [3]
Bei dem WinCryptSSHAgent handelt es sich um ein kleines Hilfstool, dass die Schlüssel aus dem Yubikey für verschiedene SSH-Clients über eine SSH-Agent [5] kompatible Schnittstelle verfügbar machen kann.
Der WinCryptSSHAgent ist hierbei sowohl mit dem Windows Tool PuTTY [6] als auch dem nativen SSH Clients kompatibel.
Wenn beide Tools installiert sin, können wir zuerst prüfen, ob der Yubikey von Windows korrekt erkannt wird.
Hierzu wird der Yubikey in den USB-Port gesteckt, anschließend öffnen wir die Zertifikatverwaltung für den aktuellen Benutzer mit dem Kommando „certmgr.msc“.
Unter eigene Zertifikate sollte jetzt ein Zertifikat mit unserem bei der Erstellung vergebenen Namen angezeigt werden.
Hierbei handelt es sich nur um einen Platzhalter, das eigentliche Zertifikat (und vor allem der private Schlüssel) bleiben weiterhin auf den Yubikey.
Als nächstes starten wir den WinCryptSSHAgent.
Hierbei passiert erst mal nicht allzu viel .. das Tool wird lediglich als Ion in der Taskleiste angezeigt.
Über die Option „Show Public Keys“ können wir die geladenen SSH Schlüssel anzeigen lassen und in die Zwischenablage kopieren.
Mit PuTTY [6] ist die Verwendung besonders einfach.
Der gestartete WinCryptSSHAgent wird automatisch erkannt und beim Aufbau einer Verbindung wird automatisch versucht die geladenen Schlüssel zu verwenden.
Beim ersten mal fragt WinCryptSSHAgent dann den PIN für den Yubikey ab.
Die PIN bleibt für die Dauer eurer Windows Session gespeichert, so dass die Eingabe nicht bei jeder Verwendung erfolgen muss.
Dieses Verhalten kann optional auch anders eingestellt werden, jedoch nur zusammen mit der Erstellung eines Schlüssels.
Jede Verwendung des Schlüssels quittiert der WinCryptSSHAgent mit einer kurzen Info-Meldung.
Auch MobaXterm [8] erkennt den gestarteten Agent automatisch.
Für OpenSSH in MinGW/Cygwin bzw. den Windows Port WinSSH müssen Umgebungsvariablen gesetzt werden.
Der WinCryptSSHAgent zeigt die dafür notwendigen Kommandozeilenbefehle nach einen Rechtsklick auf das Icon an.
Um die Keys in einer im WSL2 Umgebung zu nutzen ist ein kleines Start Script notwendig. Auch dieses gibt uns der WinCryptSSHAgent bereitwillig nach einem Klick auf die entsprechenden Menüeintrag.
Dieses kann man sich am besten in eine Startkonfiguration integrieren.
Anschließend kann man auch in der WSL2 Umgebung ebenfalls ganz regulär eine SSH Verbindung aufbauen.
Auch die Verwendung von Tools, die auf SSH Aufbauen wie Git und Ansible ist problemlos möglich
Verbessertes Key-Handling unter Windows
Da ich selber mehr als einen Yubikey verwende (einer ist immer an meinem Arbeitsplatz in meiner Wohnung, einen habe ich unterwegs am Schlüsselbund dabei) entsteht unter Windows ein interessanter Nebeneffekt:
Beide SSH Schlüssel sind als Dummy-Zertifikate im Zertifikatsstore gespeichert und damit auch im WinCryptSSHAgent geladen.
Der SSH Agent versucht jetzt bei einer Authentifizierung einen Schlüssel nach dem anderen zu verwenden, hierbei kommt es aber zu einer Fehlermeldung da auf den jeweils nicht eingesteckten Schlüssel ja nicht zugegriffen werden kann.
Um diese Fehlermeldung zu Umgehen und dem WinCryptSSHAgent zu zwingen immer nur den gerade eingesteckten Schlüssel zu nutzen, müsste jedes mal manuell das Dummy-Zertifikat aus dem Windows Zertifikatsspeicher gelöscht werden, wenn auch zwischen den Hardware-Schüsseln ein Wechsel erfolgt.
Mit Hilfe eines kleinen PowerShell Scriptes lässt sich diese Aktion jedoch auch automatisieren.
Hierfür benötigen wir mindestens PowerShell Core in der Version 7 sowie das Yubikey .NET SDK [9].
In einem Ordner unserer Wahl legen wir die Dateien aus [9] sowie eine Scriptdatei Yubikey_Certremover.ps1 an.
Das Script muss entsprechend auf die Anzahl der verwendeten Schlüssel, die Seriennummern und die Zertifikatsnamen angepasst werden.
# Load Yubikey .NET SDK DLLs
Add-Type -Path .\Yubico.YubiKey.dll
Add-Type -Path .\Yubico.Core.dll
# Get connected Yubikey Devices
$YubiKeyDevices = [Yubico.YubiKey.YubiKeyDevice]::FindAll()
# Uncomment to Output currently connected Yubikey Devices
# $YubiKeyDevices
# If first Yubikey is not connected, remove the Certificate from Windows certificate store
$YubiKey1 = $YubiKeyDevices | Where-Object { $_.SerialNumber -eq „16xxxxxx“ }
if ($YubiKey1.Length -ne 1) {
Write-Host „remove chel-yk5-01“
Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -match ‚chel-yk5-01‘ } | Remove-Item
}
# If second Yubikey is not connected, remove the Certificate from Windows certificate store
$YubiKey2 = $YubiKeyDevices | Where-Object { $_.SerialNumber -eq „15xxxxxx“ }
if ($YubiKey2.Length -ne 1) {
Write-Host „remove chel-yk5-02“
Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -match ‚chel-yk5-02‘ } | Remove-Item
}
Wenn das Script dann in der Kommandozeile ausgeführt wird, werden jeweils alle Dummy-Zertifikate, deren Yubikey nicht eingesteckt ist aus dem Zertifikatsstore entfernt.
Im Folgenden Beispiel sind aktuell beide Dummy-Zertifikate vorhanden, es ist aber nur der Yubikey des Zweiten Schlüssels eingesteckt:
Als letzter Schritt muss jetzt nur noch das Script automatisch beim Einstecken eines Yubikeys gestartet werden.
Hierfür hilft uns die Windows Aufgabenplanung. Hier legen wir uns eine neue Aufgabe an.
Unsere Aufgabe wird nur ausgeführt, wenn unser Benutzer angemeldet ist.
Der Trigger reagiert auf das Eventlog mit den hier gezeigten Einstellungen.
Als Aktion wird hier unser Script gestartet.
Die eigentlich gestartete Anwendung ist die PowerShell, das Script wird als Parameter übergeben.
Wichtig ist, dass hierbei der Parameter „Starten in“ auf das Verzeichnis, in dem Unser Script und die DLLs liegen gesetzt wird.
Unser Script wird jetzt immer beim Einstecken eines Yubikeys ausgeführt und löscht die Schlüssel der jeweils anderen Yubikeys.
Das Kommandozeilenfenster erscheint hierbei für ca. 1 Sekunde.
Linux
Auf Linux Systemen ist die Verwendung des SSH Schlüssels ähnlich einfach [10]. Seitens des Herstellers gibt es ein PKCS#11 Modul für OpenSSH.
Auf einem Debian basierten System kann dieses Modul mittels
sudo apt-get ykcs11
installiert werden. Der Pfad der Datei libykcs11.so kann möglicherweise abweichend sein.
Nach dem Einstecken des Yubikeys kann dann direkt mittels
ssh -I /usr/lib/x86_64-linux-gnu/libykcs11.so root@10.5.0.123
eine Verbindung aufgebaut werden.
Alternativ kann die Option auch in der Konfigurationsdatei ~/.ssh/config ergänzt werden:
PKCS11Provider /usr/lib/x86_64-linux-gnu/libykcs11.so
Es ist auch möglich den Schlüssel in den SSH-Agenten zu laden. Der Nachteil ist allerdings, dass der PIN beim Landen des Keys abgefragt wird.
ssh-add -s /usr/lib/x86_64-linux-gnu/libykcs11.so
Verwendung in Kombination mit Git
Die Versionskontrolle Git [11] nutzt intern maßgeblich SSH für die Verbindung zum Repository-Server.
Auf Linux-Systemen greifen die Implementierungen hier einheitlich auf den SSH Client des Systems und die jeweiligen Einstellungen bzw. den gestarteten SSH-Agent zurück, so dass es hier keine Besonderheiten zu beachten gibt.
Unter Windows hängt es von den Jeweils verwendeten Tools ab ob ggf. eine zusätzliche Konfiguration notwendig ist.
Bei der Verwendung des Grafischen Tools TortoiseGit [12] ist keine weitere Konfiguration notwendig, da hier standardmäßig PuTTY [6] bzw. dessen Tool plink.exe als SSH Client verwendet wird, welches den Vorhandenen SSH-Agent mit den Schlüsseln automatisch erkennt.
Um Git in der Windows Kommandozeile und damit auch innerhalb von Tools wie VSCode [13] zu einer Zusammenarbeit zu bewegen, ist eine Umgebungsvariable notwendig: Die Umgebungsvariable GIT_SSH muss einen vollständigen Pfad für das Tool plink.exe aus einer bestehenden PuTTY [6] Installation enthalten. Hierdurch wird erzwungen, dass auch bei Git-Operationen in der Kommandozeile und innerhalb anderer Tools plink.exe für die SSH Verbindung verwendet wird.
Am Beispiel eines SSH-Agent, der aus Keepass heraus gestartet wird, beschreibt der Artikel [12] dieses Vorgehen ausführlicher.
Quellen
- [1] Yubico: https://www.yubico.com/products/
- [2] Yubico Software Downloads: https://www.yubico.com/support/download/smart-card-drivers-tools/
- [3] WinCryptSSHAgent: https://github.com/buptczq/WinCryptSSHAgent
- [4] WinCryptSSHAgent WSL Tutorial: https://github.com/buptczq/WinCryptSSHAgent/blob/master/doc/wsl_tutorial.md
- [5] SSH Agent: https://en.wikipedia.org/wiki/Ssh-agent
- [6] PuTTY: https://www.chiark.greenend.org.uk/~sgtatham/putty/
- [7] PIV PIN and touch policies: https://docs.yubico.com/yesdk/users-manual/application-piv/pin-touch-policies.html
- [8] MobaXterm: https://mobaxterm.mobatek.net/
- [9] Yubikey .NET SDK: https://github.com/darrenjrobinson/YubiKey
- [10] Yubico PKCS11: https://developers.yubico.com/PIV/Guides/SSH_with_PIV_and_PKCS11.html
- [11] Git Homepage: https://git-scm.com/
- [12] TortoiseGit: https://tortoisegit.org/
- [13] VSCode und SSH-Agent: https://www.geekbundle.org/visual-studio-code-unter-windows-mit-ssh-agent-nutzen/