Docker安全性

预计阅读时间:11分钟

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

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

内核名称空间

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

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

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

提供内核名称空间和专用网络的代码有多成熟?内核名称空间是在内核2.6.15和2.6.26之间引入的。这意味着自2008年7月(2.6.26版本的发布日期)以来,命名空间代码已在大量生产系统上使用和检查。还有更多:命名空间代码的设计和灵感甚至更老了。命名空间实际上是一种重新实现OpenVZ功能的工作,可以将它们合并到主流内核中。OpenVZ最初于2005年发布,因此设计和实现都相当成熟。

对照组

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

因此,尽管它们在阻止一个容器访问或影响另一个容器的数据和进程方面不起作用,但对于抵御某些拒绝服务攻击而言,它们却是必不可少的。它们在公共和私有PaaS等多租户平台上尤其重要,即使在某些应用程序开始出现异常时,也要保证一致的正常运行时间(和性能)。

控制组也已经存在了一段时间:该代码始于2006年,最初合并在内核2.6.24中。

Docker守护程序攻击面

使用Docker运行容器(和应用程序)意味着运行Docker守护程序。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和收集的)。

Linux内核功能

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

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

这对于容器安全来说意义重大。让我们看看为什么!

典型的服务器运行多个进程root,包括SSH守护程序, cron守护程序,日志记录守护程序,内核模块,网络配置工具等。容器是不同的,因为几乎所有这些任务都是由容器周围的基础结构来处理的:

  • SSH访问通常由运行在Docker主机上的单个服务器管理;
  • cron,必要时,应作为用户流程运行,专门为需要其计划服务的应用量身定制,而不是作为平台范围的工具;
  • 日志管理通常也交给Docker或Loggly或Splunk等第三方服务;
  • 硬件管理无关紧要,这意味着您无需udevd在容器内运行或运行等效的守护程序;
  • 网络管理发生在容器的外面,执行关注点分离尽可能的,这意味着一个容器不应该需要执行ifconfigroute或IP命令(当容器被特别设计,以表现得象一个路由器或防火墙除外,当然) 。

这意味着,在大多数情况下,容器并不需要“真正的” root特权可言。因此,容器可以以降低的功能集运行;意味着容器中的“ root”特权比真正的“ root”少得多。例如,可以:

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

这意味着即使入侵者设法升级到容器中的根,也很难造成严重的破坏或升级到主机。

这不会影响常规的Web应用程序,但会大大降低恶意用户的攻击媒介。默认情况下,Docker会丢弃除所需功能之外的所有功能,即允许列表而不是拒绝列表方法。您可以在Linux联机帮助页中看到可用功能的完整列表。

运行Docker容器的一个主要风险是,给容器的默认功能集和安装集可能会提供不完整的隔离,无论是独立提供还是与内核漏洞结合使用。

Docker支持添加和删除功能,从而允许使用非默认配置文件。通过移除功能,这可能使Docker更加安全,而通过添加功能,则可能使Docker的安全性降低。用户的最佳做法是删除所有功能,但过程中明确不要求的功能除外。

Docker内容信任签名验证

可以将Docker引擎配置为仅运行签名的映像。Docker Content Trust签名验证功能直接内置在dockerd二进制文件中。
这是在Dockerd配置文件中配置的。

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

与以前使用CLI来执行和执行图像签名验证相比,此功能为管理员提供了更多的见识。

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

其他内核安全功能

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

尽管Docker当前仅启用功能,但它不会干扰其他系统。这意味着可以采用多种方法来强化Docker主机。这里有一些例子。

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

正如您可以使用第三方工具来扩展Docker容器(包括特殊的网络拓扑或共享文件系统)一样,现有的工具可以加固Docker容器,而无需修改Docker本身。

从Docker 1.10开始,Docker守护程序直接支持用户命名空间。此功能允许将容器中的root用户映射到容器外部的非uid-0用户,这可以帮助减轻容器突破的风险。该功能可用,但默认情况下未启用。

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

结论

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

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

如果您想到使Docker更加安全的方法,我们欢迎在Docker社区论坛上提出功能请求,拉取请求或发表评论。

DockerDocker文档安全