OpenVPN auth-user-pass: soubor, stdin, nebo výzva? Jak vybrat
Rozhodněte se mezi výzvou v konzoli, souborem přihlašovacích údajů, streamem a rozhraním pro správu a pak opravte chyby, které jen vypadají jako špatné heslo.
Který zdroj přihlašovacích údajů použít, rozhodují tři věci: zda u konzole sedí člověk, zda smí tajemství žít na disku a zda na výzvu musí odpovídat jiný proces. Zvolte špatně a klient ohlásí problém se stdin, přitom je heslo zcela platné, což většinu lidí bez důvodu pošle na server. Nejprve vyberte cestu; chybové zprávy dávají smysl, teprve když víte, která cesta je vyvolala.
Tři podmínky, které to rozhodují
Výzva v konzoli je jediná cesta, která potřebuje člověka, a proto je jediná, která v systemd unit nebo kontejneru tiše selže. Když klienta spustí člověk a napíše heslo, nevstupuje do hry žádný soubor a na disk se nedostane nic citlivého. Když se klient spustí při bootu, stejná výzva se změní v zaseknutí a časový limit se obvykle projeví jako obecné selhání připojení, nikoli jako chyba přihlašovacích údajů.
Soubor přihlašovacích údajů je správná odpověď, když proces startuje bez dozoru a tajemství smí na disku přežít pod kontrolovanou sadou oprávnění. Když se tajemství nesmí zapsat vůbec - zásada pouze trezoru, krátkodobý token - potřebujete stream, který klient dokáže otevřít, což v praxi znamená substituci procesu nebo pomocníka zapisujícího do deskriptoru souboru. Rozhraní pro správu pokrývá čtvrtý případ: kontroler, který už řídí životní cyklus tunelu a umí odpovídat na otázky přes socket.
- Člověk u konzole, žádná automatizace: interaktivní výzva.
- Start bez dozoru, tajemství se smí uložit: soubor přihlašovacích údajů s režimem 0600.
- Start bez dozoru, tajemství se nesmí uložit: substituce procesu nebo fd, do kterého zapisuje agent pro tajemství.
- Klienta vlastní jiný proces: rozhraní pro správu.
Když se hodí dvě odpovědi, vyberte tu, která drží tajemství mimo argv a mimo historii shellu. Heslo předané jako argument programu může číst každý lokální uživatel přes seznam procesů a toto vystavení se těžko odčiní.
Co každá vstupní cesta skutečně dělá
--auth-user-pass sám o sobě žádá uživatelské jméno a heslo v konzoli. Když dostane název souboru, klient bere první řádek jako uživatelské jméno a druhý jako heslo; nic nepodporuje uvozovky, komentáře ani syntaxi klíč-hodnota. To je celý formát, takže kdokoli ho upraví v očekávání souboru INI, ho rozbije. Vložený blok <auth-user-pass> drží stejné dva řádky uvnitř profilu, což dělá z profilu samotného tajemství a řadí ho do stejné třídy zacházení jako soukromý klíč.
Zbývající dvě cesty jsou stream a socket. OpenVPN potřebuje jen čitelný deskriptor souboru, takže přijme substituci procesu, položku /dev/fd napojenou na rouru nebo název souboru, který je ve skutečnosti FIFO. Rozhraní pro správu je jiné povahy: klient se ptá dohlížejícího procesu na hodnoty, místo aby je četl sám. Ten rozdíl je důležitý při opětovném připojení: soubor přihlašovacích údajů, FIFO, do kterého pomocník pro tajemství umí znovu zapsat, i rozhraní pro správu dokážou dodat hodnoty bez člověka; substituce procesu ne, protože deskriptor se prvním čtením spotřebuje.
Soubor musí mít přesně dva řádky
Většinu rozbitých souborů přihlašovacích údajů pokrývají dva režimy selhání. Editor ve Windows nechává konce CRLF, návrat vozíku se stane součástí hesla a server odmítne hodnotu, která na obrazovce vypadá správně. Prázdný druhý řádek - prázdný řádek tam, kde má být heslo - nechá klienta s prázdným heslem, které server odmítne, i když hodnota na obrazovce vypadá správně. Přebytečný nový řádek za heslem nevadí. Pište soubor ze shellu, ne z editoru, a zkontrolujte bajty:
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 -3Cesta je stejně důležitá jako obsah. Relativní cesta se vyhodnocuje vůči pracovnímu adresáři procesu, který u služby málokdy bývá adresářem, kde jste testovali. Použijte absolutní cestu, nechte soubor vlastnit účet, který klienta spouští, a držte režim 0600, aby ho skupina a ostatní nemohli číst. Manuál OpenVPN 2.6 uvádí přijímané formy direktivy; projděte ho, než vymyslíte třetí.
Otestujte soubor, než obviníte server. Spuštění openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 vypíše, zda se soubor otevřel, a později, zda byly přihlašovací údaje přijaty, což vám řekne, kterou vrstvu změnit příště.
Streamy, stdin a chyby, které produkují
Poslat heslo rourou zkouší většina lidí jako první a je to cesta s nejvíce překvapeními. Substituce procesu funguje, protože klient potřebuje jen čitelný deskriptor: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). Předání /dev/stdin funguje jen tehdy, když je stdin v okamžiku dotazu stále otevřený a čitelný, což v rourě, která ho už spotřebovala, neplatí.
ERROR: could not read Auth username from stdin má dvě různé příčiny. U některých klientů 2.3.x zpráva pocházela ze závady ve zpracování stdin, kterou pozdější vydání 2.3 opravila, takže tak starý klient se zlepší jen aktualizací. U současného klienta stejná formulace znamená, že klient požádal o vstup z konzole a stdin nebyl terminál - přesně situace v systemd unit, úloze cron nebo kontejneru spuštěném bez -t.
auth-nocache přidává třetí smyčku, která vypadá jako rozbité heslo. Zahazuje přihlašovací údaje z paměti po použití, takže opětovné připojení vyvolané změnou sítě nemá co přehrát a výzva se vrátí. To je direktiva fungující tak, jak má. auth-nocache mění to, co klient drží v paměti, ne to, co si server nebo poskytovatel identity myslí o účtu, takže celá oprava je znovu dodat stejný soubor, znovu načtený při restartu - a u spravovaného připojení má toto dodání přijít ze schváleného úložiště tajemství, ne z hesla ve skriptu.
Rozhraní pro správu, když výzvu vlastní jiný proces
Kontroler, který tunel už dohlíží, umí odpovídat i na jeho otázky. Spusťte klienta s --management 127.0.0.1 7505, čtěte stavové řádky a sledujte >PASSWORD:Need 'Auth' username/password. Kontroler odpovídá username "Auth" alice následovaným password "Auth" ... na samostatných příkazových řádcích. Token 'Auth' opakuje identifikátor z požadavku a musí sedět, jinak se odpověď ignoruje a klient čeká.
Cena je stavový stroj, který teď vlastníte: pořadí připojení, restarty klienta a lokální socket, ke kterému se ostatní uživatelé na hostiteli nesmějí dostat. Co kupujete, jsou přihlašovací údaje dodané za běhu, bez souboru na disku a bez výzvy, která se může zaseknout. Pokud nic jiného ve vašem stacku už protokol nemluví, tato cesta přidá komponentu k údržbě.
Selhání, která vypadají jako problémy s přihlašovacími údaji
TLS handshake, který se nikdy nedokončí, nebo VERIFY ERROR: depth=0, error=certificate signature failure, je problém důvěry a nastává dřív, než se přečte jakékoli uživatelské jméno. Klient proto tcp namířený na UDP listener selhává na stejném místě: pakety se nikdy nedostanou do fáze autentizace, takže každé heslo vypadá špatně asociací. Ponechte ověřování certifikátů zapnuté, než se údaje odešlou; známá výzva nic neříká o tom, kdo heslo přijímá. Zkontrolujte řetěz certifikátů, common name a transport, než sáhnete na přihlašovací údaje.
Chyby shellu ve skriptu, který skládá profil, jsou druhá falešná stopa. Chybějící mezera uvnitř [ ! -f "$file" ] vyprodukuje command not found, skript se zastaví brzy, profil se nikdy nepřestaví a klient nastartuje s předchozím. Ta chyba patří shellu, ne autentizaci, a žádné přepisování hesla ji neodstraní.
Ne každá výzva v tomto toku je tento přihlašovací údaj. Passphrase soukromého klíče, přihlášení přes HTTP proxy a heslo služby jsou tři různá tajemství vyžadovaná v různých fázích a passphrase klíče obvykle obsluhuje klient nebo agent, ne auth-user-pass. Pokud se výzva objeví dřív, než je TLS relace navázaná, odpovídáte na špatnou otázku a žádné resetování účtu nepomůže. Jakmile je špatná výzva vyloučena, zbývající kontroly začínají u nejranější vrstvy:
- Čtěte první chybu protokolu, ne poslední řádek s údaji: TLS, pak autentizace, pak push.
- Ověřte, že soubor má dva řádky, neobsahuje návraty vozíku a je odkazován absolutní cestou.
- Ověřte, že profil a příkazový řádek si ohledně direktivy neodporují.
- Oddělte "údaje přijaty" od "provoz teče" - směrování a DNS jsou pozdější vrstva.
Jakmile klient dosáhne fáze push, přestaňte hledět na přihlašovací údaje a začněte číst trasy a DNS servery, které server poslal. To je další problém a s heslem, které jste právě opravili, nemá nic společného.