RAND_bytes() failed on väite yhdestä paikallisesta primitiivistä, ei tilistä, ennalta jaetusta avaimesta tai etäportista. Kaksi hyvin erilaista vikaa tuottaa saman rivin ja jättää erilaiset jäljet. Toinen on salausbackend, joka kieltäytyy lähettämästä tavuja; toinen on prosessi, joka ei tavoita entropialähdettä, jota varten sen koodi rakennettiin. Niiden erottaminen vaatii yhden virhejonon luvun ja yhden silmäyksen vangitun prosessin tiedostojärjestelmänäkymään, ja tarkistus kuuluu ennen kaikkea, mitä /dev-hakemistoon luodaan.

Mitä paluuarvo erottaa

Dokumentoitu sopimus erottaa kolme tulosta, ei kahta: 1 onnistumiselle, -1 kun ladattu RAND-menetelmä ei tue pyyntöä, ja 0 muille vioille, jolloin selitys jää virhejonoon. RAND_bytes-viite lisää kohdan, joka on helppo sivuuttaa: oletusgeneraattori siementää itsensä käyttöjärjestelmästä tuetuilla alustoilla, ja kun siemennys epäonnistuu, se jää virhetilaan sen sijaan, että palauttaisi ennustettavia tavuja.

Vain yksi noista luvuista kuvaa ympäristöä. -1 on kysymys koonnista, toimittajasta tai ominaisuudesta, koska koodi pyysi jotain, mitä aktiivinen toteutus ei tarjoa. 0 siemennysvalituksella on ympäristökysymys, koska generaattori ei saanut entropiaa lainkaan. Luku yksinään ei koskaan kerro kumpi, eikä funktion nimi kerro sitä myöskään.

Kun piilotettu laitesolmu on todellinen syy

Rajoitettu palvelu näkee eri puun kuin se komentotulkki, johon kirjoitat. Chroot-vankilat, konttikuvat ja koventnetut unit-tiedostot esittävät säännöllisesti /dev-solmun, jossa on vähemmän solmuja kuin isännän vastaavassa. Jos epäonnistuva toteutus avaa /dev/urandom-polun nimen perusteella, tuo ero riittää rikkomaan käynnistyksen, vaikka isäntä itse näyttää täysin terveeltä. Vankilan ulkopuolella oleva laite ei todista mitään siitä, mitä vangittu prosessi saa avata.

Jokainen satunnainen rajapinta ei kuitenkaan tarvitse polkua. Linuxin getrandom-järjestelmäkutsu ei hyväksy tiedostonimeä eikä tiedostokuvaajaa, ja sen käsikirjasivu huomauttaa, että tämä ominaisuus on hyödyllinen juuri siellä, missä chroot piilottaa laitepolut.

Puuttuvan solmun selitys on siis hypoteesi koodin yhdestä haarasta, ei yleinen sääntö satunnaisluvuista. Se pitää, kun todisteet nimeävät polun, ja se on arvailua, kun todisteet nimeävät jotain muuta.

Lue virhejono, sitten prosessin näkymä

Nopein tapa ratkaista kysymys on lukea, mitä kirjasto on jo tallentanut, ja katsoa sitten suoraan vankilan sisäistä näkymää. Aloita OpenSSL-koonnista, jonka palvelu tosiasiassa latasi, koska toimittajapinot eroavat pääversioiden ja jakelujen välillä. Kysy sitten systemdiltä, mikä prosessi on käynnissä ja mitkä rajoitukset siihen kohdistuvat. Vasta kun molemmat tosiasiat ovat pöydällä, kannattaa luetella solmut, jotka kyseinen prosessi näkee.

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

Tee nuo luvut samasta prosessista, älä komentotulkista, joka sattuu olemaan auki. Isännän /dev-solmun vertaaminen asiaankuulumattoman prosessin näkymään on tapa, jolla väärä riippuvuus korjataan kahdesti.

Lisää riippuvuus vasta, kun osaat nimetä sen

Kun todisteet todella nimeävät polun, korjaus on pieni: tee juuri se yksi polku saatavilla vankilan sisällä ja jätä kaikki muu rauhaan. Yhden solmun bind-liitos riittää yleensä, ja mknod solmun tavallisilla major- ja minor-numeroilla antaa saman tuloksen asennuksissa, joissa liittäminen ei ole vaihtoehto. Hiekkalaatikon laajentaminen, pääsyn antaminen jokaiseen merkkilaitteeseen tai PrivateDevices-asetuksen poistaminen vaihtaa kohdennetun korjauksen pysyvään tietoturvaregressioon.

Entropiademoni ei korvaa tuota korjausta. Paketit kuten haveged muuttavat sitä, miten ytimen allasta ruokitaan; ne eivät voi luoda polkua, jonka vangittu prosessi saa avata. Yhden asentaminen voi parantaa terveyskuvaajan ulkoasua, kun avauskutsu yhä epäonnistuu. Pidä kaksi ongelmaa erillään, muuten seuraava vika kohdistetaan taas väärään kerrokseen.

Tarkista generaattori ja tunneli erikseen

Uudelleenkäynnistys on ainoa testi, joka käyttää uudelleen samaa kokoonpanoa, samaa unit-tiedostoa ja samaa eristystä, jotka aiheuttivat vian. Suorita se ja lue sitten uusimmat lokimerkinnät sen sijaan, että ottaisit otoksen aiemmasta käynnistyksestä.

sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'

Etsi tuosta tulosteesta kahta erillistä asiaa: viesti satunnaislähteestä katoaa, ja tunneli saavuttaa tavallisen käynnistysvaiheensa. Uudelleen toimiva generaattori poistaa yhden paikallisen vian eikä kerro mitään palvelimen identiteetistä, tunnisteista tai reitityksestä. Testaa se samalla asiakaskokoonpanolla, joka aiemmin epäonnistui, jotta tulos on vertailukelpoinen eikä vain parempi.

Aiheeseen liittyvät artikkelit