RAND_bytes() failed er en uttalelse om én lokal primitiv, ikke om kontoen, den forhåndsdelt nøkkelen eller fjernporten. To svært forskjellige feil gir samme linje og etterlater forskjellige spor. Den ene er en kryptografisk backend som nekter å sende ut byte; den andre er en prosess som ikke når entropikilden den er bygget for. Å skille dem krever én lesing av feilkøen og ett blikk på den innesperrede prosessens egen filsystemvisning, og den kontrollen hører hjemme før noe opprettes under /dev.

Hva returverdien skiller

Den dokumenterte kontrakten skiller tre utfall, ikke to: 1 for suksess, -1 når den innlastede RAND-metoden ikke støtter forespørselen, og 0 for andre feil, med forklaringen overlatt til feilkøen. RAND_bytes-referansen tilføyer et punkt som er lett å overse: standardgeneratoren initialiseres fra operativsystemet på støttede plattformer, og når den initialiseringen feiler, blir den stående i en feiltilstand i stedet for å levere forutsigbare byte.

Bare ett av disse tallene beskriver miljøet. En -1 er et spørsmål om bygg, leverandør eller funksjonalitet, fordi koden ba om noe den aktive implementeringen ikke tilbyr. En 0 med en klage om initialisering er et miljøspørsmål, fordi generatoren ikke fikk tak i entropi i det hele tatt. Tallet alene sier aldri hvilket, og funksjonsnavnet gjør det heller ikke.

Når en skjult enhetsnode er den egentlige årsaken

En innesperret tjeneste ser et annet tre enn skallet du skriver i. Chroot-fengsler, containerbilder og herdede unit-filer viser rutinemessig en /dev med færre noder enn vertens. Hvis implementeringen som feiler åpner /dev/urandom via stinavnet, er den forskjellen nok til å bryte oppstarten mens verten selv ser helt frisk ut. En enhet som finnes utenfor fengselet beviser ingenting om hva den innesperrede prosessen har lov til å åpne.

Ikke alle tilfeldige grensesnitt trenger en sti, likevel. Systemkallet getrandom i Linux godtar verken filnavn eller fildeskriptor, og manualsiden bemerker at denne egenskapen nettopp er nyttig der en chroot skjuler enhetsstier.

Så forklaringen om den manglende noden er en hypotese om én gren av koden, ikke en regel om tilfeldige tall generelt. Den holder når bevisene nevner en sti, og den er gjetning når bevisene nevner noe annet.

Les feilkøen, så prosessvisningen

Den raskeste måten å avgjøre spørsmålet er å lese hva biblioteket allerede har registrert, og deretter se direkte på visningen inne i fengselet. Begynn med OpenSSL-bygget tjenesten faktisk lastet, fordi leverandørstakker er forskjellige mellom hovedversjoner og mellom distribusjoner. Spør deretter systemd hvilken prosess som kjører og hvilke begrensninger som gjelder for den. Først når begge fakta ligger på bordet, er det verdt å liste nodene den prosessen kan se.

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

Kjør disse lesingene mot samme prosess, ikke mot skallet som tilfeldigvis er åpent. Å sammenligne vertens /dev med visningen til en urelatert prosess er hvordan den gale avhengigheten blir reparert to ganger.

Legg til avhengigheten først når du kan navngi den

Når bevisene faktisk nevner en sti, er reparasjonen liten: gjør nettopp den stien tilgjengelig inne i fengselet og la alt annet være. En bind-montering av den enkelte noden er vanligvis nok, og mknod med nodens standard major- og minortall gir samme resultat på installasjoner der montering ikke er et alternativ. Å utvide sandkassen, gi tilgang til hver tegnenhet eller slå av PrivateDevices bytter en målrettet rettelse mot en permanent sikkerhetsregresjon.

En entropi-demon erstatter ikke den reparasjonen. Pakker som haveged endrer hvordan kjernebassenget fores; de kan ikke lage et stinavn som en innesperret prosess har lov til å åpne. Å installere en kan få en helsegraf til å se bedre ut mens open-kallet fortsatt feiler. Hold de to problemene fra hverandre, ellers blir neste feil igjen tilskrevet feil lag.

Kontroller generatoren og tunnelen hver for seg

En omstart er den eneste testen som gjenbruker samme konfigurasjon, samme unit-fil og samme innesperring som frembragte feilen. Kjør den, og les deretter de nyeste journaloppføringene i stedet for et utvalg fra en tidligere oppstart.

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

Se etter to atskilte ting i den utskriften: meldingen om tilfeldighetskilden som forsvinner, og tunnelen som når sin vanlige oppstartsmilepæl. En generator som virker igjen fjerner én lokal feil og sier ingenting om serveridentitet, påloggingsdetaljer eller ruting. Test det med samme klientkonfigurasjon som feilet før, slik at resultatet blir sammenlignbart og ikke bare bedre.

Relaterte artikler