Docker安全性——官方文档[译]
本文译自Docker官方文档:https://docs.docker.com/articles/security/
在审查Docker的安全时,需要考虑三个主要方面:
◦容器内在的安全性,由内核命名空间和cgroup中实现;
◦docker守护程序本身的攻击面;
◦加固内核安全特性,以及它们如何与容器中互动。
内核 命名空间 Kernel Namespace
Docker容器中非常相似LXC容器,并且它们都具有类似的安全功能。当您以“docker run”启动一个容器,后台Docker为容器创建一组命名空间和控制组的集合。
命名空间提供隔离的最初也是最简单的形式:一个容器中运行的进程看不到运行在另一个容器中或者在主机系统中的进程,甚至它们之间更少的影响,。
每个容器也都有自己的网络协议栈,这意味着容器没有得到特权访问另一个容器的套接字或接口。当然,如果主机系统是设置因此,容器中可以相互通过各自的网络接口进
行交互 - 就像他们可以与外部的主机进行交互。当您为您的容器中或使用链路指定公共端口则IP通信允许容器之间。他们可以互相ping通,发送/接收UDP数据包,并建立
TCP连接,但可以在必要时会受到限制。从一个网络架构来看,给定Docker主机上的所有容器都坐在桥接接口。这意味着,他们只是想通过一个普通的以太网交换机连接的物
理机器;不多,不会少。
代码是如何成熟提供内核命名空间和专用网络?内核命名空间的内核版本2.6.15和2.6.26之间进行了介绍。这意味着,自2008年7月(2.6.26发布日期,现在5年前),命名
空间代码已经实行和审查上有大量的生产系统。还有更多:设计灵感的命名空间代码,甚至更老。命名空间实际上是为了重新实现的,因为它们可能被主流内核内合并这样
的方式的OpenVZ的特性。OpenVZ的最初发布于2005年,所以在设计和执行都相当成熟。
控制组 cgroups
控制组是Linux的容器的另一重要组成部分。他们实行资源核算和限制。他们提供了很多非常有用的指标,但他们也有助于确保每个容器获得其公平的内存,CPU,磁盘共享
I/O;并且,更重要的是,一个单一的容器不能用尽这些资源中的一个而使系统瘫痪。
因此,尽管它们不起到防止一个容器访问或影响数据和另一个容器的进程的作用,它们是必不可少的,以抵挡拒绝服务的一些攻击。他们是在多租户平台,像公共和私有
PaaS尤为重要,以保证正常运行时间一致(和性能),即使一些应用开始胡作非为。
控制组已经存在了一段时间,以及:代码在2006年已经开始,并在内核2.6.24开始合并。
Docker守护攻击面
运行容器(和应用程序)与Docker意味着运行Docker守护进程。此守护进程目前需要root权限,因此,你应该知道的一些重要的细节。
首先,只有受信任的用户应该可以控制你的Docker守护进程。这是直接造成一些强大的Docker功能。具体来说,Docker可以让你分享的Docker主体和客体容器之间的目录;它
允许你这样做不限制容器的访问权限。这意味着,你可以开始一个容器,其中/host目录将是你的主机上的/目录下;并且容器将能够改变你的主机文件系统没有任何限制。这
听起来很疯狂?好吧,你要知道,所有的虚拟化系统允许文件系统资源共享的行为方式相同。没有什么能阻止你从一个虚拟机共享您的根文件系统(甚至是你的root块设备
)。
这具有很强的安全性含义:例如,如果从通过API的Web服务器来提供容器中工具Docker,你应该比平常使用参数检查多加小心,以确保恶意用户无法通过精雕细琢的参数引
起Docker创建任意容器。
出于这个原因,所述的REST API端点(所使用的DockerCLI与Docker守护程序进行通信)中Docker0.5.2改变,现在采用的是UNIX套接字代替结合在127.0.0.1 TCP套接字(后
者是容易跨站点脚本攻击,如果你碰巧直接在本地计算机上运行Docker,一个VM之外)。然后,您可以使用传统的UNIX权限检查限制访问控制套接字。
您也可以通过暴露在HTTP REST API,如果你明确决定等。但是,如果你这样做,意识到上述的安全含义,你应该确保它会到达只能从一个可信任的网络或VPN;或受保护的如
与安全通道和客户端的SSL证书。你也可以保证他们HTTPS和证书。
在Linux的命名空间中的最新改进将很快允许没有root权限运行全功能的容器中,这要归功于新的用户空间。这是覆盖在这里详细。此外,这将解决由共享主机和客户之间的
文件系统的问题,因为用户命名空间允许容器(包括root用户)内的用户被映射到在主机系统的其他用户。
因此,最终目标是Docker要实现两个额外的安全性改进:
◦映射容器的root用户的Docker主机的非root用户,以减少容器到主机的权限提升的效果;
◦ 允许docker守护程序没有root权限运行,并委托操作要求这些特权以及审计的子流程,每个都有自己的(非常有限)适用范围:虚拟网络设置,文件系统管理,等等。
最后,如果在服务器上运行Docker,建议以在服务器上运行专门Docker,并且通过Docker控制容器中内移动的所有其他服务。当然,这是好的,让您最喜欢的管理工具(可
能至少SSH服务器),以及现有的监测/监控过程(例如,NRPE,collectd等)。
Linux内核能力 Capabilities
默认情况下,Docker开始容器具有非常有限的功能集。这意味着什么?
功能打开二进制“root/非root”二分法成细粒度的访问控制系统。进程(如Web服务器),仅仅需要绑定低于1024的端口上没有以root身份运行:他们可以被授予
net_bind_service能力来代替。而且还有很多其他功能,几乎所有的地方,通常都需要root权限的具体领域。
这意味着许多为docker的安全;让我们来看看为什么!
一般的服务器(裸机或虚拟机)都需要运行一堆流程作为root。这些通常包括SSH,cron,syslogd;硬件管理工具(如加载模块),网络配置工具(如处理DHCP,WPA或VPN)
的,等等。容器是非常不同的,因为几乎所有的这些任务由容器周围的基础设施进行处理:
◦SSH访问通常由Docker主机运行的单个服务器进行管理;
◦cron,必要的时候,应该运行作为一个用户进程,敬业,专为需要它的调度服务,而不是作为一个平台性的设备应用程序;
◦日志管理层也通常会被交给Docker,或由第三方服务,如Loggly或Splunk的;
◦硬件管理是无关紧要的,这意味着你永远不需要容器中运行udevd会或同等守护进程;
◦网络管理发生在容器外,执行的尽可能多的分离关注点,这意味着容器不应该需要执行ifconfig,route,或IP命令(除了当一个容器是专为像一个路由器或防火墙,当然
)。
这意味着,在大多数情况下,容器将不会在所有需要的“真实”root特权。因此,容器可以使用减少的能力集运行;这意味着“root”在一个容器内具有比真正的“root”少得多特
权。例如,它是可能的:
◦拒绝所有“装载”操作;
◦拒绝访问原始套接字(防止数据包欺骗);
◦拒绝访问某些文件系统操作,如创建新的设备节点,改变文件的所有者,或者改变属性(包括不可变标志);
◦拒绝模块加载;
◦以及等等。
这意味着,即使入侵者设法升级到root的容器内,这将是非常困难做严重损坏,或升级到主机。
这不会影响常规的网络应用;但恶意的用户会发现,兵工厂在他们的处置大幅下降!默认情况下,Docker滴除了那些需要的,白名单,而不是黑名单的方式全部功能。你可以
看到在Linux中提供联机帮助功能的完整列表。
当然,你可以随时启用额外的功能,如果你真的需要它们(举例来说,如果你想使用FUSE为基础的文件系统),但默认情况下,Docker容器使用默认的核心能力,只有白名
单。
其他内核安全特性
Capabilities 能力是现代Linux内核提供了许多安全特性之一。另外,也可以利用现有的,公知的系统,如TOMOYO,AppArmor,SELinux,GRSEC等使用Docker。
而Docker目前只允许功能,它不干扰其它系统。这意味着,有许多不同的方式来加固Docker主机。下面是一些例子。
◦您可以运行GRSEC和PAX内核。这将增加很多安全检查,无论是在编译时和运行时;它也将打败很多漏洞,这要归功于像地址随机化技术。它不需要Docker特定的配置中,由
于这些安全功能适用全系统,独立的容器中。
◦如果你的发行版自带的Docker容器安全模型模板,你可以使用它们的开箱即用。举例来说,推出一个与AppArmor工作和Red Hat自带SELinux策略Docker的模板。这些模板提
供了一个额外的安全网(即使它大大重叠使用能力)。
◦您可以使用自己喜欢的访问控制机制,定义自己的策略。
就像有许多第三方工具来增强Docker容器如特殊的网络拓扑结构或共享文件系统,你可以期望看到的工具来强化现有的Docker容器,而不会影响Docker的核心。
结论
Docker容器,默认情况下,相当安全的;特别是如果你把你的运行进程容器非特权用户内部的护理(即非root)。
您可以通过启用AppArmor中,SELinux,GRSEC,或者你最喜欢的加固解决方案中添加额外的安全层。
最后但并非最不重要的,如果你看到在其他容器化系统,有趣的安全功能,您将能够实现它们,以及使用Docker,因为一切无论如何都是由内核提供。
欲了解更多情况下,尤其是与虚拟机和其他容器系统的比较,也请看到原来的博客文章:http://blog.docker.com/2013/08/containers-docker-how-secure-are-they/。