RAND_bytes() failed är ett påstående om en lokal primitiv, inte om kontot, den fördelade nyckeln eller fjärrporten. Två mycket olika fel ger samma rad och lämnar olika spår. Det ena är en kryptografisk backend som vägrar avge byte; det andra är en process som inte når den entropikälla som dess kod byggdes för. Att skilja dem åt kräver en läsning av felkön och en blick på den inspärrade processens egen filsystemsbild, och den kontrollen hör hemma innan något skapas under /dev.

Vad returvärdet skiljer åt

Det dokumenterade kontraktet skiljer tre utfall, inte två: 1 för framgång, -1 när den laddade RAND-metoden inte stöder begäran och 0 för andra fel, med förklaringen kvar i felkön. RAND_bytes-referensen tillägger en punkt som är lätt att missa: standardgeneratorn initieras från operativsystemet på plattformar som stöds, och när den initieringen misslyckas stannar den i ett feltillstånd i stället för att lämna tillbaka förutsägbara byte.

Bara en av de siffrorna beskriver miljön. Ett -1 är en fråga om bygge, leverantör eller funktionalitet, eftersom koden bad om något som den aktiva implementationen inte erbjuder. En 0 med ett klagomål om initiering är en miljöfråga, eftersom generatorn inte alls kunde skaffa entropi. Siffran i sig säger aldrig vilket, och funktionsnamnet gör det inte heller.

När en dold enhetsnod är den verkliga orsaken

En begränsad tjänst ser ett annat träd än det skal du skriver i. Chroot-jails, containeravbildningar och härdade unitfiler visar rutinmässigt en /dev med färre noder än värden. Om den felande implementationen öppnar /dev/urandom via sökvägen räcker den skillnaden för att bryta uppstarten medan värden själv ser helt frisk ut. En enhet som finns utanför jailingen bevisar ingenting om vad den inspärrade processen får öppna.

Inte varje slumpmässigt gränssnitt behöver dock en sökväg. Linux systemanrop getrandom accepterar varken filnamn eller fildeskriptor, och dess manualsida noterar att den egenskapen är användbar just där en chroot döljer enhetssökvägar.

Så förklaringen med den saknade noden är en hypotes om en gren av koden, inte en regel om slumptal i allmänhet. Den håller när bevisen namnger en sökväg, och den är gissning när bevisen namnger något annat.

Läs felkön, sedan processvyn

Det snabbaste sättet att avgöra frågan är att läsa vad biblioteket redan har registrerat och sedan titta direkt på vyn inne i jailingen. Börja med det OpenSSL-bygge som tjänsten faktiskt laddade, eftersom leverantörsstackar skiljer sig mellan huvudversioner och mellan distributioner. Fråga sedan systemd vilken process som körs och vilka begränsningar som gäller för den. Först när båda fakta ligger på bordet är det värt att lista de noder som processen 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

Kör de läsningarna mot samma process, inte mot det skal som råkar vara öppet. Att jämföra värdens /dev med en orelaterad process vy är hur det felaktiga beroendet blir reparerat två gånger.

Lägg till beroendet först när du kan namnge det

När bevisen faktiskt namnger en sökväg är reparationen liten: gör just den sökvägen tillgänglig inne i jailingen och lämna allt annat i fred. En bind-montering av den enskilda noden räcker oftast, och mknod med nodens standard major- och minortal ger samma resultat på installationer där montering inte är ett alternativ. Att vidga sandlådan, ge åtkomst till varje teckenenhet eller stänga av PrivateDevices byter en riktad rättelse mot en permanent säkerhetsregression.

En entropidaemon ersätter inte den reparationen. Paket som haveged ändrar hur kärnpoolen matas; de kan inte skapa en sökväg som en inspärrad process får öppna. Att installera en kan få en hälsograf att se bättre ut medan open-anropet fortfarande misslyckas. Håll de två problemen åtskilda, annars tillskrivs nästa fel igen fel lager.

Kontrollera generatorn och tunneln var för sig

En omstart är det enda testet som återanvänder samma konfiguration, samma unitfil och samma avskärmning som gav upphov till felet. Kör den och läs sedan de nyaste journalposterna i stället för ett urval från en tidigare start.

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

Leta efter två separata saker i den utskriften: meddelandet om slumpkällan som försvinner, och tunneln som når sin vanliga uppstartsmilstolpe. En generator som fungerar igen tar bort ett lokalt fel och säger ingenting om serveridentitet, autentiseringsuppgifter eller routing. Testa det med samma klientkonfiguration som misslyckades tidigare, så att resultatet blir jämförbart och inte bara bättre.

Relaterade artiklar