在 Docker 中如何处理对 /dev/(u)random 等的请求?

Tho*_*mas 5 linux random linux-kernel docker

对于文档的目的在我们的项目我要寻找以下信息:

我们正在使用 Docker 来部署各种需要 SSL/TLS 和其他东西的熵的应用程序。这些应用程序可能会使用 /dev/random、/dev/random、getrandom(2) 等。我想知道这些请求是如何在 Docker 容器中处理的,而不是一台运行所有服务的虚拟机(并访问一个共享熵来源)。

到目前为止,我已经(粗略地)研究了 libcontainer 和 runC。不幸的是,我没有找到我的问题的任何答案,尽管我有一种直觉,这些请求会传递给主机上的等效调用。

您能否引导我找到支持此声明的任何文档,还是我弄错了并且这些请求实际上以不同方式处理?

Kam*_*Cuk 6

docker 容器是“类固醇上的 chroot”。无论如何,所有 docker 容器和主机系统的内核都是相同的。所以所有的内核调用共享同一个内核。

所以我们可以在我们的主机上(在任何文件夹中,以 root 身份)执行以下操作:

mknod -m 444 urandom_host c 1 9
Run Code Online (Sandbox Code Playgroud)

在一些 linux chroot 中:

wget <alpine chroot> | tar -x <some folder>
chroot <some folder>
mknod -m 444 urandom_in_chroot c 1 9
Run Code Online (Sandbox Code Playgroud)

我们可以做

docker run -ti --rm alpine sh -l
mknod -m 444 urandom_in_docker c 1 9
Run Code Online (Sandbox Code Playgroud)

然后,任何程序对任何和 的所有调用open(2)和都将进入同一个内核,进入同一个内核模块,该模块绑定到具有主编号 1 和次编号 9 的特殊字符文件,这是根据此列表的 随机数生成器。read(2)urandom_in_dockerurandom_in_chrooturandom_hosturandom

至于虚拟机,内核是不同的(如果有的话)。因此,对任何块/特殊字符文件的所有调用都由不同的内核进行翻译(也可能使用不同的虚拟化架构和不同的指令集)。从主机来看,虚拟机作为单个进程可见(取决于实现),如果虚拟化系统/程序调用 /dev/urandom,则该进程可能/也可能不调用主机 /dev/urandom。在虚拟化中,任何事情都可能发生,这取决于特定的实现。

因此,docker 中对 /dev/urandom 的请求的处理方式与主机上的相同。至于内核中如何处理 urandom,也许是一个好的开始。

如果您需要熵,请务必使用并安装haveged。

  • 不。而且我认为您不会在任何文档中找到所有内容。我认为最好的办法是浏览 libcontainerd 源代码,看看它是否拦截以及如何拦截对 /dev/urandom 的调用。我说不是。检查 `strace -f dockerd` 然后调用 `strace -f docker run alpine` 在我的操作系统上产生以下行: `mknodat(AT_FDCWD, "/var/lib/docker/overlay2/f bla bla/merged/dev/urandom" , S_IFCHR|0666, makedev(1, 9)) = 0`。urandom 的创建方式与主机上的创建方式相同。 (2认同)