DockerCon 2016 深度解读: Docker安全

前言

前端时间在乌云上出现了一篇很火的文章,从网上可以扫描到很多暴露控制端口到公网的Docker,并且没有配置认证策略,攻击者可以直接通过Docker Remote API控制Docker,而Docker通常又是用root权限启动的,所以攻击者等于完全获取的整个系统的权限。这件事再次给我们敲响了安全警钟,安全无小事,一个看似很小的问题,背后可能潜藏着巨大的安全风险。

本文将介绍Docker安全相关的一些技术,安全生态和最新的安全特性。

容器技术

容器技术最早可以追述到1979年在Unix上的chroot。Linux的目录结构从根目录/开始,根目录下是boot, usr, var, proc等目录。chroot可以改变程序的根目录,对于程序来说它看的根目录并不是系统真正的根目录,只是管理员额外准备的一套目录结构。这么做的一个重要原因就是安全:chroot之后的程序没法访问真实系统的的目录结构和文件。

这种技术和思想经过发展,最后成为了Linux上的Namespace,除了文件系统之外,还可以隔离PID、IPC、网络等。Namespace和用于管理资源CGroup一起构成了Linux上的容器技术。容器技术也叫操作系统级虚拟化,对于运行在其中的进程来说,就像运行在一台单独的机器上一样,它只能看到自己容器的进程、只能看到自己的目录结构,只能看到自己的网络栈,甚至资源也是有限制的,占用的内存超过了就会被kill。除了虚拟化,允许同时运行多个应用而不相互干扰,容器技术还带来了巨大的安全性。

使用容器虽然增强了安全性,但还远远不够。没有哪个软件是完美的,Linux内核也一样,容器也不能完全限制运行在其中的进程,曾经有漏洞允许进程可以突破容器访问到宿主机上的资源。除了程序漏洞之外,容器之间共享同一个Linux内核,容器可以直接操作内核,可以通过内核漏洞对系统进行攻击。

Linux系统的安全技术

Linux里包含了非常多的安全特性,容器技术只是其中一项。Overview of Linux Kernel Security Features给出了一个长长的列表。

Docker的安全

Docker刚出来的时候,我曾说过Docker=容器+镜像,虽然完全是出于程序员的思维习惯,从技术实现的角度所作出的评价,不过有助于我们理解背后的原理。由于Docker是基于容器的,天生具有容器带来的安全优势:可以虚拟一个隔离的运行环境,可以限制资源。但是对于容器不能解决的安全问题:逃逸和共享内核,Docker解决了吗?有没有其他新的安全问题?

Docker一直很关注安全的问题,早期的版本就支持设置capabilities,通过drop掉一些capabilities,可以削弱运行在容器中的进程权限。Docker提供了方便和LSM集成的机制,可以更容易配置SELinux或者Apparmor,增强容器安全性。

DockerCon 2016 深度解读: Docker安全

上图是Docker/LXC/CoreOS Rkt所支持的安全特性对比。

Docker镜像安全

镜像是Docker化应用分发的唯一机制,重要性不言而喻。镜像本身有哪些安全问题呢?首先,镜像内部的程序、lib和配置可能存在缺陷。去年有报道称超过30%的官方镜像存在严重的安全缺陷,因为其中包含了一些存在缺陷的软件和lib,比如openssl的心脏流血。其次是Docker镜像的完整性校验,你怎么知道你运行的镜像没有被人篡改过呢?

对于镜像完整性,Docker主要提供了两方面的功能:Registry V2引入的内容可寻址镜像存储和镜像签名。继续之前,我们先简单的回顾下镜像下载过程(Registry V2):

  1. 下载Manifest,Manifest里包含了镜像的一些元信息,以及所有组成这个镜像的层ID。层ID是层内容的SHA256摘要(也就是内容可寻址)。
  2. 下载各个层。

客户端下载镜像之后,重新计算SHA256,如果不匹配层ID,则校验失败,这种方式既解决了传输过程中的数据篡改,也解决了层内容损坏。

镜像签名保证了镜像分发过程中的完整性。在分发过程中,中间人可以修改层内容,同时把Manifest也改掉,对下载镜像的客户端来说,SHA256校验完全没有问题,但是下载到的镜像已经不是期望中的那个镜像,里面不知道放了一些什么奇怪的东西。有了镜像签名之后,镜像构建者在Manifest里加上自己的数字签名,客户端可以下载Manifest之后根据签名验证Manifest是否被篡改过。

安全生态

目前有很多的公司都在做Docker安全相关的业务,在DockerCon2016上,我们可以看到Twistlock、Aqua。甚至Docker本身也在做一些安全的产品,例如Docker Cloud的镜像安全扫描工具。业界也有一些开源的开源的产品,Coreos最近开源了镜像扫描工具Clair

Twistlock和Aqua的产品功能很像,都提供了镜像扫描、运行时容器扫描、访问控制等功能。这里的访问控制是接管了Docker控制API,也就是说不直接访问Docker,而是先访问twistlock或者Aqua的程序,由它们把请求转发给Docker,转发之前,会对请求进行一些权限检查等操作。

DockerCon 2016 深度解读: Docker安全

Twistlock架构:由控制台和运行在Docker机器上的Agent组成

因为在一台宿主机上,多个Docker容器共享一个内核,业界的看法是Docker不适合作为多租户场景。既然不能共享内核,最直接的办法就是给每个容器一个内核,实际上hyper就是这么做的。另外一种思路是通过SELinux/Apparmor和seccomp,配置一个安全的沙箱,也可以做到多租户安全,传统基于LXC的PAAS就是通过这种方式做的。

总结

Docker安全是个很大的话题,涉及从操作系统内核到企业安全策略,包括数据、网络、存储等各种安全方案,本文只能作为一个最简单的介绍。

总得来说,使用Docker,首先千万不要把对Daemon的访问不加防护的暴露到公网,就行本文开头提到的。其次,如果是多租户环境或者对运行环境安全要求高的场景,考虑各种内核安全方案配合使用,做到纵深防御。或者使用虚拟化+轻量级内核的方式。最后,使用镜像扫描工具,不要让对外提供的服务存在安全缺陷。

上一篇:脏牛(Dirty Cow)快速指南


下一篇:微信小程序遇见容器服务