57

Running out of entropy in virtualized Linux systems seems to be a common problem (e.g. /dev/random Extremely Slow?, Getting linux to buffer /dev/random). Despite of using a hardware random number generator (HRNG) the use of a an entropy gathering daemon like HAVEGED is often suggested. However an entropy gathering daemon (EGD) cannot be run inside a Docker container, it must be provided by the host.

Using an EGD works fine for docker hosts based on linux distributions like Ubuntu, RHEL, etc. Getting such a daemon to work inside boot2docker - which is based on Tiny Core Linux (TCL) - seems to be another story. Although TCL has a extension mechanism, an extension for an entropy gathering daemon doesn't seem to be available.

So an EGD seems like a proper solution for running docker containers in a (production) hosting environment, but how to solve it for development/testing in boot2docker?

Since running an EGD in boot2docker seemed too difficult, I thought about simply using /dev/urandom instead of /dev/random. Using /dev/urandom is a litte less secure, but still fine for most applications which are not generating long-term cryptographic keys. At least it should be fine for development/testing inside boot2docker.

Community
  • 1
  • 1
mbonato
  • 1,379
  • 1
  • 10
  • 11
  • openssl user `urandom`. What are you doing that requires more? – akostadinov May 01 '15 at 21:32
  • 2
    Some Java cryptographic providers relay on /dev/random (e.g. for secure random number generation). – mbonato May 12 '15 at 07:34
  • I agree you can't always control that. In any case, here you've got some additional info about java `SecureRandom` vs `/dev/[u]random` - https://bugs.openjdk.java.net/browse/JDK-4705093 – akostadinov May 12 '15 at 13:42

6 Answers6

57

I just realized, that it is simple as mounting /dev/urandom from the host as /dev/random into the container:

$ docker run -v /dev/urandom:/dev/random ...

The result is as expected:

$ docker run --rm -it -v /dev/urandom:/dev/random ubuntu dd if=/dev/random of=/dev/null bs=1 count=1024
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.00223239 s, 459 kB/s

At least I know how to build my own boot2docker images now ;-)

mbonato
  • 1,379
  • 1
  • 10
  • 11
  • 3
    The impacts on security by using /dev/urandom instead of /dev/random on development machines should be quite limited. – mbonato May 12 '15 at 07:33
  • 14
    "Fact: /dev/urandom is the preferred source of cryptographic randomness on UNIX-like systems." http://www.2uo.de/myths-about-urandom/ – Alexander Ljungberg Mar 02 '16 at 21:20
  • 2
    What about cross-platform compatibility, i.e. for those poor souls running Windows? – Claudiu Mar 23 '16 at 22:30
  • 1
    I've tried a lot of the `rng-tools`/`haveged` suggestions and this is the only one that worked. Thanks! – Ben Watson Sep 08 '17 at 13:41
  • @Claudiu docker-toolbox for Windows still runs on linux, and docker for Windows 10+ runs on the linux subsystem (if I understood correctly), so that should still work? – Codebling Oct 25 '19 at 22:08
  • This is the same as running `ln -s /dev/urandom /dev/random` inside the container. /dev/random and /dev/urandom are always mapped to host. – Codebling Oct 25 '19 at 22:10
  • See [this answer](https://stackoverflow.com/a/30577161/675721) for more info – Codebling Oct 25 '19 at 22:13
15

The most elegant solution I've found is running Haveged in separate container:

docker pull harbur/haveged
docker run --privileged -d harbur/haveged

Check whether enough entropy available:

$ cat /proc/sys/kernel/random/entropy_avail
2066
Oleksandr Horobets
  • 1,147
  • 12
  • 25
5

Another option is to install the rng-tools package and map it to use the /dev/urandom

  yum install rng-tools
  rngd -r /dev/urandom 

With this I didn't need to map any volume in the docker container.

Alexandre L Telles
  • 3,025
  • 27
  • 26
3

Since I didn't like to modify my Docker containers for development/testing I tried to modify the boot2docker image. Luckily, the boot2docker image is build with Docker and can be easily extended. So I've set up my own Docker build boot2docker-urandom. It extends the standard boot2docker image with a udev rule found here.

Building your own boot2docker.iso image is simple as

$ docker run --rm mbonato/boot2docker-urandom > boot2docker.iso

To replace the standard boot2docker.iso that comes with boot2docker you need to:

$ boot2docker stop
$ boot2docker delete
$ mv boot2docker.iso ~/.boot2docker/
$ boot2docker init
$ boot2docker up

Limitations, from inside a Docker container /dev/random still blocks. Most likely, because the Docker containers do not use /dev/random of the host directly, but use the corresponding kernel device - which still blocks.

Jean-François Fabre
  • 126,787
  • 22
  • 103
  • 165
mbonato
  • 1,379
  • 1
  • 10
  • 11
2

Alpine Linux may be a better choice for a lightweight docker host. Alpine LXC & docker images are only 5mb (versus 27mb for boot2docker)

I use haveged on Alpine for LXC guests & on Debian for docker guests. It gives enough entropy to generate gpg / ssh keys & openssl certificates in containers. Alpine now has an official docker repo.

Alternatively build a haveged package for Tiny Core - there is a package build system available.

Stuart Cardall
  • 1,513
  • 17
  • 14
2

if you have this problem in a docker container created from a self-built image that runs a java app (e.g. created FROM tomcat:alpine) and don't have access to the host (e.g. on a managed k8s cluster), you can add the following command to your dockerfile to use non-blocking seeding of SecureRandom:

RUN sed -i.bak \
  -e "s/securerandom.source=file:\/dev\/random/securerandom.source=file:\/dev\/urandom/g" \
  -e "s/securerandom.strongAlgorithms=NativePRNGBlocking/securerandom.strongAlgorithms=NativePRNG/g" \
  $JAVA_HOME/lib/security/java.security

the two regex expressions replace file:/dev/random by file:/dev/urandom and NativePRNGBlocking by NativePRNG in the file $JAVA_HOME/lib/security/java.security which causes tomcat to startup reasonably fast on a vm. i haven't checked whether this works also on non alpine-based openjdk images, but if the sed command fails, just check the location of the file java.security inside the container and adapt the path accordingly.

note: in jdk11 the path has changed to $JAVA_HOME/conf/security/java.security

Remigius Stalder
  • 1,308
  • 2
  • 18
  • 23
  • 1
    too base this technique does not work with openjdk11 as the java.security file does not exist. – Archimedes Trajano Feb 06 '19 at 02:19
  • 1
    @ArchimedesTrajano: I use `openjdk` from https://adoptopenjdk.net (for my own use currently Java8, but for an experiment today Jdk11). After downloading and extracting Jdk11 from this site, I ran the command `$ grep -r securerandom *`, which gave me the path `conf/security/java.security` (relative path below the Jdk home directory). I hope this helps. – Remigius Stalder Feb 06 '19 at 14:34
  • 1
    I'm talking specifically about the `openjdk:11-slim` image from docker hub but hopefully it is in the same spot as you said – Archimedes Trajano Feb 06 '19 at 18:02
  • 1
    @ArchimedesTrajano: just in case: enter an `openjdk:11-slim`-container as follows: `$ docker run --rm -it openjdk:11-slim bash`, then `$ cd /` (just to make sure you are in the root directory), then `$ grep -r securerandom *` which gives here: `etc/java-11-openjdk/security/java.security` (the search takes a while, but you can stop it using Ctrl+C, then exit using Ctrl+D). this would most likely work also in other containers based on images that contains a jvm. – Remigius Stalder Feb 08 '19 at 09:15