02 November 2020

Zwei-Faktor-Authentisierung für OpenSSH und OpenVPN

Einleitung

Die Anmeldung mittels Benutzernamen und Passwort stellt nach wie vor für die meisten Anwendungen die übliche Vorgehensweise dar, um sich an einem Dienst zu authentisieren. Die Nutzung eines zweiten Faktors findet jedoch immer weitere Verbreitung und wird vom BSI, dem Bundesamt für Sicherheit in der Informationstechnik, sogar empfohlen. Wenn auch nicht vorgeschrieben, so bieten verschiedene Webdienste immerhin die Option, Zwei-Faktor-Authentisierung (2FA) für ein Benutzerkonto zu aktivieren.

Doch nicht nur die Sicherheit von Webdiensten kann mittels 2FA erhöht werden, auch klassische Dienste wie SSH erlauben die Nutzung eines zweiten Faktors neben den üblichen Authentisierungsmethoden wie Passwörtern oder Zertifikaten.

Verfahren

Das am weitesten verbreitete Verfahren für Einmalpasswörter als zweiten Faktor stellt vermutlich TOTP, das Time-Based One-Time Password, dar. Das Verfahren ist in RFC6238 standardisiert und ist bisweilen auch unter dem Namen Google Authenticator bekannt.

Bei TOTP wird aus der aktuellen Uhrzeit sowie dem Shared Secret, einem sowohl dem Dienst als auch dem Benutzer bekannten Geheimnis, ein für einen kurzen Zeitraum, einmalig gültiges, numerisches Einmalpasswort (engl. one-time password, OTP) berechnet.

Üblicherweise – und im Falles des Google Authenticator fest vorgegeben – besteht das Passwort aus 6 Ziffern und hat eine Gültigkeitsdauer von 30 Sekunden. Der Standard sieht jedoch auch andere Längen und Zeiträume vor.

Zur Berechnung des OTP existieren neben CLI-Anwendungen wie oathtool auch solche mit GUI wie zum Beispiel KeePassXC oder Smartphone-Apps wie AndOTP.

Einrichtung

PAM (Pluggable Authentication Modules) ist eine Sammlung von Bibliotheken, die es Anwendungen und Diensten erlaubt die Authentifizierung von Benutzern auszulagern, statt diese selbst implementieren zu müssen. Hierzu werden die Nachrichten der Unterhaltung, die zur Authentifizierung zwischen PAM und Benutzer ausgetauscht werden, durch die Anwendung hindurch an den jeweiligen Empfänger weitergeleitet.

Während dieser Unterhaltung durchläuft PAM die in der Service-Datei der Anwendung konfigurierten Module, in welchen die jeweiligen Authentifizierungsverfahren implementiert sind. Der Anwendung selbst meldet PAM letztlich nur Erfolg oder Misserfolg der Authentifizierung.

Um unter Linux Einmalpasswörter nutzen zu können bietet sich daher die Nutzung des PAM-Moduls pam_oath an. Alle Dienste, die PAM zur Authentifizierung ihrer Benutzer verwenden, können so einfach um die Funktionalität der Zwei-Faktor-Authentisierung erweitert werden. Dazu gehören neben System-Interna wie login, su oder sudo auch über das Netzwerk erreichbare Dienste wie SSH oder OpenVPN.

Je nach verwendeter Distribution befindet sich das PAM-Modul im Paket libpam-oath (Debian etc.) oder pam_oath (CentOS etc.) und kann aus den offiziellen Quellen installiert werden.

PAM

Um TOTP für SSH einzurichten muss die entsprechende PAM-Service-Datei angepasst werden. Diese befindet sich unter /etc/pam.d/sshd.

Diese Datei ist in etwa 50 Zeilen lang und beschreibt unter anderem, wie bei der Anmeldung eines Benutzers über SSH seine Identität überprüft werden kann und welche Umgebung vor dem Aufruf seiner Login-Shell geschaffen wird.

Die genaue Funktion der einzelnen Einträge würde den Rahmen dieses Artikels sprengen. Interessant für die Einrichtung von TOTP ist lediglich die Zeile

@include common-auth

Diese übernimmt das in der Service-Datei /etc/pam.d/common-auth festgelegte Standardverhalten des Systems: mittels des Moduls pam_unix wird das Kennwort des Benutzers mit dem in /etc/shadow verglichen.

Um die Überprüfung eines OTP mittels pam_oath zu erfordern, wird die folgende Zeile, direkt unter der obigen @include-Anweisung hinzugefügt:

auth require pam_oath.so usersfile=/etc/users.oath digits=6 window=2

Der Parameter usersfile verweist dabei auf eine Datei, in der die Shared Secrets der Benutzer gespeichert sind, digits=6 legt die Länge der OTP auf 6 Ziffern fest.

Mittels window=2 wird das Fenster der erlaubten OTP vergrößert. Neben dem aktuell gültigen OTP gelten bei einer Fenstergröße von 2 auch die Passwörter des vorherigen beziehungsweise nächstes Zeitraums. Während eine Fenstergröße von 0 nur das aktuelle OTP erlaubt, wird mit wachsender Zahl jeweils ein zukünftiges und ein vergangenes Passwort mehr erlaubt. Weitere Parameter finden sich in der Dokumentation des Moduls.

Der Aufbau des Usersfile folgt der *NIX-Tradition: jede Zeile stellt einen Eintrag dar, welcher mehrere Felder enthält, die durch ein oder mehrere Leerzeichen getrennt werden. Während ein Eintrag bis zu neun Felder enthalten kann, spielen bei der Einrichtung eines neuen Benutzers nur die ersten vier eine Rolle. Sie beinhalten, der Reihe nach: das verwendete Verfahren, den Benutzernamen, eine optionale PIN sowie im letzten Feld das Shared Secret.

Als Shared Secret empfiehlt das RFC eine 160 Bit (also 20 Byte) große Zufallszahl. Diese kann leicht mit Hilfe des Programms openssl erstellt werden:

$ openssl rand -hex 20

Als Ausgabe erhält man die 40 Zeichen lange, Base16-kodierte Repräsentation der zufällig erzeugten Zeichenkette, beispielsweise e2e36e1f3010bba83fed4118244f85be1cbb23fd.

Um einen Eintrag für den Benutzer alice und dem Verfahren TOTP mit einem Gültigkeitsbereich von 30 Sekunden an das Usersfile anzuhängen kann einfach folgende Befehlszeile benutzt werden. Der in $() enthaltene Aufruf von openssl wird dabei durch seine Ausgabe, dem 20 Byte langen Shared Secret ersetzt.

$ echo "HOTP/T30 alice - $(openssl rand -hex 20)" | tee -a /etc/users.oath

Das Programm tee gibt den erzeugten Eintrag samt Shared Secret einerseits auf der Kommandozeile aus und hängt ihn außerdem als weitere Zeile an das Usersfile /etc/users.oath an:

$ echo "HOTP/T30 alice - $(openssl rand -hex 20)" | tee -a /etc/users.oath
HOTP/T30 alice - e2e36e1f3010bba83fed4118244f85be1cbb23fd

SSH

Ein in der Standardkonfiguration eingerichtetes OpenSSH authentisiert Benutzer mittels der eingebauten PasswordAuthentication. Um PAM verwenden zu können muss diese ausgeschaltet und stattdessen die ChallengeResponseAuthentication eingeschaltet werden. Die Authentisierung über PAM wird dann über den Parameter UsePAM aktiviert.

Die Konfigurationsdatei /etc/ssh/sshd_config muss also die folgenden Zeilen enthalten:

PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes

Demo

Durch die Veränderungen an der Konfiguration von OpenSSH hat sich der Prompt, welcher beim Verbindungsaufbau zur Eingabe des Passworts auffordert verändert.

Die in OpenSSH eingebaute PasswordAuthentication zeigte im Prompt den für die Verbindung verwendeten Benutzer- sowie Hostnamen an.

alice@local$ ssh alice@192.0.2.1
alice@192.0.2.1's password:
alice@remote$

Nach der Umstellung auf PAM unter Verwendung der ChallengeResponseAuthentication wird hingegen die Eingabeaufforderung des jeweiligen PAM-Moduls angezeigt: zuerst pam_unix, dann pam_oath.

alice@local$ ssh alice@192.0.2.1
Password:
One-time password (OATH) for `alice':
alice@remote$

OpenVPN

OpenVPN authentifiziert Benutzer klassischerweise über Zertifikate, die von einer vertrauenswürdigen, nicht selten lokalen, CA beglaubigt wurden. Im Laufe des Verbindungsaufbaus ist es jedoch außerdem möglich einen Benutzernamen sowie das dazugehörige Passwort clientseitig abzufragen und serverseitig zu überprüfen.

Um einer bestehenden OpenVPN-Installation eine 2FA hinzuzufügen, bedarf es nur weniger Änderungen an den Konfigurationsdateien.

Damit der OpenVPN die Authentifizierung des Benutzernamens und des Passworts an PAM übergeben kann, wird das in der Standardinstallation mitgelieferte PAM-Plugin in der OpenVPN-Konfiguration des Servers eingetragen:

plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so openvpn

Der Parameter openvpn entspricht dabei dem Namen der PAM-Service-Datei in /etc/pam.d/, welche noch neu angelegt werden muss:

auth require pam_oath.so usersfile=/etc/users.oath digits=6 window=2
@include common-account

Befinden sich auf dem Rechner, auf dem der OpenVPN-Dienst läuft, keine Benutzeraccounts, kann deren Existenzüberprüfung mit einer abgewandelten Service-Datei übersprungen werden:

auth require pam_oath.so usersfile=/etc/users.oath digits=6 window=2
account require pam_permit.so

Das Modul pam_permit liefert stets Erfolg zurück. Da es das einzige angegebene Modul des Typs auth ist, wird nur sein Ergebnis ausgewertet.

Clientseitig muss der Konfiguration lediglich folgende Zeile hinzugefügt werden, damit der Benutzer während des Verbindungsaufbau nach seinem Benutzernamen und (Einmal-)Passwort gefragt wird:

auth-user-pass

Wird die Verbindung clientseitig über eine GUI wie den NetworkManager konfiguriert, ist unter Verbindungsart statt der üblichen Einstellung Zertifikate (TLS) der Eintrag Passwort mit Zertifikaten (TLS) auszuwählen. Unter Benutzername ist der zu verwendende Benutzername einzugeben, das Feld Passwort bleibt jedoch frei, dort muss die Option Jedes Mal nach diesem Passwort fragen gewählt werden.

Demo

Nach Anpassung der Konfiguration auf dem Client wird der Benutzer während der TLS-Verhandlungen des Verbindungsaufbaus direkt nach Überprüfung der Zertifikate aufgefordert einen Benutzernamen und das zugehörige OTP einzugeben.

# openvpn client.conf
...
Enter Auth Username: alice
Enter Auth Password: ******
...

Auch bei Verwendung des NetworkManagers wird der Benutzer beim Verbindungsaufbau nach dem aktuellen Einmalpasswort gefragt.

IMG Abfrage des OTP bei Verbindungsaufbau
Abfrage des OTP bei Verbindungsaufbau

OTP berechnen

Das Shared Secret, oder auch gemeinsame Geheimnis, muss – wie der Name sagt – beiden Seiten bekannt sein. Auf der Serverseite befindet es sich im Usersfile, auf Clientseite gibt es für den Benutzer verschiedene Wege das Shared Secret aufzubewahren, um damit ein OTP zu berechnen.

Das zur Berechnung benötigte Shared Secret wurde mit dem oben aufgeführten openssl-Aufruf erzeugt und in Hexadezimal-Darstellung bzw. Base16-kodiert ausgegeben. Neben Base16 ist auch die Darstellung in Base32 verbreitet, es muss also darauf geachtet werden, welche Kodierung ein Programm bei der Eingabe des Shared Secrets erwartet. Beide genannten Verfahren sind in RFC 4648 beschrieben und standardisiert.

Während sich für Base32 und Base64 bereits die Tools base32 respektive base64 im Paket coreutils befinden, muss für die Umwandlung von Base16 ein weiteres Tool, beispielsweise basez installiert werden. Neben der Hauptanwendung basez werden hierbei auch einige symbolische Links hierauf eingerichtet, darunter base16, welches sich wie base32 und base64 bedienen lässt.

Um das oben erzeugte Shared Secret für alice von Base16 in Base32 umzuwandeln reicht der folgende Aufruf. Die Option -d beim Aufruf von base16 steht dabei für decode, da die Umwandlung aus Base16 heraus erfolgt.

$ echo e2e36e1f3010bba83fed4118244f85be1cbb23fd | base16 -d | base32
4LRW4HZQCC52QP7NIEMCIT4FXYOLWI75

In Base32-Kodierung lautet das Shared Secret also 4LRW4HZQCC52QP7NIEMCIT4FXYOLWI75.

Wie zu erwarten finden sich auch online etliche webbasierte Tools zur Umwandlung zwischen den verschiedenen Kodierungen. Die Übermittlung an Webseiten ist jedoch nicht zu empfehlen: auch ein geteiltes Geheimnis ist ein Geheimnis und sollte nicht an Dritte weitergegeben werden!

Ähnlich verhält es sich bei der Verwendung von QR-Codes, der sich ein gesonderter Artikel widmen wird. Obwohl weit verbreitet ist ihre Benutzung nicht ohne Risiken, die vorher analysiert und minimiert werden sollten.

CLI

Das Programm oathtool ermöglicht die Berechnung von OTP auf der Kommandozeile. Um TOTP zu berechnen wird ihm beim Aufruf das Argument --totp sowie das Shared Secret in Base16-Kodierung übergeben:

$ oathtool --totp e2e36e1f3010bba83fed4118244f85be1cbb23fd

oathtool geht dabei von einer OTP-Länge von 6 Ziffern und einem Fenster von 0 aus. Diese Annahmen können mit den Argumenten -d (Digits) sowie -w (Window) angepasst werden.

Liegt das Shared Secret Base32-kodiert vor, muss ihm das Argument -b vorangestellt werden:

$ oathtool --totp -b 4LRW4HZQCC52QP7NIEMCIT4FXYOLWI75

GUI

Neben der sicheren Speicherung von statischen Passwörtern bietet KeepassXC auch die Möglichkeit Einmalpasswörter nach TOTP zu generieren. Hierzu wird das Shared Secret als Attribut eines Eintrags gespeichert.

Einem bestehenden Eintrag kann mittels Rechtsklick über Zeitbasiertes Einmal-Passwort (TOTP) > TOTP einrichten… das Shared Secret als Schlüssel hinzugefügt werden. RFC 6238-Token-Standardeinstellungen geht dabei von Länge von 6 Ziffern und einer Gültigkeit von 30 Sekunden aus. Als Schlüssel wird das Base16-Kodierte Shared Secret erwartet.

Aufruf: TOTP einrichten
Aufruf: TOTP einrichten
Dialog: TOTP einrichten
Dialog: TOTP einrichten

Mittels Rechtsklick auf den Eintrag kann das aktuelle Einmalpasswort über Zeitbasiertes Einmal-Passwort (TOTP) > TOTP anzeigen angezeigt, beziehungsweise über TOTP kopieren in die Zwischenablage kopiert werden.

Aufruf: TOTP anzeigen
Aufruf: TOTP anzeigen
Dialog: TOTP anzeigen
Dialog: TOTP anzeigen

Smartphone-App

Um ein TOTP auf dem Smartphone berechnen zu lassen bietet sich andOTP an. Die App ist Freie Software, steht unter der MIT-Lizenz und kann einfach über F-Droid oder aus dem Google Play Store installiert werden.

Über den Plus-Button in der unteren rechten Bildschirmecke kann ein neuer Eintrag angelegt werden. Neben der Möglichkeit einen QR-Code einzuscannen, kann über den Menüpunkt Details eingeben neben einigen Einstellungen wie Zeitraum, Länge oder Hash-Algorithmus das Shared Secret von Hand eingegeben werden.

Eingabe der Details in andOTP
Eingabe der Details in andOTP
Anzeige des aktuellen TOTP in andOTP
Anzeige des aktuellen TOTP in andOTP

Der Möglichkeit, das Shared Secret und Einstellungen zur Berechnung eines TOTP mittels eines QR-Codes einzulesen, widmet sich ein kommender Artikel.

Fazit

Die aufgeführten Beispiele zeigen wie einfach es ist auch bereits bestehende Dienste, um eine Zwei-Faktor-Authentisierung mit TOTP zu erweitern. Es muss lediglich in der entsprechenden Service-Datei die Anbindung an PAM und die Verwendung des Moduls pam_oath konfiguriert werden.

Das gezeigte Vorgehen eignet sich vornehmlich für einzelne Systeme mit einigen wenigen abzusichernden Benutzerkonten. Komplexere Installationen und andere Verfahren für Einmalpasswörter sind auch möglich.

Unterstützung

Falls Sie Unterstützung bei der Konfiguration oder dem Einsatz von Zwei-Faktor-Authentisierung wünschen, steht Ihnen unser Open Source Support Center gerne zur Verfügung – falls gewünscht auch 24 Stunden am Tag, an 365 Tagen im Jahr.

Kategorien: HowTos
Tags: 2FA OpenSSH OpenVPN SSH

JB

über den Autor

Jan Bolle


Beitrag teilen: