Sobald SSH nur mit Keys eingerichtet ist, kommt oft der nächste Vorschlag: Zwei-Faktor-Authentifizierung zusätzlich zum Key, ein TOTP-Code aus einer Authenticator-App, zusätzlich zum privaten Schlüssel erforderlich. Das wird als naheliegender nächster Schritt präsentiert, mehr Faktoren, mehr Sicherheit. Das ist nicht falsch, aber es lohnt sich, konkret zu benennen, welche Bedrohung das eigentlich adressiert, denn das entscheidet, wo sich der zusätzliche Aufwand lohnt und wo nicht.
Wogegen es tatsächlich schützt
SSH nur mit Keys bedeutet schon, dass ein erratenes, geleaktes oder gephishtes Passwort niemandem Zugang verschafft, es gibt kein Passwort zu stehlen. Der zusätzliche Schutz von SSH-2FA richtet sich speziell gegen den Fall, dass der private Schlüssel selbst kompromittiert wird, von einem Laptop gestohlen, aus einem unverschlüsselten Backup kopiert, oder von einer Maschine genutzt, die auf andere Weise kompromittiert wurde. Passiert das, reicht der Schlüssel allein nicht, der Angreifer braucht zusätzlich den TOTP-Code, der auf einem separaten Gerät liegt.
Das ist ein reales Szenario, Laptops werden gestohlen, Backups falsch konfiguriert, und "der Key liegt auf einer verschlüsselten Disk, also passt das schon" setzt voraus, dass die Festplattenverschlüsselung tatsächlich konfiguriert ist und der Laptop gesperrt war. Aber es ist ein spezifisches Szenario, und es lohnt sich, klarzustellen, dass genau dieses Szenario adressiert wird, nicht "SSH-Sicherheit im Allgemeinen", die mit Key-only-Auth schon ziemlich gut abgedeckt ist.
Die Einrichtung
pam_google_authenticator ist der gängige Weg, TOTP unter Linux zu SSH hinzuzufügen:
apt install libpam-google-authenticator
google-authenticator
Das erzeugt ein Secret (als QR-Code für eine Authenticator-App angezeigt) und einen Satz Backup-Codes. Danach müssen SSH und PAM angewiesen werden, es zu verlangen:
# /etc/pam.d/sshd
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config
AuthenticationMethods publickey,keyboard-interactive
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive ist die entscheidende Zeile, sie verlangt beides, den Key und die TOTP-Abfrage, nicht eins von beiden. Das falsch zu machen (zum Beispiel AuthenticationMethods auf dem Standard unverändert zu lassen) kann zu einem Setup führen, das jeden der beiden Faktoren allein akzeptiert, was den ganzen Zweck zunichtemacht, also lohnt es sich, das in einem zweiten Terminal zu testen, bevor man sich aus dem ersten ausloggt.
Wo es im Weg steht
Der zusätzliche Aufwand zeigt sich an zwei Stellen. Erstens braucht jeder interaktive Login jetzt ein Smartphone oder eine Authenticator-App, kein großes Ding für gelegentliche Logins, deutlich spürbarer, wenn man dutzende Mal am Tag per SSH auf einen Server geht. Zweitens, und wichtiger, bricht Automatisierung. Eine CI/CD-Pipeline, die per SSH deployed, ein Ansible-Playbook, ein Cron-Job, der per rsync auf einen Remote-Host synchronisiert, keiner davon hat einen Menschen zur Hand, der einen TOTP-Code eintippt. AuthenticationMethods publickey,keyboard-interactive serverweit anzuwenden bricht all das gleichzeitig, oft auf eine Art, die erst auffällt, wenn der nächste geplante Job fehlschlägt.
Der Mittelweg, der tatsächlich funktioniert
Statt 2FA überall einzuführen, wende ich es nur auf interaktive Logins von Menschen an, während Automatisierung separate, stärker eingeschränkte Service-Accounts nutzt, die nicht der 2FA-Pflicht unterliegen, oft weil sie auch auf andere Weise eingeschränkt sind (ein forced command in authorized_keys, oder ein Key, der nur ein bestimmtes Skript ausführen kann):
# /etc/ssh/sshd_config
Match User deploy,admin
AuthenticationMethods publickey,keyboard-interactive
Match User ci-deploy
AuthenticationMethods publickey
So bekommen die Accounts, mit denen sich Menschen einloggen und beliebige Befehle ausführen, den zusätzlichen Faktor, während die eng begrenzten Automatisierungs-Accounts, die ohnehin realistisch keinen TOTP-Code liefern könnten, und die eine Kompromittierung eines Laptops nicht direkt offenlegen würde (ihre Keys liegen in CI-Secrets, nicht auf dem Laptop irgendeiner Person), ohne 2FA weiterlaufen.
Wo ich lande
Für einen Server, auf den ausschließlich Automatisierung zugreift, ganz ohne interaktive Logins von Menschen, bringt SSH-2FA wenig, die Bedrohung, die es adressiert (ein gestohlener, von Menschen gehaltener Key), trifft hier kaum zu. Für Server, in die sich Menschen direkt einloggen, besonders solche mit Zugriff auf Produktionsdaten oder der Möglichkeit, Änderungen vorzunehmen, ist das Laptop-Diebstahl-Szenario real genug, dass der relativ kleine zusätzliche Aufwand, eine TOTP-Abfrage beim Login, sich lohnt, solange es speziell auf diese Accounts begrenzt bleibt und nicht im Stillen die Automatisierung kaputt macht, die alles andere am Laufen hält.