Zwei-Faktor-Authentifizierung für SSH mit TOTP einrichten

Installieren Sie libpam-google-authenticator, führen Sie google-authenticator für jeden Benutzer aus, tragen Sie auth required pam_google_authenticator.so in /etc/pam.d/sshd ein und setzen Sie AuthenticationMethods publickey,keyboard-interactive und KbdInteractiveAuthentication yes in der SSH-Server-Konfiguration. Jede Anmeldung braucht dann den Schlüssel und einen sechsstelligen Code. Lassen Sie beim Testen eine Sitzung offen, denn ein Fehler kann Sie aussperren.

Serverseitig fertig? Wardterm erledigt Schlüssel und Code ohne zusätzliche Einstellungen. Zeigen

Aktualisiert am . Von Anfang bis Ende ausgeführt mit OpenSSH 10.0 und libpam-google-authenticator unter Debian 13, in einem Wegwerf-Container, mit echten Anmeldungen und von oathtool erzeugten Codes: richtige, falsche, wiederverwendete und alte Codes, Scratch-Codes, Benutzer ohne Secret-Datei und ein falscher Dateimodus.

Bevor Sie anfangen

Bleiben Sie bis zum Ende in einem Fenster am Server angemeldet. Prüfen Sie, ob Sie zusätzlich eine Konsole Ihres Hosting-Anbieters haben. Richten Sie zuerst die Anmeldung per Schlüssel ein: siehe SSH-Schlüssel erzeugen.

Schritt 1: Modul installieren

sudo apt update
sudo apt install libpam-google-authenticator

Trotz des Namens braucht es kein Google-Konto und funktioniert mit jeder TOTP-App. Der Server prüft die Codes selbst.

Schritt 2: Secret für jeden Benutzer erzeugen

Führen Sie das als der Benutzer aus, der sich anmelden wird, nicht mit sudo:

google-authenticator -t -d -f -r 3 -R 30 -w 3
OptionBedeutung
-tZeitbasierte Codes
-dEin Code kann nicht zweimal verwendet werden. Wir haben es geprüft: Eine zweite Anmeldung mit demselben Code scheiterte.
-fDie Datei ohne Nachfrage schreiben
-r 3 -R 30Höchstens 3 Anmeldungen alle 30 Sekunden. Denken Sie beim Testen daran: Schnelle wiederholte Versuche scheitern auch mit richtigem Code.
-w 3Den aktuellen Code und die unmittelbar davor und danach akzeptieren, um einen kleinen Zeitunterschied auszugleichen

Scannen Sie den QR-Code mit Ihrer App und tippen Sie zur Bestätigung einen Code ein. Wenn Sie nicht scannen können, geben Sie den geheimen Schlüssel von Hand in die App ein. Das Werkzeug gibt außerdem einen Link zu einer Google-Chart-Seite aus und warnt, dass das Öffnen das Secret an Google preisgibt, öffnen Sie ihn also nicht. Der Befehl gibt fünf Scratch-Codes für den Notfall aus. Speichern Sie sie woanders als auf diesem Server und Ihrem Handy. Jeder funktioniert einmal anstelle eines Codes.

Das legt ~/.google_authenticator mit dem Modus 400 an. Lassen Sie es dabei: In unserem Test scheiterten Anmeldungen mit dem Modus 644 auch bei richtigem Code.

Schritt 3: PAM konfigurieren

Bearbeiten Sie /etc/pam.d/sshd. Kommentieren Sie die Zeile aus, die nach dem Passwort fragt, und fügen Sie darunter zwei Zeilen hinzu:

# @include common-auth
auth required pam_google_authenticator.so nullok
auth required pam_permit.so
  • Warum common-auth auskommentiert wird: Lassen Sie es stehen, fragte die Anmeldung in unserem Test nach dem Code und danach auch noch nach dem Systempasswort.
  • Was nullok tut: Ein Benutzer ohne Secret-Datei kann sich ohne Code anmelden, sodass Sie das Verfahren Benutzer für Benutzer einführen können. Entfernen Sie es, wenn alle eingerichtet sind.
  • Warum pam_permit.so: nullok lässt das Modul sich enthalten, und PAM braucht mindestens ein Modul mit Erfolg. Ohne diese Zeile wurden Benutzer ohne Secret-Datei in unserem Test abgewiesen. Benutzer, die eine Datei haben, brauchen weiterhin den richtigen Code.

Sobald Sie nullok entfernen, können Sie auch pam_permit.so entfernen. Red-Hat-Systeme verwenden eine andere erste Zeile, und das Paket kommt aus EPEL. Lesen Sie dazu die Dokumentation Ihrer Distribution.

Schritt 4: sshd konfigurieren

# /etc/ssh/sshd_config.d/10-2fa.conf
AuthenticationMethods publickey,keyboard-interactive
KbdInteractiveAuthentication yes
UsePAM yes

Das Komma bedeutet, dass beides nötig ist, in dieser Reihenfolge. Nehmen Sie eine Datei in diesem Ordner, weil der zuerst gelesene Wert gilt und die Haupt-sshd_config von Debian weiter unten KbdInteractiveAuthentication no enthält. Ältere Systeme nannten diese Einstellung ChallengeResponseAuthentication.

Prüfen Sie die Datei, bevor Sie neu laden:

sudo sshd -t
sudo sshd -T | grep -iE '^(authenticationmethods|kbdinteractiveauthentication|usepam) '
sudo systemctl reload ssh

Ist KbdInteractiveAuthentication aus, meldet sshd -t das, und Sie sollten nicht neu laden:

Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive"
AuthenticationMethods cannot be satisfied by enabled authentication methods

Schritt 5: aus einem neuen Fenster testen

ssh user@server
(user@server) Verification code:

Das haben wir in den einzelnen Fällen erhalten:

VersuchErgebnis
Schlüssel und richtiger CodeAngemeldet. Das Log zeigt Accepted keyboard-interactive/pam for user.
Schlüssel und falscher, wiederverwendeter oder fünf Minuten alter CodePermission denied (keyboard-interactive).
Kein SchlüsselPermission denied (publickey). Es wird kein Code verlangt, und kein Passwort wird akzeptiert.
Schlüssel und Scratch-CodeEinmal angemeldet. Der Code wird danach aus der Datei entfernt und scheitert bei erneuter Verwendung.

Scheitern richtige Codes, prüfen Sie zuerst die Uhr. Server und Handy müssen sich über die Uhrzeit einig sein. Führen Sie timedatectl auf dem Server aus und prüfen Sie, ob die Uhr synchronisiert ist.

Einen Weg zurück offenhalten

Haben Sie mindestens zwei davon, bevor Sie Ihre letzte offene Sitzung schließen:

  • Ihre Scratch-Codes, getrennt vom Handy aufbewahrt. Geht das Handy verloren, melden Sie sich mit einem davon an und führen google-authenticator erneut aus, um das Secret zu ersetzen.
  • Die Konsole des Anbieters. Sie nutzt kein SSH. Löschen Sie dort 10-2fa.conf und laden Sie neu.
  • Eine Ausnahme nach Adresse, für ein Netz, das nur Sie erreichen können, etwa ein VPN:
# At the end of 10-2fa.conf
Match Address 10.8.0.0/24
    AuthenticationMethods publickey
  • Ein getrenntes Notfallkonto mit einem Schlüssel, der offline aufbewahrt wird. Fügen Sie denselben Block mit Match User breakglass hinzu. Das passt auch zu einem automatisierten Auftrag, wenn Sie seinen Schlüssel einschränken.

Prüfen Sie eine Ausnahme mit -C, weil ein einfaches sshd -T Match-Blöcke nicht zeigt:

sudo sshd -T -C user=user,host=server,addr=10.8.0.5 | grep -i authenticationmethods

Jede Ausnahme ist ein Weg um den zweiten Faktor herum, halten Sie sie also wenige und eng gefasst.

Wie Sie einschränken, was ein Notfall- oder Job-Schlüssel ausführen darf, zeigt einen SSH-Schlüssel auf einen Befehl beschränken.

Weniger Codes tippen

Mit geteilten Verbindungen nutzen neue Sitzungen eine offene Verbindung mit und fragen nicht erneut nach einem Code.

Fragen

Betrifft das scp, sftp, rsync und Skripte?

Ja. Sie melden sich alle auf dieselbe Weise an und fragen nach einem Code, sodass ein Auftrag, bei dem niemand tippt, scheitert. Nehmen Sie sein Konto mit einem Match-Block aus und beschränken Sie mit den Optionen aus der Anleitung zum Einschränken von Schlüsseln, was sein Schlüssel darf.

Schützt das auch sudo?

Nein. Das ändert nur /etc/pam.d/sshd. sudo hat eine eigene PAM-Datei und ist nicht betroffen.

Quellen

Mehr zu Server absichern

Alle Anleitungen