增强型容器隔离
增强型容器隔离 (ECI) 可防止恶意容器破坏 Docker Desktop 或宿主系统。它自动应用高级安全技术,同时保持开发人员的生产力和工作流的完全兼容性。
ECI 加强了容器隔离,并锁定管理员创建的安全配置,例如注册表访问管理策略和设置管理控制。
注意ECI 与其他 Docker 安全功能协同工作,例如简化的 Linux 功能、seccomp 和 AppArmor。
谁应该使用增强型容器隔离?
增强型容器隔离专为以下用户设计:
- 希望防止基于容器的攻击并减少开发环境中安全漏洞的组织
- 需要更强容器隔离而又不影响开发人员工作流的安全团队
- 在运行不受信任或第三方容器镜像时需要额外保护的企业
增强型容器隔离的工作原理
Docker 使用 Sysbox 容器运行时实现 ECI,它是标准 OCI runc 运行时的安全增强型分支。启用 ECI 后,通过 docker run 或 docker create 创建的容器会自动使用 Sysbox 而不是 runc,而无需更改开发人员工作流。
即使是使用 --privileged 标志的容器也能通过增强型容器隔离安全运行,从而防止它们突破 Docker Desktop 虚拟机或其他容器。
注意启用 ECI 后,Docker CLI
--runtime标志将被忽略。Docker 的默认运行时仍为 runc,但所有用户容器都会隐式地使用 Sysbox 启动。
主要安全特性
Linux 用户命名空间隔离
借助增强型容器隔离,所有容器都利用 Linux 用户命名空间来获得更强的隔离。容器根用户映射到 Docker Desktop VM 中的非特权用户。
$ docker run -it --rm --name=first alpine
/ # cat /proc/self/uid_map
0 100000 65536
此输出显示容器根 (0) 映射到 VM 中的非特权用户 100000,用户 ID 范围为 64K。每个容器都获得独占映射。
$ docker run -it --rm --name=second alpine
/ # cat /proc/self/uid_map
0 165536 65536
如果没有增强型容器隔离,容器将以真正的根用户身份运行。
$ docker run -it --rm alpine
/ # cat /proc/self/uid_map
0 0 4294967295
通过使用 Linux 用户命名空间,ECI 确保容器进程绝不会在 Linux VM 中使用有效的用户 ID 运行,从而将其功能限制在容器内的资源。
安全特权容器
特权容器(`docker run --privileged`)通常会带来重大的安全风险,因为它们提供对 Linux 内核的无限制访问。如果没有 ECI,特权容器可以:
- 以拥有所有功能的真正根用户身份运行
- 绕过 seccomp 和 AppArmor 限制
- 访问所有硬件设备
- 修改全局内核设置
保护开发者环境的组织面临特权容器的挑战,因为它们可以控制 Docker Desktop VM 并更改注册表访问管理和网络代理等安全设置。
增强型容器隔离通过确保特权容器只能访问其容器边界内的资源来改造特权容器。例如,特权容器无法访问 Docker Desktop 的网络配置。
$ docker run --privileged djs55/bpftool map show
Error: can't get next map: Operation not permitted
如果没有 ECI,特权容器可以轻松访问和修改这些设置。
$ 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
Docker-in-Docker 和 Kubernetes-in-Docker 等高级容器工作负载仍可与 ECI 配合使用,但运行起来更安全。
注意ECI 不会阻止用户运行特权容器,但会通过限制其访问来确保它们的安全。修改全局内核设置(加载内核模块、更改 Berkeley Packet Filter 设置)的特权工作负载会收到“权限被拒绝”错误。
命名空间隔离强制执行
增强型容器隔离可防止容器与 Docker Desktop VM 共享 Linux 命名空间,从而保持隔离边界。
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.
用户命名空间覆盖被忽略
$ docker run -it --rm --userns=host alpine
/ # cat /proc/self/uid_map
0 100000 65536
使用 --network-host 的 Docker 构建操作和 Docker buildx 权限(network.host、security.insecure)也被阻止。
受保护的绑定挂载
增强型容器隔离支持标准文件共享,同时防止访问敏感的 VM 目录。
主机目录挂载继续有效
$ docker run -it --rm -v $HOME:/mnt alpine
/ # ls /mnt
# Successfully lists home directory contents
VM 配置挂载被阻止
$ 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 配置、注册表访问管理设置、代理配置以及其他与安全相关的 VM 文件。
注意默认情况下,ECI 会阻止绑定挂载 Docker Engine 套接字(/var/run/docker.sock),因为这会授予容器对 Docker Engine 的控制权。管理员可以为受信任的容器镜像创建例外。
高级系统调用保护
增强型容器隔离拦截敏感系统调用,防止容器恶意使用合法功能。
$ 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?)
即使拥有 CAP_SYS_ADMIN 能力,容器也无法将只读绑定挂载更改为读写,从而确保它们无法突破容器边界。
容器仍可在其文件系统内创建内部挂载
/ # 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
ECI 通过仅拦截控制路径系统调用(很少使用)来高效执行系统调用过滤,同时不影响数据路径系统调用,从而保持容器性能。
自动文件系统用户 ID 映射
增强型容器隔离通过自动文件系统映射解决了具有不同用户 ID 范围的容器之间的文件共享挑战。
每个容器都获得独占的用户 ID 映射,但 Sysbox 通过 Linux 内核 ID 映射挂载(2021 年添加)或替代的 shiftsfs 模块执行文件系统用户 ID 重新映射。这会将容器实际用户 ID 的文件系统访问映射到标准范围,从而实现:
- 跨不同用户 ID 范围的容器共享卷
- 无论容器用户 ID 映射如何,都保持一致的文件所有权
- 无需用户干预即可透明地访问文件
通过文件系统模拟隐藏信息
ECI 模拟容器内 `/proc` 和 `/sys` 文件系统的部分内容,以隐藏敏感主机信息并提供每个容器的内核资源视图。
$ docker run -it --rm alpine
/ # cat /proc/uptime
5.86 5.86
这显示的是容器的运行时间,而不是 Docker Desktop VM 的运行时间,从而防止系统信息泄露到容器中。
Linux 内核未命名空间化的几个 `/proc/sys` 资源会按容器进行模拟,Sysbox 在编程内核设置时会协调这些值。这使得通常需要特权访问的容器工作负载能够安全运行。
性能和兼容性
增强型容器隔离保持优化的性能和完全兼容性。
- 无性能影响:系统调用过滤仅针对控制路径调用,不影响数据路径操作。
- 完全工作流兼容性:现有开发流程、工具和容器镜像无需更改即可工作。
- 高级工作负载支持:Docker-in-Docker、Kubernetes-in-Docker 和其他复杂场景可安全工作。
- 自动管理:用户 ID 映射、文件系统访问和安全策略均自动处理。
- 标准镜像支持:无需特殊容器镜像或修改。
重要ECI 保护因 Docker Desktop 版本而异,目前尚未保护扩展容器。Docker 构建和 Docker Desktop 中的 Kubernetes 的保护级别因版本而异。有关详细信息,请参阅增强型容器隔离限制。