OpenVPN auth-user-pass: fil, stdin eller prompt? Så väljer du
Välj mellan konsolprompten, en inloggningsfil, en ström och administrationsgränssnittet, och rätta sedan de fel som bara ser ut som ett felaktigt lösenord.
Tre saker avgör vilken källa för inloggningsuppgifter du bör använda: om en person sitter vid konsolen, om hemligheten får ligga på disken och om en annan process måste svara på prompten. Väljer du fel rapporterar klienten ett stdin-problem medan lösenordet är helt giltigt, och det skickar de flesta till servern utan anledning. Välj väg först; felmeddelandena blir bara begripliga när du vet vilken väg som skapade dem.
De tre villkor som avgör det
Konsolprompten är den enda vägen som kräver en människa, så den är den enda som misslyckas tyst i en systemd-enhet eller en container. Om en person startar klienten och skriver lösenordet är ingen fil inblandad och inget känsligt hamnar på disken. Om klienten startar vid boot blir samma prompt en hang, och tidsgränsen visas oftast som ett allmänt anslutningsfel i stället för ett inloggningsfel.
En inloggningsfil är rätt svar när processen startar utan övervakning och hemligheten kan överleva på disken under en kontrollerad uppsättning behörigheter. När hemligheten inte får skrivas alls - en policy med bara valv, en kortlivad token - behöver du en ström som klienten kan öppna, vilket i praktiken betyder processubstitution eller en hjälpare som skriver till en fildeskriptor. Administrationsgränssnittet täcker det fjärde fallet: en styrenhet som redan hanterar tunnellivscykeln och kan svara på frågor via en socket.
- Människa vid konsolen, ingen automatisering: interaktiv prompt.
- Start utan övervakning, hemligheten får lagras: inloggningsfil med läge 0600.
- Start utan övervakning, hemligheten får inte lagras: processubstitution eller en fd som en hemlighetsagent skriver till.
- En annan process äger klienten: administrationsgränssnittet.
När två svar passar, välj det som håller hemligheten utanför argv och utanför shell-historiken. Ett lösenord som skickas som programargument kan läsas av varje lokal användare via processlistan, och den exponeringen är svår att ångra.
Vad varje ingångsväg faktiskt gör
--auth-user-pass ensamt frågar efter användarnamn och lösenord i konsolen. Med ett filnamn tar klienten rad ett som användarnamn och rad två som lösenord; inget stöder citattecken, kommentarer eller nyckel-värde-syntax. Det är hela formatet, så den som redigerar det i förväntan på en INI-fil förstör det. Ett inbäddat <auth-user-pass>-block innehåller samma två rader i profilen, vilket gör profilen själv till en hemlighet och placerar den i samma hanteringsklass som en privat nyckel.
De två andra vägarna är en ström och en socket. OpenVPN behöver bara en läsbar fildeskriptor, så den accepterar en processubstitution, en rörstödd /dev/fd-post eller ett filnamn som faktiskt är en FIFO. Administrationsgränssnittet är annorlunda till sin natur: klienten frågar en övervakande process om värdena i stället för att läsa dem själv. Den skillnaden spelar roll vid återanslutning: en inloggningsfil, en FIFO som en hemlighetshjälpare kan skriva till igen och administrationsgränssnittet kan leverera på nytt utan en människa; processubstitution kan inte, eftersom deskriptorn förbrukas vid första läsningen.
Filen måste vara exakt två rader
Två fellägen täcker de flesta trasiga inloggningsfiler. En Windows-redigerare lämnar CRLF-radslut, vagnreturen blir en del av lösenordet och servern avvisar ett värde som ser korrekt ut på skärmen. En tom andra rad - en tom rad där lösenordet ska stå - lämnar klienten med ett tomt lösenord, som servern avvisar även om värdet på skärmen ser rätt ut. En extra ny rad efter lösenordet är ofarlig. Skriv filen från shellen, inte från en redigerare, och kontrollera byten:
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 -3Vägen är lika viktig som innehållet. En relativ väg löses mot processens arbetskatalog, som för en tjänst sällan är katalogen där du testade. Använd en absolut väg, låt filen ägas av kontot som kör klienten och behåll läge 0600 så att grupp och andra inte kan läsa den. OpenVPN 2.6-handboken listar de godtagna formerna för direktivet; kontrollera den innan du hittar på en tredje.
Testa filen innan du skyller på servern. Att köra openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 skriver ut om filen öppnades och senare om inloggningsuppgifterna godtogs, vilket säger vilket lager du ska ändra nästa gång.
Strömmar, stdin och felen de producerar
Att röra in lösenordet är det första de flesta provar och vägen med flest överraskningar. Processubstitution fungerar eftersom klienten bara behöver en läsbar deskriptor: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). Att skicka /dev/stdin fungerar bara när stdin fortfarande är öppen och läsbar i det ögonblick klienten frågar, vilket inte stämmer i en pipeline som redan förbrukat den.
ERROR: could not read Auth username from stdin har två olika orsaker. Hos en del 2.3.x-klienter kom meddelandet från ett fel i stdin-hanteringen som senare 2.3-utgåvor rättade, så en så gammal klient blir bara bättre av att uppgradera. Hos en aktuell klient betyder samma formulering att klienten bad om konsolinmatning och att stdin inte var en terminal - exakt situationen i en systemd-enhet, ett cron-jobb eller en container startad utan -t.
auth-nocache lägger till en tredje slinga som ser ut som ett trasigt lösenord. Det kastar inloggningsuppgifterna ur minnet efter användning, så en återanslutning som utlöses av en nätverksändring har inget att spela upp igen och prompten återkommer. Det är direktivet som fungerar som det är designat. auth-nocache ändrar vad klienten behåller i minnet, inte vad servern eller identitetsleverantören anser om kontot, så hela rättningen är att leverera samma fil på nytt, läst igen vid omstart - och för en hanterad anslutning bör den leveransen komma från det godkända hemlighetsarkivet, inte från ett lösenord i ett skript.
Administrationsgränssnittet när en annan process äger prompten
En styrenhet som redan övervakar tunneln kan också svara på dess frågor. Starta klienten med --management 127.0.0.1 7505, läs statusraderna och håll koll på >PASSWORD:Need 'Auth' username/password. Styrenheten svarar med username "Auth" alice följt av password "Auth" ... på separata kommandorader. 'Auth'-tokenet upprepar identifieraren från begäran och måste stämma, annars ignoreras svaret och klienten väntar.
Priset är en tillståndsmaskin som du nu äger: ordningen på anslutningar, omstarter av klienten och en lokal socket som andra användare på värden inte ska nå. Det du köper är en inloggningsuppgift som levereras vid körning, utan fil på disken och utan en prompt som kan hänga sig. Om inget annat i din stack redan talar protokollet, lägger den här vägen till en komponent som måste underhållas.
Fel som ser ut som inloggningsproblem
En TLS-handskakning som aldrig fullbordas, eller VERIFY ERROR: depth=0, error=certificate signature failure, är ett tillitsproblem och inträffar innan något användarnamn läses. En proto tcp-klient riktad mot en UDP-lyssnare misslyckas på samma ställe: paketen når aldrig autentiseringsfasen, så varje lösenord ser fel ut genom association. Håll certifikatverifieringen på innan inloggningsuppgifterna skickas; en bekant prompt säger ingenting om vem som tar emot lösenordet. Kontrollera certifikatkedjan, common name och transporten innan du rör inloggningsuppgifterna.
Shell-fel i skriptet som sätter ihop profilen är det andra falska spåret. Ett saknat mellanslag i [ ! -f "$file" ] ger command not found, skriptet stannar tidigt, profilen byggs aldrig om och klienten startar med den förra. Det felet tillhör shellen, inte autentiseringen, och hur många gånger du än skriver lösenordet på nytt försvinner det inte.
Inte varje prompt i det här flödet är den här inloggningsuppgiften. En lösenfras för en privat nyckel, en HTTP-proxyinloggning och tjänstens lösenord är tre olika hemligheter som efterfrågas i olika faser, och en nyckellösenfras hanteras oftast av klienten eller en agent i stället för auth-user-pass. Om prompten dyker upp innan TLS-sessionen är uppe svarar du på fel fråga och ingen kontoåterställning hjälper. När fel prompt är utesluten börjar de återstående kontrollerna på det tidigaste lagret:
- Läs det första protokollfelet, inte den sista inloggningsraden: TLS, sedan autentisering, sedan push.
- Bekräfta att filen är två rader, inte har vagnreturer och anges med en absolut väg.
- Bekräfta att profilen och kommandoraden inte är oense om direktivet.
- Skilj "inloggningsuppgifter godtagna" från "trafik flyter" - routing och DNS är ett senare lager.
När klienten når push-fasen, sluta titta på inloggningsuppgifterna och börja läsa rutterna och DNS-servrarna som servern skickade. Det är nästa problem, och det har inget att göra med lösenordet du just rättade.