Docker Engine 安全性

在审查 Docker 安全性时,需要考虑四个主要方面:

  • 内核的内在安全性及其对 命名空间和 cgroups
  • Docker 守护程序本身的攻击面
  • 容器配置文件中的漏洞,默认情况下, 或由用户自定义时。
  • 内核的 “强化” 安全功能及其方式 与容器交互。

内核命名空间

Docker 容器与 LXC 容器非常相似,它们具有 类似的安全功能。当您使用 启动容器时,Docker 会在后台创建一组命名空间和控制 组。docker run

命名空间提供了第一种也是最直接的 隔离。在容器中运行的进程无法看到,甚至无法看到 影响较小,在另一个容器或主机中运行的进程 系统。

每个容器还拥有自己的网络堆栈,这意味着 容器没有获得对套接字或接口的特权访问权限 另一个容器。当然,如果设置了主机系统 因此,容器可以通过其 各自的网络接口 — 就像它们可以与之交互一样 外部主机。当您为容器指定公有端口或使用链接时,容器之间允许 IP 流量。他们可以互相 ping , 发送/接收 UDP 数据包,并建立 TCP 连接,但那可以是 必要时限制。从网络架构的角度来看,所有 给定 Docker 主机上的容器位于桥接接口上。这 意味着它们就像通过 通用以太网交换机;不多也不少。

提供内核命名空间和私有代码的代码成熟度如何 联网?内核命名空间是在内核版本之间引入的 2.6.15 和 2.6.26. 这意味着,自 2008 年 7 月(2.6.26 版本发布之日)以来 ),命名空间代码已在大型 生产系统的数量。还有更多:设计和 命名空间代码的灵感甚至更古老。命名空间是 实际上是为了重新实现 OpenVZ 的功能,使它们能够 合并到主流内核中。OpenVZ 最初发布 在 2005 年,所以设计和实现都相当成熟。

控制组

控制组是 Linux 容器的另一个关键组件。他们 实施资源核算和限制。他们提供了许多 有用的指标,但它们也有助于确保每个容器获得 内存、CPU、磁盘 I/O 的公平份额;更重要的是,一个 单个容器无法通过耗尽其中一个容器来使系统关闭 资源。

因此,虽然它们在阻止一个容器 访问或影响另一个容器的数据和进程,则 对于抵御某些拒绝服务攻击至关重要。他们是 在多租户平台(如 Public 和 私有 PaaS,以保证一致的正常运行时间(和性能) 当某些应用程序开始行为异常时。

Control Group 也已经存在了一段时间:代码是 始于 2006 年,最初合并到内核 2.6.24 中。

Docker 守护程序攻击面

使用 Docker 运行容器(和应用程序)意味着运行 Docker 守护程序。除非您选择加入,否则此守护进程需要权限 设置为 Rootless 模式,因此您应该注意 一些重要的细节。root

首先,只允许受信任的用户控制您的 Docker 守护程序。这是一些强大的 Docker 的直接结果 特征。具体来说,Docker 允许您在 Docker 主机和来宾容器;它允许您这样做 而不限制容器的访问权限。这意味着您 可以启动一个容器,其中 directory 是目录 在您的主机上;容器可以更改您的主机文件系统 没有任何限制。这类似于虚拟化系统 允许文件系统资源共享。没有什么可以阻止您共享您的 root 文件系统(甚至是根块设备)与虚拟机一起使用。/host/

这具有很强的安全隐患:例如,如果您检测 Docker 从 Web 服务器通过 API 配置容器,您应该 参数检查比平时更加小心,以确保 恶意用户无法传递构建的参数,导致 Docker 创建 任意容器。

因此,REST API 端点(由 Docker CLI 用于 communicate with the Docker daemon)在 Docker 0.5.2 中发生了变化,现在 使用 Unix 套接字而不是绑定在 127.0.0.1 上的 TCP 套接字( 如果您碰巧运行 Docker 直接位于本地计算机上,在 VM 之外)。然后,您可以 使用传统的 Unix 权限检查来限制对控件的访问 插座。

如果您明确决定这样做,还可以通过 HTTP 公开 REST API。 但是,如果您这样做,请注意上述安全隐患。 请注意,即使您有防火墙来限制对 REST API 的访问 endpoint 时,该 endpoint 仍可访问 ,并且很容易导致权限提升。 因此,必须使用 HTTPS 和证书保护 API 终端节点。 不允许在没有 TLS 的情况下通过 HTTP 公开守护程序 API, 并且此类配置会导致守护程序在启动时提前失败,请参阅未经身份验证的 TCP 连接。 此外,建议确保只能从受信任的 network 或 VPN。

如果您更喜欢 SSH 而不是 TLS,也可以使用 OR。DOCKER_HOST=ssh://USER@HOSTssh -L /path/to/docker.sock:/var/run/docker.sock

守护程序还可能容易受到其他输入(如 image) 使用 从磁盘加载,或使用 从网络加载。从 Docker 1.3.2 开始,镜像现在被提取到 chroot 的 subprocess 的 API 中,这是更广泛努力的第一步 走向特权分离。从 Docker 1.10.0 开始,所有镜像都被存储并 通过其内容的加密校验和访问,从而限制 攻击者可能导致与现有镜像发生冲突的可能性。docker loaddocker pull

最后,如果您在服务器上运行 Docker,建议运行 在服务器上独占 Docker,并在 由 Docker 控制的容器。当然,保留你的 最喜欢的管理工具(可能至少是 SSH 服务器),以及 现有的监控/监督流程,例如 NRPE 和 collectd。

Linux 内核功能

默认情况下,Docker 使用一组受限的 能力。那是什么意思?

功能将二进制 “root/non-root” 二分法转换为 细粒度的访问控制系统。进程(如 Web 服务器) 只需要绑定在 1024 以下的端口上,不需要以 root 身份运行:它们 可以改为授予该能力。然后 是许多其他功能,适用于根 通常需要 privileges。这对容器安全来说意义重大。net_bind_service

典型的服务器以 的形式运行多个进程,包括 SSH 守护进程、守护进程、日志守护进程、内核模块、网络配置工具、 和更多。容器是不同的,因为几乎所有这些任务都是 由容器周围的基础设施处理:rootcron

  • SSH 访问通常由在 Docker 主机
  • cron,必要时,应以用户身份运行 进程,专用且为需要其 Scheduling 服务,而不是作为平台范围的工具
  • 日志管理通常也交给 Docker 或 第三方服务,如 Loggly 或 Splunk
  • 硬件管理无关紧要,这意味着您永远不需要 run 或等效守护进程 器皿udevd
  • 网络管理发生在容器之外,强制 尽可能地分离关注点,这意味着容器 永远不需要执行 、 、 或 ip 命令(除非容器 经过专门设计,其行为类似于路由器或防火墙, 课程)ifconfigroute

这意味着在大多数情况下,容器不需要 “真正的” 根 权限*因此,容器可以在减少的 能力集;这意味着容器中的 “root” 要少得多 权限。例如,可以:

  • 拒绝所有 “mount” 操作
  • 拒绝访问原始套接字(以防止数据包欺骗)
  • 拒绝访问某些文件系统操作,例如创建新设备 节点、更改文件所有者或更改属性(包括 immutable 标志)
  • 拒绝模块加载

这意味着,即使入侵者设法在 容器,则造成严重损害或升级要困难得多 添加到主机。

这不会影响常规 Web 应用程序,但会将攻击向量减少 恶意用户相当多。默认情况下 Docker 丢弃除 需要, 允许列表而不是拒绝列表方法。您可以查看 Linux 中的可用功能 manpages

运行 Docker 容器的一个主要风险是默认设置 的功能和挂载数可能提供不完整 隔离,可独立使用,也可与 内核漏洞。

Docker 支持添加和删除功能,允许使用 的非默认配置文件。这可能会使 Docker 更安全,方法是 功能删除,或者通过添加功能而降低安全性。 用户的最佳实践是删除除 那些是他们的流程明确需要的。

Docker Content Trust 签名验证

Docker Engine 可以配置为仅运行已签名的镜像。Docker 内容 信任签名验证功能直接内置于二进制文件中。
这是在 Dockerd 配置文件中配置的。
dockerd

要启用此功能,可以在 中配置 trustpinning,从而 只能提取和运行使用用户指定的根密钥签名的存储库。daemon.json

此功能为管理员提供了比以前 用于实施和执行镜像签名验证的 CLI。

有关配置 Docker 内容信任签名验证的更多信息,请转到 Docker 中的内容信任

其他内核安全功能

功能只是 提供的众多安全功能之一 现代 Linux 内核。还可以利用现有的 TOMOYO、AppArmor、SELinux、GRSEC 等知名系统与 Docker。

虽然 Docker 目前只启用功能,但它不会干扰 与其他系统。这意味着有许多不同的方法 强化 Docker 主机。以下是一些示例。

  • 您可以使用 GRSEC 和 PAX 运行内核。这增加了许多安全性 在编译时和运行时进行检查;它也击败了许多人 漏洞利用,这要归功于地址随机化等技术。它没有 需要特定于 Docker 的配置,因为这些安全功能 在系统范围内应用,独立于容器。
  • 如果您的分配附带了 Docker 容器,您可以开箱即用。例如,我们 提供与 AppArmor 配合使用的模板,Red Hat 附带 SELinux 策略。这些模板提供了一个额外的安全网(甚至 尽管它与 capabilities 有很大的重叠)。
  • 您可以使用自己喜欢的访问控制来定义自己的策略 机制。

就像您可以使用第三方工具来增强 Docker 容器一样,包括 特殊的网络拓扑或共享文件系统,存在强化 Docker 的工具 容器,而无需修改 Docker 本身。

从 Docker 1.10 开始,docker 直接支持用户命名空间 守护 进程。此功能允许映射容器中的 root 用户 分配给容器外部的非 UID-0 用户,这有助于缓解 容器破裂的风险。此功能可用但未启用 默认情况下。

有关此功能的更多信息,请参阅命令行参考中的 daemon 命令。 有关在 Docker 中实现用户命名空间的其他信息 可以在这篇博文中找到。

结论

默认情况下,Docker 容器非常安全;特别是如果你 在容器内以非特权用户身份运行您的进程。

您可以通过启用 AppArmor、SELinux、 GRSEC 或其他适当的强化系统。

如果您想让 docker 更安全,我们欢迎功能请求, 拉取请求,或在 Docker 社区论坛上发表评论。