主要特点和优势
所有容器上的 Linux 用户命名空间
借助增强型容器隔离,所有用户容器都可以利用 Linux 用户命名空间进行额外隔离。这意味着容器中的 root 用户映射到非特权 用户。
例如:
$ docker run -it --rm --name=first alpine
/ # cat /proc/self/uid_map
0 100000 65536
输出是 Linux 用户命名空间的签名。它
表示容器中的 root 用户 (0) 映射到非特权用户
100000 的 Docker Desktop Linux VM 中,并且映射将持续扩展
64K 用户 ID 的范围。这同样适用于组 ID。0 100000 65536
每个容器都有一个由 Sysbox 管理的独占映射范围。为 例如,如果启动了第二个容器,则映射范围不同:
$ docker run -it --rm --name=second alpine
/ # cat /proc/self/uid_map
0 165536 65536
相比之下,如果没有增强容器隔离,容器的 root 用户是 实际上,主机上的 root(又名 “true root”),这适用于所有容器:
$ docker run -it --rm alpine
/ # cat /proc/self/uid_map
0 0 4294967295
通过使用 Linux 用户命名空间,增强的容器隔离 确保容器进程永远不会在 Linux 中以用户 ID 0 (true root) 运行 事实上,它们从不在 Linux VM 中使用任何有效的用户 ID 运行。因此,他们的 Linux 功能仅限于容器中的资源, 与常规容器相比,隔离率显著提高 容器到主机和跨容器隔离。
特权容器也受到保护
特权容器不安全,因为它们
为容器提供对 Linux 内核的完全访问权限。也就是说,容器运行
作为 true root,启用所有功能,seccomp 和 AppArmor 限制
被禁用,则所有硬件设备都会公开。docker run --privileged ...
旨在保护开发人员计算机上的 Docker Desktop 的组织面临着特权容器的挑战。这些容器(无论是运行良性工作负载还是恶意工作负载)都可以在 Docker Desktop VM 中获得对 Linux 内核的控制权,从而可能更改与安全相关的设置,例如注册表 访问管理和网络代理。
使用增强型容器隔离后,特权容器无法再执行 这。Linux 用户命名空间和其他安全技术的组合 使用 Sysbox 确保特权容器内的进程只能 访问分配给容器的资源。
注意
增强的容器隔离不会阻止用户启动特权 容器,而是通过确保它们只能 修改与容器关联的资源。特权工作负载 修改全局内核设置,例如加载内核模块或更改 Berkeley 数据包过滤器 (BPF) 设置将无法正常工作,因为它们将获得“权限 denied“错误。
例如,增强型容器隔离可确保特权容器无法 访问通过 BPF 配置的 Linux VM 中的 Docker Desktop 网络设置:
$ docker run --privileged djs55/bpftool map show
Error: can't get next map: Operation not permitted
相比之下,如果没有增强型容器隔离,特权容器 可以轻松做到这一点:
$ docker run --privileged djs55/bpftool map show
17: ringbuf name blocked_packets flags 0x0
key 0B value 0B max_entries 16777216 memlock 0B
18: hash name allowed_map flags 0x0
key 4B value 4B max_entries 10000 memlock 81920B
20: lpm_trie name allowed_trie flags 0x1
key 8B value 8B max_entries 1024 memlock 16384B
请注意,某些高级容器工作负载需要特权容器,以便 示例 Docker-in-Docker、Kubernetes-in-Docker 等。使用增强型容器 隔离:您仍然可以运行此类工作负载,但执行操作比 以前。
容器无法与 Linux VM 共享命名空间
启用增强型容器隔离后,容器无法共享 Linux 命名空间,主机(例如 PID、网络、UTS 等)本质上是 打破孤立。
例如,共享 PID 命名空间会失败:
$ docker run -it --rm --pid=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown.
同样,共享网络命名空间也会失败:
$ docker run -it --rm --network=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown.
此外,该标志用于在
container 被忽略:--userns=host
$ docker run -it --rm --userns=host alpine
/ # cat /proc/self/uid_map
0 100000 65536
最后,Docker build 和 Docker buildx 权利
(, ) 不允许。需要这些的构建
无法正常工作。--network=host
network.host
security.insecure
绑定挂载限制
启用增强型容器隔离后,Docker Desktop 用户可以继续 按照 Settings > Resources > File sharing(文件共享)配置将挂载主机目录绑定到容器中,但不再允许它们绑定挂载 将任意 Linux VM 目录添加到容器中。
这可以防止容器修改 Docker 中的敏感文件 桌面 Linux VM,可以保存注册表访问配置的文件 管理、代理、Docker Engine 配置等。
例如,Docker Engine 配置文件的以下 bind 挂载
(在 Linux VM 中)放入容器中受到限制
,因此失败:/etc/docker/daemon.json
$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown
相比之下,在没有增强容器隔离的情况下,此挂载会正常工作,并提供 容器对 Docker Engine 配置的完全读写访问权限。
当然,主机文件的 bind 挂载将继续照常工作。例如
假设用户将 Docker Desktop 配置为文件共享她的目录,
她可以将 mount 它绑定到容器中:$HOME
$ docker run -it --rm -v $HOME:/mnt alpine
/ #
注意
默认情况下,增强型容器隔离不允许绑定挂载 Docker Engine 套接字 () 添加到容器中,因为这样做实质上会授予 Docker Engine 的容器控制,从而打破容器隔离。然而 由于某些合法用例需要这样做,因此可以放宽 此限制适用于受信任的容器镜像。请参阅 Docker 套接字挂载权限。
/var/run/docker.sock
审查敏感的系统调用
增强型容器隔离的另一个功能是,它可以拦截和审查
容器内高度敏感的系统调用很少,例如 和 。这可确保能够执行这些操作的进程
系统调用不能使用它们来破坏容器。mount
umount
例如,具有 (执行系统调用所需的) 的容器无法使用该功能来更改只读绑定挂载
放入读写挂载中:CAP_SYS_ADMIN
mount
$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine
/ # mount -o remount,rw /mnt /mnt
mount: permission denied (are you root?)
由于该目录已作为
read-only,则无法从容器内部更改为 read-write,即使容器进程能够这样做。这
确保容器进程无法使用 、 或 来破坏容器的
root 文件系统。$HOME
/mnt
mount
umount
但请注意,在前面的示例中,容器仍然可以创建 mounts ,并根据需要以只读或读写方式挂载它们。那些 允许挂载,因为它们发生在容器内,因此不会 破坏它的根文件系统:
/ # mkdir /root/tmpfs
/ # mount -t tmpfs tmpfs /root/tmpfs
/ # mount -o remount,ro /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs tmpfs tmpfs ro,relatime,uid=100000,gid=100000
/ # mount -o remount,rw /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs tmpfs tmpfs rw,relatime,uid=100000,gid=100000
此功能与用户命名空间一起确保即使容器 进程具有所有 Linux 功能,它们不能用于破坏容器。
最后,增强型容器隔离以这种方式执行系统调用审查 它不会影响容器的性能,在绝大多数 例。它拦截大多数 容器工作负载,但数据路径系统调用不会被拦截。
文件系统 user-ID 映射
如前所述,ECI 支持 Linux user 命名空间。这可确保容器的 User-ID 范围 (0->64K) 映射到 Docker 中“真实”用户 ID 的非特权范围 桌面 Linux VM(例如 100000->165535)。
此外,每个容器在 Linux 中都会获得一个专有的真实用户 ID 范围 VM(例如,容器 0 可以映射到 100000->165535,容器 2 可以映射到 165536->231071、容器 3 到 231072->296607,依此类推)。这同样适用于 group-ID 的 ID 中。此外,如果容器停止并重新启动,则不会 保证它将收到与以前相同的映射。这是设计使然, 进一步提高了安全性。
但是,当将 Docker 卷挂载到 器皿。写入此类卷的文件具有真正的 user/group-ID 的 ID,因此无法通过容器的 start/stop/restart,或者由于实际 每个容器的 user-ID/group-ID。
为了解决这个问题,Sysbox 通过 Linux 使用“文件系统用户 ID 重新映射”
内核的 ID-mapped mounts 功能(2021 年添加)或替代模块。这些技术将文件系统访问从容器的
真实用户 ID(例如,范围 100000->165535)到 Docker 内部的范围 (0->65535)
桌面的 Linux VM。这样,现在可以挂载或共享卷
容器,即使每个容器都使用 User-ID 的独占范围。用户
无需担心容器的真实 User-ID。shiftsfs
尽管文件系统 user-ID 重新映射可能会导致容器访问 将 Linux VM 文件挂载到真实用户 ID 为 0 的容器中,受限挂载功能可确保 敏感的 Linux VM 文件无法装载到容器中。
Procfs & sysfs 仿真
增强型容器隔离的另一个功能是,在每个容器内,
和 文件系统被部分模拟。这
有多种用途,例如将敏感的主机信息隐藏在
容器和命名空间尚未由
Linux 内核本身。/proc
/sys
举个简单的例子,启用增强型容器隔离后,该文件显示容器本身的正常运行时间,而不是
Docker 桌面 Linux VM:/proc/uptime
$ docker run -it --rm alpine
/ # cat /proc/uptime
5.86 5.86
相比之下,如果没有增强型容器隔离,您会看到 Docker 桌面 Linux VM。虽然这是一个微不足道的例子,但它展示了如何 增强的容器隔离旨在防止 Linux VM 的配置和 信息泄漏到容器中,从而使其更难 破坏 VM。
此外,其下的其他几个资源不是由
Linux 内核也在容器内部进行模拟。每个容器
看到每个此类资源的单独视图,并且 Sysbox 会协调值
在对相应的 Linux 内核设置进行编程时。/proc/sys
这样做的好处是支持容器工作负载,否则 需要真正具有特权的容器才能访问此类非命名空间内核 在启用增强型容器隔离的情况下运行的资源,从而提高 安全。