加入收藏 | 设为首页 | 会员中心 | 我要投稿 源码网 (https://www.900php.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

Podman和用户名字空间:天作之合

发布时间:2019-08-27 13:27:17 所属栏目:Windows 来源:Daniel J Walsh
导读:副标题#e# 了解如何使用 Podman 在单独的用户空间运行容器。 Podman 是 libpod 库的一部分,使用户能够管理 pod、容器和容器镜像。在我的上一篇文章中,我写过将 Podman 作为一种更安全的运行容器的方式。在这里,我将解释如何使用 Podman 在单独的用户命名
副标题[/!--empirenews.page--]

Podman和用户名字空间:天作之合

了解如何使用 Podman 在单独的用户空间运行容器。

Podman 是 libpod 库的一部分,使用户能够管理 pod、容器和容器镜像。在我的上一篇文章中,我写过将 Podman 作为一种更安全的运行容器的方式。在这里,我将解释如何使用 Podman 在单独的用户命名空间中运行容器。

作为分离容器的一个很棒的功能,我一直在思考用户命名空间user namespace,它主要是由 Red Hat 的 Eric Biederman 开发的。用户命名空间允许你指定用于运行容器的用户标识符(UID)和组标识符(GID)映射。这意味着你可以在容器内以 UID 0 运行,在容器外以 UID 100000 运行。如果容器进程逃逸出了容器,内核会将它们视为以 UID 100000 运行。不仅如此,任何未映射到用户命名空间的 UID 所拥有的文件对象都将被视为 nobody 所拥有(UID 是 65534, 由 kernel.overflowuid 指定),并且不允许容器进程访问,除非该对象可由“其他人”访问(即世界可读/可写)。

如果你拥有一个权限为 660 的属主为“真实” root 的文件,而当用户命名空间中的容器进程尝试读取它时,会阻止它们访问它,并且会将该文件视为 nobody 所拥有。

示例

以下是它是如何工作的。首先,我在 root 拥有的系统中创建一个文件。

  1. $ sudo bash -c "echo Test > /tmp/test"
  2. $ sudo chmod 600 /tmp/test
  3. $ sudo ls -l /tmp/test
  4. -rw-------. 1 root root 5 Dec 17 16:40 /tmp/test

接下来,我将该文件卷挂载到一个使用用户命名空间映射 0:100000:5000 运行的容器中。

  1. $ sudo podman run -ti -v /tmp/test:/tmp/test:Z --uidmap 0:100000:5000 fedora sh
  2. # id
  3. uid=0(root) gid=0(root) groups=0(root)
  4. # ls -l /tmp/test
  5. -rw-rw----. 1 nobody nobody 8 Nov 30 12:40 /tmp/test
  6. # cat /tmp/test
  7. cat: /tmp/test: Permission denied

上面的 --uidmap 设置告诉 Podman 在容器内映射一系列的 5000 个 UID,从容器外的 UID 100000 开始的范围(100000-104999)映射到容器内 UID 0 开始的范围(0-4999)。在容器内部,如果我的进程以 UID 1 运行,则它在主机上为 100001。

由于实际的 UID=0 未映射到容器中,因此 root 拥有的任何文件都将被视为 nobody 所拥有。即使容器内的进程具有 CAP_DAC_OVERRIDE 能力,也无法覆盖此种保护。DAC_OVERRIDE 能力使得 root 的进程能够读/写系统上的任何文件,即使进程不是 root 用户拥有的,也不是全局可读或可写的。

用户命名空间的功能与宿主机上的功能不同。它们是命名空间的功能。这意味着我的容器的 root 只在容器内具有功能 —— 实际上只有该范围内的 UID 映射到内用户命名空间。如果容器进程逃逸出了容器,则它将没有任何非映射到用户命名空间的 UID 之外的功能,这包括 UID=0。即使进程可能以某种方式进入另一个容器,如果容器使用不同范围的 UID,它们也不具备这些功能。

请注意,SELinux 和其他技术还限制了容器进程破开容器时会发生的情况。

使用 podman top 来显示用户名字空间

我们在 podman top 中添加了一些功能,允许你检查容器内运行的进程的用户名,并标识它们在宿主机上的真实 UID。

让我们首先使用我们的 UID 映射运行一个 sleep 容器。

  1. $ sudo podman run --uidmap 0:100000:5000 -d fedora sleep 1000

现在运行 podman top

  1. $ sudo podman top --latest user huser
  2. USER   HUSER
  3. root   100000
  4.  
  5. $ ps -ef | grep sleep
  6. 100000   21821 21809  0 08:04 ?         00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000

注意 podman top 报告用户进程在容器内以 root 身份运行,但在宿主机(HUSER)上以 UID 100000 运行。此外,ps 命令确认 sleep 过程以 UID 100000 运行。

现在让我们运行第二个容器,但这次我们将选择一个单独的 UID 映射,从 200000 开始。

  1. $ sudo podman run --uidmap 0:200000:5000 -d fedora sleep 1000
  2. $ sudo podman top --latest user huser
  3. USER   HUSER
  4. root   200000
  5.  
  6. $ ps -ef | grep sleep
  7. 100000   21821 21809  0 08:04 ?         00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000
  8. 200000   23644 23632  1 08:08 ?         00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000

请注意,podman top 报告第二个容器在容器内以 root 身份运行,但在宿主机上是 UID=200000。

另请参阅 ps 命令,它显示两个 sleep 进程都在运行:一个为 100000,另一个为 200000。

这意味着在单独的用户命名空间内运行容器可以在进程之间进行传统的 UID 分离,而这从一开始就是 Linux/Unix 的标准安全工具。

用户名字空间的问题

(编辑:源码网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读