15 | Docker安全:在虚拟的环境中,就不用考虑安全了吗?
Docker服务:Docker所提供的功能以及在宿主机Linux中的Docker进程
Docker镜像:通过Dockerfile构建出来的Docker镜像
Docker容器:实际运行的Docker容器,通常来说,一个Docker镜像会生成多个Docker容器。Docker容器运行与Docker服务至上
Docker服务安全
Docker 服务本身需要关注的安全性就是:隔离。如果黑客在控制了容器之后,能够成功对宿主机产生影响,就说明黑客突破了 Docker 服务的隔离保护,也就是我们所说的“Docker 逃逸”。
Namespace机制
Docker轻量级
虚拟机是自己创造了一个虚拟内核,让这个虚拟内核去和虚拟机的进程进行沟通,然后虚拟内核再和真实的 Linux 内核进行沟通。而 Docker 提供的容器,简化了这个沟通过程,让 Docker 中的进程直接和 Linux 内核进行沟通。
Docker隔离
Docker 提供的容器环境是和 Linux 内核隔离的。想要实现这种隔离,就需要用到 Namespace 机制了。
Namespace 是 Linux 提供的一种标签机制,Linux 内核会对不同 Namespace 之间的进程做隔离,避免不同的进程之间互相产生影响。所以,Docker 服务会为每一个 Docker 容器创建一个单独的 Namespace 空间。
这种基于 Namespace 的隔离我一般叫它“伪隔离”。
因为容器和宿主机需要共同使用一些服务(比如容器和宿主机使用的是同一个鼠标),所以一些目录和模块,对于容器和宿主机来说,其实是共享的。从理论上来说,如果你在 Docker 容器中修改了这些目录,那么宿主机当中也会同步相应的修改结果。
Capabilities 机制
Namespace 的伪隔离机制让容器和宿主机共享部分目录。那么,这是不是也意味着,Docker 容器可以通过这些目录来影响宿主机,从而实现“Docker 逃逸”呢?为了避免这种情况,Docker 服务使用了 Capabilities 机制,来限制容器的操作。
CGroups 机制
知道 Docker 服务本身是如何防止“Docker 逃逸”的了。作为一个容器,Docker 显然不能过多地占用宿主机资源,不然对宿主机和自身的可用性都会产生影响。那 Docker 是如何实现资源限制的呢?
Docker 服务可以利用 CGroups 机制来实现对容器中内存、CPU 和 IO 等的限制。
所以,当一个宿主机中运行了多个 Docker 容器的时候,我们可以通过 CGroups,给每一个容器弹性地分配 CPU 资源。同样地,这个限制既不能过松,过松会导致某一个 Docker 容器耗尽宿主机资源,也不能过严,过严会使得容器内的服务得不到足够的资源支持。
Docker 守护进程
想要运行 Docker 镜像,就必须先启动 Docker 的 Daemon 守护进程。而启动这个守护进程需要 ROOT 权限。因此,守护进程本身如果出现漏洞,就会给黑客提供一个权限提升的入口。那通过这个守护进程,黑客能进行哪些操作呢?
首先,作为守护进程,Daemon 具备操控 Docker 容器的全部权限。这也就意味着,黑客可以任意地上线和下线容器、运行黑客自己的镜像、篡改已有镜像的配置等。
守护进程提供的 API 接口,是为了方便用户去做一些自动化的工具,来操控 Docker 容器。而在默认情况下,这个 API 接口不需要进行认证。
为了避免这种无认证的情况发生,Docker 提供了证书的方式来进行认证。
Docker 镜像安全
对于 Docker 镜像来说,它本身就是一个模拟的操作系统,自然也会存在操作系统中的各类安全威胁和漏洞。
Snyk 在 2019 年的Docker 漏洞统计报告称,最热门的 10 个 Docker 基础镜像,包含的已知系统漏洞,最少的有 30 个,最多的有 580 个。
使用最精简的镜像
通过使用最精简的基础镜像,来删减 Docker 镜像中不必要的功能,从而降低出现漏洞的概率。
Docker 中的最小权限原则
以低权限用户来执行服务,限制黑客的能力。
总结
在 Docker 服务中,主要是利用 Namespace、Capabilities 和 CGroups 机制,来对 Docker 容器进行各种隔离和限制;在 Docker 守护进程中,我们通过给远程 API 加上认证功能来保证安全性;在 Docker 镜像中,我们主要是通过最小镜像和最小权限的原则,去提升镜像本身的安全性。
在实际对 Docker 进行安全防护的过程中,我们也可以采取各类针对 Docker 的扫描工具,来发现问题。比如Clair,它会对你的镜像进行静态的扫描分析,并和漏洞库进行比对,从而发现镜像中可能存在的安全漏洞。