RAND_bytes unter OpenVPN fehlgeschlagen: Bibliotheksfehler oder fehlender Knoten
Ein RAND_bytes-Fehler kann eine verweigerte Entropiequelle oder einen von einer Jail verdeckten Geräteknoten bedeuten. Lies die Fehlerwarteschlange und die Prozesssicht, bevor du Geräte anlegst.
RAND_bytes() failed ist eine Aussage über eine lokale Primitivfunktion, nicht über das Konto, den vorab vereinbarten Schlüssel oder den entfernten Port. Zwei sehr verschiedene Fehler erzeugen dieselbe Zeile und hinterlassen unterschiedliche Spuren. Der eine ist ein kryptografisches Backend, das sich weigert, Bytes auszugeben; der andere ist ein Prozess, der die Entropiequelle nicht erreicht, für die sein Code gebaut wurde. Sie zu trennen erfordert ein Lesen der Fehlerwarteschlange und einen Blick auf die Dateisystemsicht des eingesperrten Prozesses, und diese Prüfung gehört vor alles, was unter /dev angelegt wird.
Was der Rückgabewert unterscheidet
Der dokumentierte Vertrag unterscheidet drei Ausgänge, nicht zwei: 1 für Erfolg, -1 wenn die geladene RAND-Methode die Anfrage nicht unterstützt, und 0 für andere Fehler, wobei die Erklärung in der Fehlerwarteschlange bleibt. Die RAND_bytes-Referenz ergänzt einen leicht zu übersehenden Punkt: Der Standardgenerator initialisiert sich auf unterstützten Plattformen aus dem Betriebssystem, und wenn diese Initialisierung scheitert, bleibt er in einem Fehlerzustand, statt vorhersagbare Bytes zurückzugeben.
Nur eine dieser Zahlen beschreibt die Umgebung. Ein -1 ist eine Frage von Build, Provider oder Funktionalität, weil der Code etwas verlangte, das die aktive Implementierung nicht bietet. Ein 0 mit einer Klage über die Initialisierung ist eine Frage der Umgebung, weil der Generator überhaupt keine Entropie beziehen konnte. Die Zahl allein sagt nie, welche von beiden, und der Funktionsname auch nicht.
Wann ein verdeckter Geräteknoten die eigentliche Ursache ist
Ein eingeschränkter Dienst sieht einen anderen Baum als die Shell, in die Sie tippen. Chroot-Jails, Container-Images und gehärtete Unit-Dateien zeigen regelmäßig ein /dev, das weniger Knoten enthält als das des Hosts. Wenn die fehlerhafte Implementierung /dev/urandom über den Pfadnamen öffnet, reicht dieser Unterschied aus, um den Start zu brechen, während der Host selbst völlig gesund aussieht. Ein Gerät, das außerhalb der Jail existiert, beweist nichts darüber, was der eingesperrte Prozess öffnen darf.
Nicht jede Zufallsschnittstelle braucht jedoch einen Pfad. Der Systemaufruf getrandom von Linux akzeptiert weder einen Dateinamen noch einen Dateideskriptor, und seine Handbuchseite merkt an, dass diese Eigenschaft genau dort nützlich ist, wo ein Chroot Gerätepfade verbirgt.
Die Erklärung des fehlenden Knotens ist also eine Hypothese über einen Zweig des Codes, keine Regel über Zufallszahlen im Allgemeinen. Sie hält, wenn die Belege einen Pfad nennen, und sie ist Vermutung, wenn die Belege etwas anderes nennen.
Erst die Fehlerwarteschlange, dann die Prozesssicht lesen
Der schnellste Weg, die Frage zu klären, ist zu lesen, was die Bibliothek bereits aufgezeichnet hat, und dann direkt die Sicht in der Jail anzusehen. Beginnen Sie mit dem OpenSSL-Build, den der Dienst tatsächlich geladen hat, denn Provider-Stapel unterscheiden sich zwischen Hauptversionen und zwischen Distributionen. Fragen Sie dann systemd, welcher Prozess läuft und welche Einschränkungen für ihn gelten. Erst wenn beide Fakten auf dem Tisch liegen, lohnt es sich, die Knoten aufzulisten, die dieser Prozess sehen kann.
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
Führen Sie diese Prüfungen gegen denselben Prozess aus, nicht gegen die Shell, die gerade offen ist. Die /dev des Hosts mit der Sicht eines fremden Prozesses zu vergleichen, ist der Weg, auf dem die falsche Abhängigkeit zweimal repariert wird.
Die Abhängigkeit erst hinzufügen, wenn Sie sie benennen können
Wenn die Belege tatsächlich einen Pfad nennen, ist die Reparatur klein: Machen Sie genau diesen einen Pfad innerhalb der Jail verfügbar und lassen Sie alles andere in Ruhe. Ein Bind-Mount des einzelnen Knotens genügt meist, und mknod mit den üblichen Major- und Minor-Nummern des Knotens liefert dasselbe Ergebnis auf Installationen, bei denen kein Mount möglich ist. Die Sandbox zu erweitern, Zugriff auf jedes Zeichengerät zu gewähren oder PrivateDevices abzuschalten tauscht eine gezielte Korrektur gegen eine dauerhafte Sicherheitsregression.
Ein Entropie-Daemon ersetzt diese Reparatur nicht. Pakete wie haveged ändern, wie der Kernel-Pool gespeist wird; sie können keinen Pfadnamen erzeugen, den ein eingesperrter Prozess öffnen darf. Eines zu installieren kann einen Gesundheitsgraphen besser aussehen lassen, während der Open-Aufruf weiterhin scheitert. Halten Sie die beiden Probleme getrennt, sonst wird der nächste Fehler wieder der falschen Schicht zugeschrieben.
Generator und Tunnel getrennt prüfen
Ein Neustart ist der einzige Test, der dieselbe Konfiguration, dieselbe Unit-Datei und dieselbe Abschottung wiederverwendet, die den Fehler erzeugt haben. Führen Sie ihn aus und lesen Sie dann die neuesten Journal-Einträge statt einer Stichprobe von einem früheren Start.
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
Suchen Sie zwei getrennte Dinge in dieser Ausgabe: die Meldung zur Zufallsquelle, die verschwindet, und den Tunnel, der seinen üblichen Startmeilenstein erreicht. Ein Generator, der wieder funktioniert, beseitigt einen lokalen Fehler und sagt nichts über Serveridentität, Anmeldedaten oder Routing. Prüfen Sie das mit derselben Client-Konfiguration, die zuvor scheiterte, damit das Ergebnis vergleichbar und nicht nur besser ist.