Eșec RAND_bytes în OpenVPN: eroare de bibliotecă sau nod lipsă
Un eșec RAND_bytes poate însemna o sursă de entropie refuzată sau un nod ascuns de o închisoare. Citește coada de erori și vederea procesului înainte de a crea dispozitive.
RAND_bytes() failed este o afirmație despre o primitivă locală, nu despre cont, cheia prepartajată sau portul la distanță. Două defecțiuni foarte diferite produc aceeași linie și lasă în urmă dovezi diferite. Una este un backend criptografic care refuză să emită octeți; cealaltă este un proces care nu ajunge la sursa de entropie pentru care i-a fost construit codul. Separarea lor cere o citire a cozii de erori și o privire la vederea sistemului de fișiere a procesului închis, iar verificarea aceasta trebuie făcută înainte de a crea ceva sub /dev.
Ce distinge valoarea returnată
Contractul documentat separă trei rezultate, nu două: 1 pentru succes, -1 când metoda RAND încărcată nu acceptă cererea și 0 pentru celelalte eșecuri, explicația fiind lăsată cozii de erori. Referința RAND_bytes adaugă un punct ușor de trecut cu vederea: generatorul implicit se inițializează din sistemul de operare pe platformele acceptate, iar când această inițializare eșuează rămâne într-o stare de eroare în loc să livreze octeți previzibili.
Doar unul dintre aceste numere descrie mediul. Un -1 este o chestiune de compilare, de furnizor sau de funcționalitate, pentru că codul a cerut ceva ce implementarea activă nu oferă. Un 0 cu o plângere despre inițializare este o chestiune de mediu, pentru că generatorul nu a putut obține deloc entropie. Numărul singur nu spune niciodată care dintre ele, și nici numele funcției.
Când un nod de dispozitiv ascuns este cauza reală
Un serviciu restricționat vede un arbore diferit de shell-ul în care tastați. Închisorile chroot, imaginile de container și fișierele unitate întărite prezintă de obicei un /dev cu mai puține noduri decât cel al gazdei. Dacă implementarea care eșuează deschide /dev/urandom după cale, diferența aceasta e suficientă pentru a rupe pornirea în timp ce gazda pare perfect sănătoasă. Un dispozitiv care există în afara închisorii nu dovedește nimic despre ce are voie să deschidă procesul închis.
Nu orice interfață aleatoare are nevoie de o cale, totuși. Apelul de sistem getrandom din Linux nu acceptă nici nume de fișier, nici descriptor de fișier, iar pagina sa de manual notează că această proprietate este utilă exact acolo unde un chroot ascunde căile dispozitivelor.
Deci explicația nodului lipsă este o ipoteză despre o ramură a codului, nu o regulă despre numerele aleatoare în general. Ea rezistă când dovezile numesc o cale și este o presupunere când dovezile numesc altceva.
Citește coada de erori, apoi vederea procesului
Cea mai rapidă cale de a lămuri întrebarea este să citești ce a înregistrat deja biblioteca, apoi să te uiți direct la vederea din închisoare. Începe cu compilarea OpenSSL pe care serviciul a încărcat-o efectiv, pentru că stivele de furnizori diferă între versiunile majore și între distribuții. Întreabă apoi systemd ce proces rulează și ce restricții i se aplică. Abia după ce ambele fapte sunt pe masă merită să listezi nodurile pe care le poate vedea acel proces.
openssl version -a
systemctl show openvpn-server@lab -p MainPID -p PrivateDevices -p DevicePolicy
pid=$(systemctl show -p MainPID --value openvpn-server@lab)
sudo ls -l /proc/"$pid"/root/dev/urandom /proc/"$pid"/root/dev/random
Rulează citirile acelea pe același proces, nu pe shell-ul care se întâmplă să fie deschis. Compararea dispozitivului /dev al gazdei cu vederea unui proces fără legătură este felul în care dependența greșită este reparată de două ori.
Adaugă dependența doar după ce o poți numi
Când dovezile numesc într-adevăr o cale, reparația este mică: fă acea singură cale disponibilă în închisoare și nu atinge nimic altceva. O montare bind a nodului unic este de obicei suficientă, iar mknod cu numerele major și minor standard ale nodului produce același rezultat pe instalările unde montarea nu este o opțiune. Lărgirea sandbox-ului, acordarea accesului la fiecare dispozitiv de caractere sau oprirea PrivateDevices schimbă o corecție țintită pe o regresie de securitate permanentă.
Un demon de entropie nu înlocuiește reparația aceea. Pachete precum haveged schimbă modul în care este alimentat pool-ul nucleului; ele nu pot crea o cale pe care un proces închis are voie să o deschidă. Instalarea unuia poate face un grafic de sănătate să arate mai bine în timp ce apelul de deschidere tot eșuează. Ține cele două probleme separate, altfel următorul eșec va fi atribuit din nou stratului greșit.
Verifică separat generatorul și tunelul
O repornire este singurul test care refolosește aceeași configurație, același fișier unitate și același confinament care au produs eșecul. Rulează-l, apoi citește cele mai noi intrări din journal în loc de un eșantion dintr-o pornire anterioară.
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
Caută două lucruri separate în acea ieșire: mesajul despre sursa aleatoare care dispare și tunelul care ajunge la reperul său obișnuit de pornire. Un generator care funcționează din nou elimină un eșec local și nu spune nimic despre identitatea serverului, acreditările sau despre rutare. Testează asta cu aceeași configurație de client care eșua înainte, ca rezultatul să fie comparabil, nu doar mai bun.