在运行于boot2docker中的Docker容器中,/dev/random缺乏足够的熵支持。

61
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 using a hardware random number generator (HRNG), it is often suggested to use an entropy gathering daemon like HAVEGED. However, an EGD cannot be run inside a Docker container and must be provided by the host.
Using an EGD works fine for Docker hosts based on Linux distributions like Ubuntu, RHEL, etc. However, getting such a daemon to work inside boot2docker - which is based on Tiny Core Linux (TCL) - seems to be another story. Although TCL has an extension mechanism, an extension for an entropy gathering daemon doesn't seem to be available.

EGD似乎是在(生产)托管环境中运行docker容器的合适解决方案,但如何在boot2docker中进行开发/测试呢?

由于在boot2docker中运行EGD似乎太困难了,我考虑简单地使用/dev/urandom代替/dev/random。使用/dev/urandom不太安全,但对于大多数不生成长期加密密钥的应用程序来说仍然可以接受。至少在boot2docker内部进行开发/测试应该是可以的。


openssl使用urandom用户。你需要做什么才需要更多的呢? - akostadinov
2
一些Java加密提供程序依赖于/dev/random(例如用于安全随机数生成)。 - mbonato
我同意你不能总是控制这个。无论如何,这里有一些关于Java SecureRandom vs /dev/[u]random的额外信息 - https://bugs.openjdk.java.net/browse/JDK-4705093 - akostadinov
6个回答

60

我刚刚意识到,将主机上的 /dev/urandom 挂载为容器中的 /dev/random 就像是一件简单的事情:

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

结果如预期:

$ 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

至少我现在知道如何构建自己的boot2docker镜像了 ;-)


3
在开发机器上使用/dev/urandom而非/dev/random对安全性的影响应该是相当有限的。 - mbonato
16
事实:在类 UNIX 系统中,/dev/urandom 是首选的加密随机数源。http://www.2uo.de/myths-about-urandom/ - Alexander Ljungberg
2
跨平台兼容性怎么样,也就是那些运行Windows的可怜人呢? - Claudiu
1
我尝试了很多rng-tools/haveged的建议,但只有这个有效。谢谢! - Ben Watson
@Claudiu Docker Toolbox适用于Windows仍在Linux上运行,而Docker适用于Windows 10+在Linux子系统上运行(如果我理解正确的话),因此应该仍然可以工作? - Codebling
显示剩余2条评论

17

我发现最优雅的解决方案是在单独的容器中运行Haveged:

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

检查是否有足够的熵可用:

$ cat /proc/sys/kernel/random/entropy_avail
2066

6

另一个选项是安装rng-tools软件包并将其映射到使用/dev/urandom

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

有了这个,我就不需要在docker容器中映射任何卷。


3
这个信息告诉我:无法调整write_wakeup_threshold:只读文件系统 - Kagami Sascha Rosylight
3
在Docker宿主机上运行它,而不是在容器内部。 - Casey

3

由于我不喜欢修改我的Docker容器进行开发/测试,所以我尝试修改boot2docker镜像。幸运的是,boot2docker镜像是用Docker构建的,可以很容易地扩展。因此,我设置了自己的Docker构建boot2docker-urandom。它使用udev规则扩展了标准的boot2docker镜像,该规则在这里中找到。

构建自己的boot2docker.iso镜像很简单

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

要替换boot2docker中自带的标准boot2docker.iso,您需要执行以下操作:
$ boot2docker stop
$ boot2docker delete
$ mv boot2docker.iso ~/.boot2docker/
$ boot2docker init
$ boot2docker up

限制,在Docker容器内部,/dev/random仍然会阻塞。很可能是因为Docker容器不直接使用主机的/dev/random,而是使用相应的内核设备 - 该设备仍然会阻塞。


2

如果您在运行一个Java应用程序的自建镜像中创建的Docker容器(例如,使用FROM tomcat:alpine创建的)中遇到此问题,并且无法访问主机(例如,在托管的K8s集群上),则可以将以下命令添加到您的Dockerfile中,以使用非阻塞播种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

两个正则表达式将在文件$JAVA_HOME/lib/security/java.security中将file:/dev/random替换为file:/dev/urandom,并将NativePRNGBlocking替换为NativePRNG,这会使Tomcat在虚拟机上启动得更快。我没有检查这是否也适用于非基于Alpine的OpenJDK映像,但如果sed命令失败,请检查容器内java.security文件的位置并相应地调整路径。
注意:在JDK11中,路径已更改为$JAVA_HOME/conf/security/java.security

1
这种技术不适用于OpenJDK11,因为java.security文件不存在。 - Archimedes Trajano
1
@ArchimedesTrajano:我使用https://adoptopenjdk.net上的`openjdk`(目前是Java8,但今天为了进行实验而使用了Jdk11)。 从该站点下载并提取Jdk11后,我运行了命令$ grep -r securerandom *,这给我提供了路径conf/security/java.security(Jdk主目录下的相对路径)。希望这可以帮到你。 - Remigius Stalder
1
我特别指的是来自Docker Hub的openjdk:11-slim镜像,但希望它与您所说的位置相同。 - Archimedes Trajano
1
@ArchimedesTrajano: 以防万一:要进入一个 openjdk:11-slim 容器,请按以下方式操作: $ docker run --rm -it openjdk:11-slim bash,然后 $ cd /(只是为了确保您在根目录下),然后 $ grep -r securerandom *,这将会找到 etc/java-11-openjdk/security/java.security ( 搜索需要一段时间,但可以使用 Ctrl+C 停止搜索,然后使用 Ctrl+D 退出)。 这种方法很可能也适用于基于包含jvm的镜像的其他容器。 - Remigius Stalder

2

Alpine Linux 可能是一个更好的轻量级 docker 主机选择。与 boot2docker 的 27mb 相比,Alpine LXC & docker 镜像仅有5mb。

我在 Alpine 上使用 haveged 作为 LXC 客户端和在 Debian 上作为 docker 客户端。它提供足够的熵来生成容器中的 gpg / ssh 密钥和 openssl 证书。现在 Alpine 有一个官方的 docker 库。

或者为 Tiny Core 构建一个 haveged 软件包 - 有一个可用的软件包构建系统


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接