Fișier de acreditări sau socket de administrare OpenVPN: pe care să îl scriptezi
auth-user-pass acoperă promptul contului; socketul de administrare le acoperă pe toate patru. Compară expunerea, costul scriptului și felul în care fiecare eșuează într-un serviciu.
Un script care pornește OpenVPN și nu se conectează niciodată nu este de obicei o problemă de rețea: clientul stă la un prompt fără terminal pe care să îl deseneze. OpenVPN are exact două moduri acceptate de a răspunde la acel prompt fără un om, un fișier de acreditări în spatele auth-user-pass și socketul de administrare, iar acestea nu sunt interschimbabile. Fișierul costă o directivă și răspunde la un prompt; socketul răspunde la fiecare prompt și dă oricui poate deschide un port loopback un canal de control neautentificat. Care aparține implementării tale depinde de ce prompt blochează de fapt și de ce secret îți permiți să lași în repaus.
Numește promptul înainte de a alege un mecanism
Patru prompturi arată identic pe un terminal. Perechea de cont vine din configurarea PAM sau auth-user-pass-verify a serverului și este răspunsă de auth-user-pass. Fraza de acces a unei chei private aparține fișierului cheii și se citește prin --askpass sau se tastează manual. Un pachet PKCS#12 cere o parolă proprie. Autentificarea proxy folosește fișierul auth pe care îl preia --http-proxy, nu acreditările contului.
Când OpenVPN rulează ca fiu al systemd, PHP sau Node nu există terminal, așa că fiecare dintre acestea blochează în tăcere. Procesul stă acolo, jurnalul se oprește după linia cifrului și unitatea ajunge în cele din urmă la expirare; acea tăcere este motivul pentru care oamenii adaugă o buclă de reîncercare sau un sleep în loc să se uite care prompt este în așteptare. Doar socketul de administrare poate răspunde la toate patru. Fișierul de acreditări răspunde la primul și la nimic altceva.
auth-user-pass: un fișier, un prompt
Fișierul conține numele de utilizator pe primul rând și parola pe al doilea, și nimic altceva: fără ghilimele, fără nume de chei, fără comentariu. Setează modul 600 și fă proprietar contul care rulează openvpn, care pentru un serviciu este adesea un utilizator dedicat și nu autentificarea ta. Un fișier deținut de root sub /root este diferența dintre o comandă care funcționează în shellul tău și o unitate care eșuează la pornire.
Două detalii transformă un fișier corect într-un prompt. Un editor care salvează CRLF lasă un retur de car lipit de parolă, așa că serverul respinge o parolă care în fișier pare corectă; verifică cu cat -A sau od -c, nu cu ochiul. Iar un auth-user-pass fără argument în profil înseamnă prin proiectare «întreabă utilizatorul», ceea ce o a doua directivă pe linia de comandă poate să nu anuleze, pentru că profilul este analizat acolo unde se află.
Ordinea opțiunilor este a treia capcană și depinde de versiune. Unele compilări OpenVPN 2.4 ignoră --auth-user-pass când apare înainte de --config, așa că aceleași două opțiuni în cealaltă ordine se conectează. Pune directiva în profil sau după --config pe linia de comandă și caută în profil fiecare apariție înainte de a schimba altceva.
auth-nocache aparține acestui mecanism dar nu furnizează nimic. Limitează cât timp clientul ține acreditările în memorie, ceea ce ajută după o cădere și nu ajută deloc când fișierul lipsește. O reconectare după expirarea sesiunii pe server recitește fișierul, așa că o acreditare care a funcționat la pornire poate expira la mijlocul zilei.
Socketul de administrare: fiecare prompt, mai multă suprafață
Pornește clientul cu un ascultător și declară explicit că prompturile vor fi raportate pe el, folosind directivele documentate în manualul OpenVPN 2.6:
management 127.0.0.1 3030
management-query-passwords
Din bash ține conexiunea pe un descriptor de fișier liber și răspunde după numele promptului, nu după poziție, pentru că o reconectare poate întreba în altă ordine:
exec 3<>/dev/tcp/127.0.0.1/3030
while read -r -u 3 line; do
case "$line" in
*"Need 'Auth' username/password"*)
echo 'username "Auth" alice' >&3
echo 'password "Auth" secret' >&3 ;;
*"Need 'Private Key' password"*)
echo 'password "Private Key" secret' >&3 ;;
esac
done
Granularitatea este transportul. Protocolul de administrare este text simplu peste TCP pe loopback, așa că ascultătorul nu trebuie publicat pe o adresă LAN sau de tunel pentru ca un controler remote să ajungă la el; un controler remote înseamnă o redirecționare SSH, nu o legare mai largă. Daemonul comunității acceptă și un singur client de administrare o dată, așa că o GUI sau un monitor nu pot partaja socketul cu scriptul tău. A doua conexiune este refuzată, nu pusă în coadă, iar eșecul arată ca un script care a surzit.
Acest socket este și un canal de control. Fără o parolă de administrare, orice se poate conecta la 127.0.0.1:3030 poate citi starea, ucide tunelul sau răspunde singur la un prompt. Parola de administrare și fișierul de acreditări sunt secrete din aceeași clasă, iar ambele merită aceeași grijă.
Care se potrivește implementării
Alege fișierul de acreditări când singurul prompt este perechea de cont, clientul rulează ca serviciu cu un proprietar stabil și poți ține un fișier 600 în afara copiilor de siguranță pe care nu le controlezi. Alege socketul de administrare când este în joc o frază de acces a cheii sau o parolă PKCS#12, când wrapperul supraveghează deja procesul sau când trebuie să urmărești starea și prompturile în timp ce depanezi o reconectare.
Două condiții mișcă decizia. Dacă wrapperul este /bin/sh, o unitate systemd care apelează binarul direct sau un container minimal, lipiciul de socket doar pentru bash nu este disponibil și fișierul este răspunsul mai ieftin. Dacă secretul se rotește des, niciun fișier nu este o casă bună pentru el: întreabă un portchei dintr-un wrapper mic și lasă unitatea să apeleze wrapperul, ceea ce ține rotația într-un singur loc și parola în afara istoricului shellului.
Substituția de procese stă între cele două și nu aparține niciuneia. Comanda de o linie de mai jos funcționează pentru că bash o extinde înainte ca openvpn să pornească, nu pentru că clientul ar înțelege sintaxa:
openvpn --config client.ovpn --auth-user-pass <(printf "%s
%s
" "$USER" "$PASS")
Se rupe sub /bin/sh, într-o unitate care ocolește shellul și în imagini fără bash sau /dev/fd. Păstreaz-o pentru teste interactive, niciodată ca acordul de care depinde un serviciu.
Protejează secretul, apoi verifică din jurnal
Ambele mecanisme lasă un secret care poate fi citit de procesul OpenVPN. Nu pune niciodată parola pe linia de comandă sau în fișierul unității, unde ps și systemctl o arată fiecărui utilizator local; transmite calea către fișier, nu valoarea din el. Acolo unde certificatele pot înlocui perechea de cont, asta elimină categoria de prompt în loc să o ascundă.
O rulare corectă arată secvența de prompturi completându-se și sesiunea ajungând la «Initialization Sequence Completed». Dacă clientul se oprește la același prompt, potrivirea a eșuat: tipărește liniile exacte pe care le-a trimis socketul, verifică ghilimelele și numele promptului și corectează modelul în loc să adaugi un sleep. Un tunel care raportează succes și nu transportă nimic este o problemă de rutare sau de push, nu de acreditări.
Apoi testează reconectarea, nu doar prima pornire. Taie sesiunea din partea serverului sau așteaptă expirarea ei; clientul întreabă din nou, și acolo un fișier care părea corect la pornire arată dacă mai este citibil de contul care se reconectează.