OpenVPN auth-user-pass: Datei, stdin oder Abfrage? So wählen Sie
Entscheiden Sie zwischen der Konsolenabfrage, einer Anmeldedatendatei, einem Stream und der Managementschnittstelle und beheben Sie dann die Fehler, die nur wie ein falsches Passwort aussehen.
Drei Dinge entscheiden, welche Anmeldequelle Sie verwenden sollten: ob eine Person an der Konsole sitzt, ob das Geheimnis auf der Festplatte liegen darf und ob ein anderer Prozess die Abfrage beantworten muss. Wählen Sie falsch, meldet der Client ein stdin-Problem, obwohl das Passwort völlig gültig ist, und das schickt die meisten ohne Grund zum Server. Wählen Sie zuerst den Weg; die Fehlermeldungen ergeben erst Sinn, wenn Sie wissen, welcher Weg sie erzeugt hat.
Die drei Bedingungen, die den Ausschlag geben
Die Konsolenabfrage ist der einzige Weg, der einen Menschen braucht, also der einzige, der in einer systemd-Unit oder einem Container still scheitert. Startet eine Person den Client und tippt das Passwort, ist keine Datei beteiligt, und nichts Sensibles landet auf der Festplatte. Startet der Client beim Booten, wird dieselbe Abfrage zum Hänger, und der Timeout erscheint meist als allgemeiner Verbindungsfehler statt als Anmeldefehler.
Eine Anmeldedatendatei ist die richtige Antwort, wenn der Prozess unbeaufsichtigt startet und das Geheimnis unter einem kontrollierten Berechtigungssatz auf der Festplatte überleben darf. Wenn das Geheimnis überhaupt nicht geschrieben werden darf - eine Nur-Tresor-Richtlinie, ein kurzlebiges Token - brauchen Sie einen Stream, den der Client öffnen kann, was in der Praxis Prozesssubstitution oder ein Helfer bedeutet, der in einen Dateideskriptor schreibt. Die Managementschnittstelle deckt den vierten Fall ab: einen Controller, der den Lebenszyklus des Tunnels bereits verwaltet und Fragen über einen Socket beantworten kann.
- Mensch an der Konsole, keine Automatisierung: interaktive Abfrage.
- Unbeaufsichtigter Start, Geheimnis darf gespeichert werden: Anmeldedatendatei mit Modus 0600.
- Unbeaufsichtigter Start, Geheimnis darf nicht gespeichert werden: Prozesssubstitution oder ein fd, in den ein Secret-Agent schreibt.
- Ein anderer Prozess besitzt den Client: Managementschnittstelle.
Wenn zwei Antworten passen, nehmen Sie die, die das Geheimnis aus argv und aus der Shell-Historie heraushält. Ein als Programmargument übergebenes Passwort ist für jeden lokalen Benutzer über die Prozessliste lesbar, und diese Bloßstellung ist schwer rückgängig zu machen.
Was jeder Eingabeweg tatsächlich tut
--auth-user-pass allein fragt an der Konsole nach Benutzername und Passwort. Bei einem Dateinamen nimmt der Client Zeile eins als Benutzername und Zeile zwei als Passwort; nichts unterstützt Anführungszeichen, Kommentare oder Schlüssel-Wert-Syntax. Das ist das ganze Format, wer es also in Erwartung einer INI-Datei bearbeitet, macht es kaputt. Ein eingebetteter <auth-user-pass>-Block enthält dieselben zwei Zeilen im Profil, was das Profil selbst zu einem Geheimnis macht und es in dieselbe Behandlungsklasse wie einen privaten Schlüssel stellt.
Die anderen beiden Wege sind ein Stream und ein Socket. OpenVPN braucht nur einen lesbaren Dateideskriptor, daher akzeptiert es eine Prozesssubstitution, einen pipe-gestützten /dev/fd-Eintrag oder einen Dateinamen, der in Wahrheit ein FIFO ist. Die Managementschnittstelle ist anderer Art: Der Client fragt einen überwachenden Prozess nach den Werten, statt sie selbst zu lesen. Dieser Unterschied zählt beim Wiederverbinden: eine Anmeldedatendatei, ein FIFO, in das ein Secret-Helfer erneut schreiben kann, und die Managementschnittstelle können ohne einen Menschen nachliefern; Prozesssubstitution kann das nicht, weil der Deskriptor beim ersten Lesen verbraucht wird.
Die Datei muss genau zwei Zeilen haben
Zwei Fehlermuster decken die meisten defekten Anmeldedatendateien ab. Ein Windows-Editor hinterlässt CRLF-Zeilenenden, der Wagenrücklauf wird Teil des Passworts, und der Server weist einen Wert ab, der am Bildschirm korrekt aussieht. Eine leere zweite Zeile - eine Leerzeile, wo das Passwort hingehört - lässt den Client mit einem leeren Passwort zurück, das der Server ablehnt, obwohl der Wert am Bildschirm richtig aussieht. Ein zusätzlicher Zeilenumbruch nach dem Passwort ist harmlos. Schreiben Sie die Datei aus der Shell, nicht aus einem Editor, und prüfen Sie die Bytes:
install -m 600 /dev/null /etc/openvpn/client.creds
printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS" > /etc/openvpn/client.creds
od -c /etc/openvpn/client.creds | head -3Der Pfad ist so wichtig wie der Inhalt. Ein relativer Pfad wird gegen das Arbeitsverzeichnis des Prozesses aufgelöst, das bei einem Dienst selten das Verzeichnis ist, in dem Sie getestet haben. Verwenden Sie einen absoluten Pfad, lassen Sie die Datei dem Konto gehören, das den Client ausführt, und halten Sie Modus 0600, damit Gruppe und andere sie nicht lesen können. Das OpenVPN-2.6-Handbuch listet die akzeptierten Formen der Direktive; prüfen Sie es, bevor Sie eine dritte erfinden.
Testen Sie die Datei, bevor Sie den Server beschuldigen. Der Aufruf von openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 gibt aus, ob die Datei geöffnet wurde und später, ob die Anmeldedaten akzeptiert wurden, was Ihnen sagt, welche Schicht als Nächstes zu ändern ist.
Streams, stdin und die Fehler, die sie erzeugen
Das Passwort hineinzupipen ist das Erste, was die meisten versuchen, und der Weg mit den meisten Überraschungen. Prozesssubstitution funktioniert, weil der Client nur einen lesbaren Deskriptor braucht: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). /dev/stdin zu übergeben funktioniert nur, wenn stdin in dem Moment noch offen und lesbar ist, in dem der Client fragt, was in einer Pipeline, die es bereits verbraucht hat, nicht gilt.
ERROR: could not read Auth username from stdin hat zwei verschiedene Ursachen. Bei manchen 2.3.x-Clients stammte die Meldung aus einem stdin-Handhabungsfehler, den spätere 2.3-Versionen behoben, ein so alter Client wird also nur durch ein Upgrade besser. Bei einem aktuellen Client bedeutet derselbe Wortlaut, dass der Client Konsoleneingabe angefordert hat und stdin kein Terminal war - genau die Situation in einer systemd-Unit, einem Cron-Job oder einem Container, der ohne -t gestartet wurde.
auth-nocache fügt eine dritte Schleife hinzu, die wie ein defektes Passwort aussieht. Es verwirft die Anmeldedaten nach der Nutzung aus dem Speicher, sodass ein durch eine Netzwerkänderung ausgelöster Reconnect nichts zum Wiederabspielen hat und die Abfrage zurückkehrt. Das ist die Direktive, die wie entworfen arbeitet. auth-nocache ändert, was der Client im Speicher behält, nicht was der Server oder der Identitätsanbieter über das Konto denkt, die ganze Lösung ist also, dieselbe Datei erneut zu liefern, beim Neustart neu gelesen - und für eine verwaltete Verbindung sollte diese Lieferung aus dem freigegebenen Secret-Store kommen, nicht aus einem Passwort in einem Skript.
Die Managementschnittstelle, wenn ein anderer Prozess die Abfrage besitzt
Ein Controller, der den Tunnel bereits überwacht, kann auch seine Fragen beantworten. Starten Sie den Client mit --management 127.0.0.1 7505, lesen Sie die Statuszeilen und achten Sie auf >PASSWORD:Need 'Auth' username/password. Der Controller antwortet mit username "Auth" alice, gefolgt von password "Auth" ... auf getrennten Kommandozeilen. Das 'Auth'-Token wiederholt die Kennung aus der Anfrage und muss passen, sonst wird die Antwort ignoriert und der Client wartet.
Der Preis ist eine Zustandsmaschine, die Sie nun besitzen: Verbindungsreihenfolge, Client-Neustarts und ein lokaler Socket, den andere Benutzer auf dem Host nicht erreichen dürfen. Was Sie kaufen, sind zur Laufzeit gelieferte Anmeldedaten, ohne Datei auf der Festplatte und ohne Abfrage, die hängen kann. Wenn sonst nichts in Ihrem Stack das Protokoll bereits spricht, fügt dieser Weg eine zu pflegende Komponente hinzu.
Fehler, die wie Anmeldeprobleme aussehen
Ein TLS-Handshake, der nie abgeschlossen wird, oder VERIFY ERROR: depth=0, error=certificate signature failure ist ein Vertrauensproblem und geschieht, bevor irgendein Benutzername gelesen wird. Ein proto tcp-Client, der auf einen UDP-Listener zeigt, scheitert an derselben Stelle: Die Pakete erreichen nie die Authentifizierungsphase, also sieht jedes Passwort durch Assoziation falsch aus. Lassen Sie die Zertifikatsprüfung an, bevor die Anmeldedaten gesendet werden; eine vertraute Abfrage sagt nichts darüber, wer das Passwort empfängt. Prüfen Sie die Zertifikatskette, den Common Name und den Transport, bevor Sie die Anmeldedaten anfassen.
Shell-Fehler im Skript, das das Profil zusammensetzt, sind die andere falsche Fährte. Ein fehlendes Leerzeichen in [ ! -f "$file" ] erzeugt command not found, das Skript stoppt früh, das Profil wird nie neu gebaut, und der Client startet mit dem vorherigen. Dieser Fehler gehört zur Shell, nicht zur Authentifizierung, und kein noch so häufiges Neutippen des Passworts beseitigt ihn.
Nicht jede Abfrage in diesem Ablauf ist diese Anmeldung. Eine Passphrase für einen privaten Schlüssel, ein HTTP-Proxy-Login und das Dienstpasswort sind drei verschiedene Geheimnisse, die in verschiedenen Phasen abgefragt werden, und eine Schlüssel-Passphrase wird meist vom Client oder einem Agenten behandelt, nicht von auth-user-pass. Erscheint die Abfrage, bevor die TLS-Sitzung steht, beantworten Sie die falsche Frage, und kein Konto-Reset hilft. Sobald die falsche Abfrage ausgeschlossen ist, beginnen die verbleibenden Prüfungen bei der frühesten Schicht:
- Lesen Sie den ersten Protokollfehler, nicht die letzte Anmeldezeile: TLS, dann Authentifizierung, dann Push.
- Bestätigen Sie, dass die Datei zwei Zeilen hat, keine Wagenrückläufe enthält und über einen absoluten Pfad referenziert wird.
- Bestätigen Sie, dass Profil und Kommandozeile sich bei der Direktive nicht widersprechen.
- Trennen Sie "Anmeldedaten akzeptiert" von "Verkehr fließt" - Routing und DNS sind eine spätere Schicht.
Sobald der Client die Push-Phase erreicht, hören Sie auf, die Anmeldedaten anzusehen, und lesen Sie die Routen und DNS-Server, die der Server gesendet hat. Das ist das nächste Problem, und es hat nichts mit dem Passwort zu tun, das Sie gerade repariert haben.