当我们提到Docker安全时,主要考虑四个方面:
内核本身的安全性和内核对namespace和cgroup的支持;
Docker Deamon 本身的攻击面
默认的或是用户定制的配置文件的漏洞
“固化的”内核安全功能,以及他们如何同容器交互
内核的命名空间
Docker容器与LXC容器非常像,他们有相同的安全功能。当你使用docker run 命令开启一个容器时,其实Docker为容器创建了一系列的namespace和controlgroup。
Namespace提供了最初最直接的隔离形式:当你在容器中运行一个进程,其它容器或者host系统中的进程不可见甚至不会受其影响。
每个容器有其自己的网络协议栈,这意味着一个容器不会得到权限去访问其它容器的socket和接口。当然,如果host系统做了相应的设置,那么容器间可以的接口可以彼此交互——就像他们可以和外部host交互一样。当你为你的容器指定一个公共接口或者或使用链接,那么容器之间就可以出现IP的交通(IP traffic),他们可以互相ping通,或者收发UDP数据包、建立TCP 链接,但在需要的时候可以限制他们。从一个网络架构的观点来看,Docker提供的所有的容器都与网桥的对应接口相连。这意味着他们就像物理机通过以太网交换机相连一样,不多也不少。
由代码提供的内核namespace和私有网络有多成熟呢?在内核版本2.6.15至2.6.26时引入namespaces。这说明自从2008年6月就已经实施了namespace的代码,并经过了大量的系统产品的检查。甚至,设计和创造namespace代码的时间就更长了。Namespaces的确是一个合并于主流操作系统的重新实现OpenVZ特征方法。OpenVZ最早于2005年发行,所以namespace的设计和实行都十分成熟了。
Controlgroups(控制组)
Controlgroups是Linux Container(Linux容器)的关键组件。他们实现了资源统计和限制。他们提供了许多有用的metrics(韵律?),但是也确实帮助每个容器可以公平的分享内存、CPI、磁盘读写等等。更为重要的是,单独一个容器不能消耗所有的资源后使计算机宕机。
所以他们无法避免一个容器中的数据被其他容器访问,但是他们主要可以避免拒绝服务攻击(DOS)。尤其在多租户系统中他们显得尤为有用,例如私有或公有PaaS,甚至在有应用出现误操作时,来保证连续的运行(和性能)。
ControlGroups也运行了很长的时间,从2006年起,最早被整合在2.6.24内核中。
DockerDaemon攻击面
运行中的容器(和应用)意味着Docker Daemon也在运行。这个Daemon当前要求root权限,并且你应该注意一些重要的细节。
首先,只有你信任的用户才允许控制你的Docker Daemon。这直接导致一些有效地Docker特性。特别得,Docker允许Dockerhost和容器共享目录;这允许你做不受容器访问权限控制的操作。这意味着你可以将 / 路径设为/host 然后开启容器,那么容器就可以不受限制地访问你的主机文件系统。这很像虚拟系统允许文件系统资源共享。没有人阻拦你和虚拟机分享你的根文件系统甚至块设备。
这是一个强烈的安全隐患:例如,如果你在web服务器通过一个API来部署容器,你应该比平时检查参数时更小心,确定是否有禁止恶意用户自己设定参数来随意创建容器。
出于这个原因,REST API终端(用于DcokerCLI和Docker Daemon通信)在Docker0.5.2时改进,现在使用了UNIXsocket而不是使用与127.0.0.1绑定的TCPsocket(后者易于跨站请求伪造攻击,如果直接在主机上运行Docker)。你可以使用传统的UNIX授权检查来限制控制socket(controlsocket)。
如果你的确确定的话,你也可以使用RST API 而不是http。然而如果你这么做,要意识到上述的安全隐患,你应该确保只能接收到可信的网络或VPN;或者保护比如stunnl和SSL证书。你也可以通过HTTPS和证书来保护他们。
Daemon也有可能被其他输入攻击,比如使用docker load从磁盘load图片,或从其他网站使用docker pull。截至Docker1.3.2,在Linux、Unix平台上,镜像现在被取至chroot,这是将权限分开的有重要意义的第一步。截至Docker1.10.0,所有的镜像访问时加密他的内容的checksum(all images are stored andaccessed by the cryptographic checksums of their contents),用于限制攻击者破坏一个已有的镜像。
甚至,Dcoker Daemon会被限制运行权限,代表操作会被子进程仔细检查Linux的容量、网络设置,文件系统管理,等等。也就是说,Docker引擎本身可能运行于容器之中。
最后,如果您在服务器上运行Docker,则建议在服务器上专门运行Docker,并将所有其他服务移动到由Docker控制的容器中。当然,它会很好地保留你的管理工具,(可能至少是一个SSL服务),和存在的监视器、监管进程,比如NRPE(Nagios Remote Plugin Executor)和collected.