博客

一份实用的多租户托管 Docker 隔离安全清单

使用这份实用清单保护您的多租户 Docker 托管,涵盖非 root 用户、能力、seccomp、用户命名空间、资源限制和只读文件系统。

摘要

多租户 Docker 托管需要强大的隔离性以防止容器逃逸。本文提供了一份实用的安全清单,涵盖六个关键领域:以非 root 用户运行、丢弃能力、应用 seccomp 配置文件、启用用户命名空间重映射、设置资源限制以及使用只读根文件系统。每一步都包含一个针对 Docker Compose 的具体配置示例。您还将了解常见陷阱,例如用户命名空间的内核兼容性问题以及应用 seccomp 时的性能权衡。遵循此清单,您可以显著减少攻击面,而不会增加不必要的复杂性。本文最后给出了生产多租户环境的推荐基线配置。

如果您运行的是多租户 Docker 环境,容器逃逸攻击的阴影会让您夜不能寐。一次内核漏洞利用就可能突破容器,让攻击者无限制地访问主机和所有其他租户的数据。虽然 Docker 提供了强大的隔离原语——命名空间、cgroups 和能力——但配置不当仍会留下漏洞。本文提供了一个您可以立即应用的分步安全清单。每一步都包含一个可运行的 Docker Compose 代码片段和关键注意事项。到最后,您将获得一个兼顾安全性和性能的强化基线。

1. 以非 Root 用户运行容器

容器默认以 root 用户身份在容器内运行。如果攻击者在容器中获取了 root 权限,他们就占据了逃逸的先机。始终在 Dockerfile 中定义一个非 root 用户。

FROM alpine:3.18
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

在 Compose 中,您也可以直接设置用户:

services:
  app:
    image: myapp
    user: "1000:1000"

注意: 某些应用程序需要 root 权限进行合法操作(例如绑定到 1024 以下的端口)。请使用 CAP_NET_BIND_SERVICE,而不是将整个容器以 root 身份运行。有关隔离基础的更深入探讨,请参阅我们的指南:在 Docker 中实现真正的多租户隔离

2. 丢弃所有能力,仅添加所需的能力

Linux 能力为容器提供了细粒度的权限。默认情况下,Docker 授予一组能力。丢弃所有能力,仅授予所需的能力。

services:
  app:
    image: myapp
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE  # 如果需要

注意: 诸如 SYS_ADMINNET_RAW 之类的能力很少需要。审计您的应用程序以确定最小集合。丢弃所有能力可以阻止许多逃逸途径。

3. 应用 Seccomp 配置文件

Seccomp(安全计算模式)过滤容器可用的系统调用。Docker 附带了默认的 seccomp 配置文件,该文件会阻止某些危险系统调用(如带有某些标志的 clone)。您可以进一步自定义它。

services:
  app:
    image: myapp
    security_opt:
      - seccomp=/path/to/custom-profile.json

一个强化的配置文件可能会阻止 unshareptracemount。从 Docker 的默认配置文件开始,然后进一步限制。注意: 过于严格的配置文件可能会破坏应用程序。在预发布环境中彻底测试。有关容器逃逸防御的更多信息,请阅读防御容器逃逸

4. 启用用户命名空间重映射

用户命名空间将容器的 root 用户映射到主机上的非特权用户。这意味着即使攻击者在容器内获得了 root 权限,他们在主机上也没有特殊权限。

通过编辑 /etc/docker/daemon.json 在 Docker 守护进程中启用它:

{
  "userns-remap": "default"
}

然后重启 Docker。注意: 用户命名空间重映射有两个缺点:如果配置不当,它会破坏卷挂载(文件由重映射的用户所有),并且与某些存储驱动程序(如旧内核上的 overlay2)不兼容。请彻底测试。

5. 使用 Cgroups 设置资源限制

资源限制可防止受损容器对主机发起拒绝服务攻击。使用 cgroups 限制 CPU、内存和磁盘 I/O。

services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

对于 Docker Compose v3,请使用 deploy 部分(适用于 swarm 或 compose v2)。对于普通 Docker,使用 --memory--cpus注意: 将限制设置得过低可能会导致 OOM 终止。监控使用情况并进行相应调整。

6. 使用只读根文件系统

只读根文件系统可防止攻击者在容器内写入恶意二进制文件或修改配置文件。

services:
  app:
    image: myapp
    read_only: true
    tmpfs:
      - /tmp:noexec,nosuid,size=64m

在需要写入访问的目录(如 /tmp)上挂载 tmpfs。这将强制所有可写数据为临时数据。注意: 某些应用程序需要持久化存储;请使用命名卷来满足需求。

常见陷阱

  • 内核兼容性: 用户命名空间重映射和一些 seccomp 规则需要较新的 Linux 内核(4.14+)。检查您的内核版本。
  • 性能影响: Seccomp 和用户命名空间会带来少量开销,但对于大多数工作负载来说可以忽略不计。请对您的特定应用程序进行基准测试。
  • 复杂性: 同时添加所有六项措施可能会破坏功能。逐一应用,每次更改后都进行测试。

有关编排模式的更广泛了解,请参阅我们的指南:设计多租户 Docker 架构

结论

一个安全的多租户 Docker 主机不需要奇特的工具——只需正确使用 Docker 的内置功能即可。从非 root 用户开始,丢弃所有能力,应用 seccomp 配置文件,启用用户命名空间重映射,设置资源限制,并使用只读文件系统。这份清单构成了一个强大的基线,可以阻止最常见的逃逸技术。实施后,运行 docker-bench-security 等安全工具来验证您的配置。请记住:安全是一个过程,而不是一个产品。随着新的内核漏洞出现,请重新审视您的设置。对于展示您托管服务的自动登陆页面,请使用 Pagenza 在几分钟内让您的网站上线。

Sources (5)