Docker security

预计阅读时间:11分钟

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

  • 内核的内在安全性及其对命名空间和 cgroup 的支持;
  • Docker 守护进程本身的攻击面;
  • 容器配置文件中的漏洞,无论是默认情况下,还是由用户自定义时.
  • 内核的"强化"安全特性以及它们如何与容器交互.

Kernel namespaces

Docker 容器与 LXC 容器非常相似,并且具有相似的安全特性. 当您使用docker run启动容器时,Docker 会在后台为容器创建一组命名空间和控制组.

命名空间提供了第一种也是最直接的隔离形式:在一个容器中运行的进程无法看到运行在另一个容器或主机系统中的进程,而且影响更小.

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

提供内核命名空间和私有网络的代码有多成熟? 在内核版本 2.6.15 和 2.6.26 之间引入了内核命名空间. 这意味着自 2008 年 7 月(2.6.26 发布日期)以来,命名空间代码已经在大量生产系统上进行了测试和审查. 还有更多:命名空间代码的设计和灵感更古老. 命名空间实际上是为了重新实现OpenVZ的特性,以便它们可以合并到主流内核中. 而 OpenVZ 最初是在 2005 年发布的,所以无论是设计还是实现都相当成熟.

Control groups

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

因此,虽然它们在阻止一个容器访问或影响另一个容器的数据和进程方面没有发挥作用,但它们对于抵御一些拒绝服务攻击至关重要. 它们在多租户平台上尤其重要,例如公共和私有 PaaS,即使在某些应用程序开始出现异常时也能保证一致的正常运行时间(和性能).

控制组也已经存在了一段时间:代码开始于 2006 年,最初并入内核 2.6.24.

Docker daemon attack surface

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

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

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

出于这个原因,REST API 端点(由 Docker CLI 用于与 Docker 守护程序通信)在 Docker 0.5.2 中发生了变化,现在使用 UNIX 套接字而不是绑定在 127.0.0.1 上的 TCP 套接字(后者容易如果您碰巧直接在本地机器上运行 Docker,则跨站点请求伪造攻击). 然后,您可以使用传统的 UNIX 权限检查来限制对控制套接字的访问.

如果您明确决定这样做,您还可以通过 HTTP 公开 REST API. 但是,如果您这样做,请注意上述安全隐患. 请注意,即使您有防火墙来限制网络中其他主机对 REST API 端点的访问,该端点仍然可以从容器中访问,并且很容易导致权限提升. 因此,必须使用HTTPS 和证书来保护 API 端点. 还建议确保只能从受信任的网络或 VPN 访问它.

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

守护进程也可能容易受到其他输入的影响,例如使用docker load从磁盘加载图像,或者使用docker pull从网络加载图像. 从 Docker 1.3.2 开始,图像现在在 Linux/Unix 平台上的 chroot 子进程中提取,这是更广泛的权限分离努力的第一步. 从 Docker 1.10.0 开始,所有图像都通过其内容的加密校验和进行存储和访问,从而限制了攻击者与现有图像发生冲突的可能性.

最后,如果您在服务器上运行 Docker,建议在服务器上独占运行 Docker,并将所有其他服务移动到 Docker 控制的容器中. 当然,保留您最喜欢的管理工具(可能至少是一个 SSH 服务器)以及现有的监控/监督流程(例如 NRPE 和 collectd)是可以的.

Linux kernel capabilities

默认情况下,Docker 启动具有一组受限功能的容器. 这意味着什么?

功能将二进制"根/非根"二分法转变为细粒度的访问控制系统. 只需要在低于 1024 的端口上绑定的进程(如 Web 服务器)不需要以 root 身份运行:它们可以被授予net_bind_service能力. 对于通常需要 root 权限的几乎所有特定领域,还有许多其他功能.

这对容器安全意义重大; 让我们看看为什么!

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

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

这意味着在大多数情况下,容器根本不需要"真正的"root 权限. 因此,容器可以以减少的能力集运行; 这意味着容器中的"root"比真正的"root"拥有更少的权限. 例如,可以:

  • 拒绝所有"挂载"操作;
  • 拒绝访问原始套接字(以防止数据包欺骗);
  • 拒绝访问某些文件系统操作,例如创建新设备节点、更改文件所有者或更改属性(包括不可变标志);
  • 拒绝模块加载;
  • 和许多其他人.

这意味着即使入侵者设法在容器内升级为 root,也很难造成严重破坏或升级到主机.

这不会影响常规 Web 应用程序,但会大大减少恶意用户的攻击媒介. 默认情况下,Docker 会删除除那些需要之外的所有功能,即允许列表而不是拒绝列表方法. 您可以在Linux 手册页中查看可用功能的完整列表.

运行 Docker 容器的一个主要风险是,为容器提供的一组默认功能和挂载可能会提供不完整的隔离,无论是独立的,还是与内核漏洞结合使用时.

Docker 支持添加和删除功能,允许使用非默认配置文件. 这可能会使 Docker 通过删除功能更安全,或者通过添加功能来降低安全性. 用户的最佳实践是删除所有功能,但其流程明确要求的功能除外.

Docker Content Trust Signature Verification

可以将 Docker 引擎配置为仅运行签名图像. Docker 内容信任签名验证功能直接内置在dockerd二进制文件中.
这是在 Dockerd 配置文件中配置的.

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

此功能为管理员提供了比以前使用 CLI 执行和执行图像签名验证的更多洞察力.

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

Other kernel security features

功能只是现代 Linux 内核提供的众多安全特性之一. 也可以通过 Docker 来利用现有的知名系统,如 TOMOYO、AppArmor、SELinux、GRSEC 等.

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

  • 您可以使用 GRSEC 和 PAX 运行内核. 这在编译时和运行时都增加了许多安全检查; 由于地址随机化等技术,它还击败了许多漏洞. 它不需要特定于 Docker 的配置,因为这些安全功能适用于系统范围,独立于容器.
  • 如果您的发行版附带 Docker 容器的安全模型模板,您可以开箱即用地使用它们. 例如,我们发布了一个适用于 AppArmor 的模板,而 Red Hat 附带了用于 Docker 的 SELinux 策略. 这些模板提供了额外的安全网(即使它与功能有很大重叠).
  • 您可以使用自己喜欢的访问控制机制定义自己的策略.

Just as you can use third-party tools to augment Docker containers, including special network topologies or shared filesystems, tools exist to harden Docker containers without the need to modify Docker itself.

从 Docker 1.10 开始,docker 守护进程直接支持用户命名空间. 此功能允许将容器中的 root 用户映射到容器外的非 uid-0 用户,这有助于降低容器突围的风险. 此功能可用,但默认情况下未启用.

有关此功能的更多信息,请参阅命令行参考中的daemon 命令. 有关在 Docker 中实现用户命名空间的其他信息,请参阅此博客文章.

Conclusions

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

您可以通过启用 AppArmor、SELinux、GRSEC 或其他适当的强化系统来增加额外的安全层.

如果您想办法让 docker 更安全,我们欢迎在 Docker 社区论坛上提出功能请求、拉取请求或评论.

Docker, Docker 文档, security

by  icopy.site