OpenVPN auth-user-pass: bestand, stdin of prompt? Zo kiest u
Kies tussen de consoleprompt, een inloggegevensbestand, een stream en de beheerinterface, en los daarna de fouten op die alleen op een verkeerd wachtwoord lijken.
Drie dingen bepalen welke bron van inloggegevens u moet gebruiken: of er iemand achter de console zit, of het geheim op schijf mag staan en of een ander proces de prompt moet beantwoorden. Kiest u verkeerd, dan meldt de client een stdin-probleem terwijl het wachtwoord volkomen geldig is, en dat stuurt de meeste mensen zonder reden naar de server. Kies eerst het pad; de foutmeldingen zijn pas logisch als u weet welk pad ze heeft veroorzaakt.
De drie voorwaarden die het bepalen
De consoleprompt is het enige pad dat een mens nodig heeft, dus het enige dat stil faalt in een systemd-unit of een container. Als iemand de client start en het wachtwoord typt, is er geen bestand bij betrokken en komt er niets gevoeligs op de schijf. Als de client bij het opstarten begint, wordt diezelfde prompt een hang, en de time-out verschijnt meestal als een algemene verbindingsfout in plaats van een inlogfout.
Een inloggegevensbestand is het juiste antwoord wanneer het proces onbeheerd start en het geheim op schijf mag blijven onder een gecontroleerde set rechten. Wanneer het geheim helemaal niet mag worden geschreven - een alleen-kluisbeleid, een kortlevend token - hebt u een stream nodig die de client kan openen, wat in de praktijk procesvervanging of een helper betekent die in een bestandsdescriptor schrijft. De beheerinterface dekt het vierde geval: een controller die de levenscyclus van de tunnel al beheert en vragen via een socket kan beantwoorden.
- Mens achter de console, geen automatisering: interactieve prompt.
- Onbeheerde start, geheim mag worden opgeslagen: inloggegevensbestand met modus 0600.
- Onbeheerde start, geheim mag niet worden opgeslagen: procesvervanging of een fd waarin een geheimagent schrijft.
- Een ander proces bezit de client: beheerinterface.
Als twee antwoorden passen, kies dan het antwoord dat het geheim buiten argv en buiten de shell-geschiedenis houdt. Een wachtwoord dat als programargument wordt doorgegeven, is via de proceslijst leesbaar voor elke lokale gebruiker, en die blootstelling is moeilijk terug te draaien.
Wat elk invoerpad werkelijk doet
--auth-user-pass alleen vraagt op de console om een gebruikersnaam en een wachtwoord. Met een bestandsnaam neemt de client regel één als gebruikersnaam en regel twee als wachtwoord; niets ondersteunt aanhalingstekens, opmerkingen of sleutel-waarde-syntaxis. Dat is het hele formaat, dus wie het bewerkt in de verwachting van een INI-bestand, breekt het. Een inline <auth-user-pass>-blok bevat dezelfde twee regels in het profiel, wat het profiel zelf tot een geheim maakt en het in dezelfde behandelingsklasse als een privésleutel plaatst.
De andere twee paden zijn een stream en een socket. OpenVPN heeft alleen een leesbare bestandsdescriptor nodig, dus accepteert het een procesvervanging, een door een pipe ondersteunde /dev/fd-vermelding of een bestandsnaam die in werkelijkheid een FIFO is. De beheerinterface is anders van aard: de client vraagt een toezichthoudend proces om de waarden in plaats van ze zelf te lezen. Dat verschil is belangrijk bij opnieuw verbinden: een inloggegevensbestand, een FIFO waarin een geheimhelper opnieuw kan schrijven en de beheerinterface kunnen zonder mens opnieuw leveren; procesvervanging kan dat niet, omdat de descriptor bij de eerste lezing wordt verbruikt.
Het bestand moet precies twee regels hebben
Twee faalwijzen dekken de meeste kapotte inloggegevensbestanden. Een Windows-editor laat CRLF-regeleinden staan, de carriage return wordt deel van het wachtwoord, en de server weigert een waarde die op het scherm correct lijkt. Een lege tweede regel - een lege regel waar het wachtwoord hoort - laat de client met een leeg wachtwoord achter, dat de server weigert ook al lijkt de waarde op het scherm juist. Een extra regeleinde na het wachtwoord is onschadelijk. Schrijf het bestand vanuit de shell, niet vanuit een editor, en controleer de 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 -3Het pad is even belangrijk als de inhoud. Een relatief pad wordt opgelost tegen de werkmap van het proces, die voor een dienst zelden de map is waarin u hebt getest. Gebruik een absoluut pad, laat het bestand eigendom zijn van het account dat de client uitvoert, en houd modus 0600 zodat groep en anderen het niet kunnen lezen. De OpenVPN 2.6-handleiding somt de geaccepteerde vormen van de richtlijn op; raadpleeg die voordat u een derde vorm bedenkt.
Test het bestand voordat u de server de schuld geeft. Het uitvoeren van openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 print of het bestand is geopend en later of de inloggegevens zijn geaccepteerd, wat u vertelt welke laag u hierna moet wijzigen.
Streams, stdin en de fouten die ze opleveren
Het wachtwoord door een pipe sturen is het eerste dat de meeste mensen proberen en het pad met de meeste verrassingen. Procesvervanging werkt omdat de client alleen een leesbare descriptor nodig heeft: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). /dev/stdin doorgeven werkt alleen als stdin op het moment dat de client vraagt nog open en leesbaar is, wat niet geldt in een pijplijn die het al heeft verbruikt.
ERROR: could not read Auth username from stdin heeft twee verschillende oorzaken. Bij sommige 2.3.x-clients kwam de melding uit een fout in de stdin-afhandeling die latere 2.3-releases hebben verholpen, dus zo'n oude client verbetert alleen door te upgraden. Bij een huidige client betekent dezelfde formulering dat de client console-invoer heeft gevraagd en stdin geen terminal was - precies de situatie in een systemd-unit, een cron-taak of een container die zonder -t is gestart.
auth-nocache voegt een derde lus toe die op een kapot wachtwoord lijkt. Het gooit de inloggegevens na gebruik uit het geheugen, dus een herverbinding die door een netwerkwijziging wordt veroorzaakt heeft niets om opnieuw af te spelen en de prompt komt terug. Dat is de richtlijn die werkt zoals ontworpen. auth-nocache verandert wat de client in het geheugen houdt, niet wat de server of de identiteitsprovider van het account vindt, dus de hele oplossing is hetzelfde bestand opnieuw leveren, bij herstart opnieuw gelezen - en voor een beheerde verbinding zou die levering uit de goedgekeurde geheimopslag moeten komen, niet uit een wachtwoord in een script.
De beheerinterface wanneer een ander proces de prompt bezit
Een controller die de tunnel al superviseert, kan ook de vragen ervan beantwoorden. Start de client met --management 127.0.0.1 7505, lees de statusregels en let op >PASSWORD:Need 'Auth' username/password. De controller antwoordt met username "Auth" alice gevolgd door password "Auth" ... op afzonderlijke commandoregels. Het 'Auth'-token herhaalt de identificatie uit het verzoek en moet overeenkomen, anders wordt het antwoord genegeerd en wacht de client.
De prijs is een toestandsmachine die u nu bezit: volgorde van verbindingen, herstarts van de client en een lokale socket die andere gebruikers op de host niet mogen bereiken. Wat u koopt is een inloggegeven dat tijdens de uitvoering wordt geleverd, zonder bestand op schijf en zonder prompt die kan hangen. Als niets anders in uw stack het protocol al spreekt, voegt dit pad een te onderhouden component toe.
Storingen die op inlogproblemen lijken
Een TLS-handshake die nooit voltooit, of VERIFY ERROR: depth=0, error=certificate signature failure, is een vertrouwensprobleem en gebeurt voordat er een gebruikersnaam wordt gelezen. Een proto tcp-client gericht op een UDP-listener faalt op dezelfde plek: de pakketten bereiken nooit de authenticatiefase, dus elk wachtwoord lijkt door associatie onjuist. Houd certificaatverificatie aan voordat de inloggegevens worden verzonden; een vertrouwde prompt zegt niets over wie het wachtwoord ontvangt. Controleer de certificaatketen, de common name en het transport voordat u de inloggegevens aanraakt.
Shell-fouten in het script dat het profiel samenstelt zijn het andere valse spoor. Een ontbrekende spatie in [ ! -f "$file" ] levert command not found op, het script stopt vroeg, het profiel wordt nooit opnieuw opgebouwd en de client start met het vorige. Die fout hoort bij de shell, niet bij de authenticatie, en hoe vaak u het wachtwoord ook opnieuw typt, hij gaat niet weg.
Niet elke prompt in deze stroom is dit inloggegeven. Een wachtzin voor een privésleutel, een HTTP-proxylogin en het servicewachtwoord zijn drie verschillende geheimen die in verschillende fasen worden gevraagd, en een sleutelwachtzin wordt meestal door de client of een agent afgehandeld in plaats van door auth-user-pass. Als de prompt verschijnt voordat de TLS-sessie staat, beantwoordt u de verkeerde vraag en geen enkele accountreset helpt. Zodra de verkeerde prompt is uitgesloten, beginnen de overige controles bij de vroegste laag:
- Lees de eerste protocolfout, niet de laatste inlogregel: TLS, dan authenticatie, dan push.
- Bevestig dat het bestand twee regels heeft, geen carriage returns bevat en met een absoluut pad wordt aangeduid.
- Bevestig dat het profiel en de commandoregel het niet oneens zijn over de richtlijn.
- Scheid "inloggegevens geaccepteerd" van "verkeer stroomt" - routing en DNS zijn een latere laag.
Wanneer de client de push-fase bereikt, stop met kijken naar de inloggegevens en begin de routes en DNS-servers te lezen die de server heeft gestuurd. Dat is het volgende probleem, en het heeft niets te maken met het wachtwoord dat u zojuist hebt gerepareerd.