Random Number Generators in virtuellen Maschinen

Blockierendes /dev/random

Benötigt ein Prozess auf einem Linux Server eine Zufallsquelle, dann kann er hierfür auf die unter Linux Betriebssystemen üblichen Quellen /dev/random und /dev/urandom zurückgreifen. Hier gibt es einen wesentlichen Unterschied: random blockiert, wenn es keine hinreichend zufälligen Werte mehr liefern kann. Die Quelle urandom hingegen liefert weiter Werte, jedoch sind diese mit abfallender Entropie weniger zufällig.

Virtualisierte Server verfügen in der Regel nicht über Hardwareresourcen, welche sich eignen würden, um zufällige Startwerte für einen Zufallsgenerator zu bilden (beispielsweise ein Trusted Platform Modul, TPM). Auf Grund dessen erschöpft sich der Entropiepool hier sehr schnell und /dev/random liefert keine Werte mehr. Dies kann dann, wie in JDBC Zugriff auf Oracle-Datenbank scheitert mit I/O-Fehler: Connection reset (1) beschrieben, auch dazu führen, dass zwei Applikationen nicht verschlüsselt miteinander kommunizieren können.

Je nach Szenario kann dann auf eine schlechte, also weniger zufällige Quelle ausgewichen werden, um Verzögerungen durch die blockierende Zufallsquelle zu vermeiden. Hier kann dann die Wahl auf /dev/urandom fallen.

Wird die Zufallsquelle jedoch, wie im oben erwähnten Blog Post beschrieben, für die Initialisierung kryptographischer Schlüssel verwendet, so ist die Verwendung einer guten Entropiequelle unausweichlich.

Lösung

Mit dem Erscheinen von RHEL 7 ist es möglich, die auf einem Virtualisierungshost vorhandene Entropie mittels VirtIO-RNG Device auch den Gästen zur Verfügung zu stellen:

The first new (aforementioned) security feature, guest entropy, allows KVM Virtualization to meet new cryptographic security requirements from both the United States and United Kingdom. The para-virtualized random number generator (virtio-rng) driver allows the host to feed entropy to the guest. This allows cryptographic applications running on the guest to be more effective by alleviating entropy starvation in guests.
RHEL-Blog – Refining the Virtual World with Red Hat Enterprise Linux 7 Beta

Im einfachsten Fall geschieht dies im Virtual Machine Manager, wo einfach nur das RNG-Device der jeweiligen Maschine hinzugefügt werden muss:

virt-manager add rng-device.png

Sollte dies nicht möglich sein (Bspw. bei CentOS, Ubuntu), so kann das RNG-Device auch über die xml-Konfiguration hinzugefügt werden (3):

[code language=”bash” gutter=”false”][root@host ~]# virsh edit <domain>[/code]

[code language=”xml” highlight=”5,6,7″]
<domain type=’kvm’>

<devices>

<rng model=’virtio’>
<backend model=’random’>/dev/random</backend>
</rng>
</devices>
</domain>
[/code]
Auf RHEL 7.0 und 6.x Gästen wird /dev/random vom rng-daemon (rngd) aus /dev/hwrng befüllt, hierfür ist es nötig diesen entsprechend zu konfigurieren:

[code language=”bash” highlight=”2″ title=”/etc/sysconfig/rngd”]
# Add extra options here
EXTRAOPTIONS="-r /dev/hwrng -o /dev/random"
[/code]

Dieser Eingriff ist ab RHEL 7.1 nicht mehr nötig:

No rngd Needed
Red Hat Enterprise Linux 7.0 and Red Hat Enterprise Linux 6 guests could make use of the entropy from hosts via the rngd userspace daemon. Setting up the daemon was a manual step for each Red Hat Enterprise Linux install.
With Red Hat Enterprise Linux 7.1 the manual step has been eliminated making the entire process seamless and automatic.
The use of rngd is now not required and the guest kernel itself fetches entropy from the host when the available entropy falls below a specific threshold. The guest kernel is then in a position to make random numbers available to applications as soon as they request them.
RHEL-Blog – Access to Random Numbers Made Easy

Das Problem mit der Lösung

Auf vielen Systemen ab RHEL 7.1 wird dies zu einem Problem durch den nicht mehr nötigen, jedoch weiterhin vorhandenen und aktiven Random Number Generator Daemon (rngd) führen.
In diesem gibt es aktuell einen Bug welcher dazu führt, dass hwrng für immer in den D-State (uninterruptible sleep) wechselt, sobald hwrng und rngd gleichzeitig versuchen aus der Entropiequelle zu lesen (5).
Auswirkungen zeigen sich auch in der Berechnung für den Loadaverage, dieser resultiert nun in einem Load von ~1.00 (bei einem CPU-Kern). Dieser Umstand hat uns auch auf dieses Problem aufmerksam gemacht.
Verhindert werden kann dies aktuell nur durch Deaktivieren des RNG-Daemon, bevor der Fehler auftritt.

[code language=”bash” gutter=”false”]
systemctl stop rngd.service
systemctl disable rngd.service
[/code]

Nach dem Auftreten des Fehlers hilft nur ein Neustart des Betriebssystems.

Quellen

  1. JDBC Zugriff auf Oracle-Datenbank scheitert mit I/O-Fehler: Connection reset
  2. RHEL-Blog – Refining the Virtual World with Red Hat Enterprise Linux 7 Beta
  3. http://libvirt.org/formatdomain.html#elementsRng
  4. RHEL-Blog – Access to Random Numbers Made Easy
  5. https://bugzilla.redhat.com/show_bug.cgi?id=1376397