Docker安全性

需要考虑四个方面的因素:
1、linux内核的namespace和cgroup。
2、docker daemon的攻击。
3、容器的配置文件漏洞,默认的或者用户自定义的配置文件。
4、内核的“强化”安全功能,以及它们如何与容器交互。

linux内核的namespace

     Docker容器与LXC容器非常相似,并且它们具有类似的安全功能。当你启动一个容器时 docker run,Docker为这个容器创建一组linux内核的namespace和cgroup。namespace提供最直接的隔离形式:容器中运行的进程互相不受影响,互相看不到。
     每个容器有自己的网络栈:这意味着容器不会获取另一个容器的socket和其他接口的访问权限,容器可以通过他们个自己的接口相互访问,就像他们访问外部主机一样的效果。当您为容器指定公共端口或使用links时,他他们可以相互提供IP通信,它们可以互相ping通,发送/接收UDP数据包,并建立TCP连接,如该需要也可以限制他们。

linux内核的cgroup

    cgroup是Linux容器的另一个关键组件。他们实现了系统资源的统计和限制。它们提供了许多有用的度量标准,它们也有助于确保每个容器获得其公平的内存,CPU和磁盘I/O份额,更重要的是,单个容器不能耗尽这些资源中的一个来降低系统的性能。
    因此,尽管它们不能阻止一个容器访问或影响另一个容器的数据和进程,但它们对抵御一些拒绝服务攻击至关重要。它们对于多租户平台尤其重要。
cgroup技术出现有一段时间:代码是在2006年开始的,最初被合并到内核2.6.24中。

Docker daemon 攻击

    运行容器意味着肯定要运行docker daemon,docker daemon 一般需要root权限运行,因此你应该知道一些重要的细节。
     首先,应该只允许受信任的用户来控制你的Docker守护进程,这是强大docker功能导致的直接后果,具体来说:Docker允许您在Docker主机和访客容器之间共享一个目录(-v),这意味着您可以启动一个容器,他的/host目录是你主机的根目录,容器可以不受任何限制地改变你的主机文件系统。这与虚拟化系统如何允许文件系统资源共享类似。没有什么能够阻止你与虚拟机共享你的根文件系统(甚至你的根块设备)。

Linux内核功能 kernel capabilities

默认情况下,Docker会使用一组受限制的功能启动容器,那是什么意思?
    Capabilities将二元“root/non-root”二分法转变为一个细粒度的访问控制系统,只需要绑定到低于1024端口的进程(如Web服务器)不需要以root用户身份运行,他们只需要net_bind_service授予权限,
典型的服务器都会以root身份运行一些进程,比如SSH daemon,cron daemon,logging daemon,kernel modules,网络配置工具等,容器是不同的,因为几乎所有这些任务都是由容器周围的基础设施处理的:

  • SSH访问通常由运行在Docker主机上的单个服务器管理;
  • cron在必要时应该作为用户进程运行,专门针对需要其调度服务的应用程序专门定制,而不是作为平台范围的设施;
  • 日志管理通常也交给Docker或者Loggly或Splunk等第三方服务;
  • 硬件管理是无关紧要的,这意味着你永远不需要udevd在容器中运行或等效的守护进程;
  • 网络管理发生在容器的外面,执行关注点分离尽可能的,这意味着一个容器不应该需要执行ifconfig,route或IP命令(当容器被特别设计,以表现得象一个路由器或防火墙除外,当然) 。
        这意味着,在大多数情况下,容器并不需要“真正的” root特权可言。因此,集装箱可以运行一个能力较低的集合; 这意味着容器中的“根”比真正的“根”要少得多。例如,有可能:
  • 否认所有“挂载”操作;
  • 拒绝访问原始套接字(以防止数据包欺骗);
  • 拒绝访问某些文件系统操作,如创建新设备节点,更改文件所有者或更改属性(包括不可变标志);
  • 拒绝模块加载;
  • 其他

这意味着,即使入侵者设法在容器内升级到根目录,要做到严重损坏或升级到主机也要困难得多。

其他内核安全功能

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

Docker的AppArmor安全配置

    AppArmor (Application Armor) 是一个Linux安全模块,可保护操作系统及其应用程序免受安全威胁。要使用它,系统管理员会将AppArmor安全配置文件与每个进程关联起来。
    docker 自动生成并加载默认的配置文件,名字为:docker-default。在Docker版本1.13.0和更高版本中,Docker生成此配置文件在tmpfs目录下,然后加载到内核中。在早于1.13.0版本的Docker中,生成此配置文件在/etc/apparmor.d/docker,此配置文件用于容器,而不是 Docker守护程序。

理解该策略

    docker-default配置文件是运行容器的默认设置。它具有适度的保护性,同时提供广泛的应用兼容性 该配置文件是从以下模板生成:https://github.com/moby/moby/blob/master/profiles/apparmor/template.go

    运行容器的时候,可以通过security-opt选项自己指定该配置文件的路径,如下:

docker run –rm -it –security-opt apparmor=docker-default hello-world

加载,卸载AppArmor配置文件命令:

# stop apparmor
$ /etc/init.d/apparmor stop

# start apparmor
$ /etc/init.d/apparmor start

# unload the profile
$ apparmor_parser -R /path/to/profile

# load the apparmor profile
$ apparmor_parser -r -W /path/to/your_profile

# to check which profiles are loaded
$ sudo aa-status

Docker的Seccomp安全配置

    Secure computing mode (seccomp)是Linux内核功能。可以使用它来限制容器内可用的操作.该seccomp()系统调用可以用来限制应用程序的访问权限。

    只有在Docker已经构建seccomp并且内核配置为CONFIG_SECCOMP启用的情况下,此功能才可用。检查你的内核是否支持seccomp:

$ grep CONFIG_SECCOMP= /boot/config-$(uname -r)
CONFIG_SECCOMP=y

传递配置文件到容器中

    默认的seccomp配置文件为容器运行提供一个健全的默认配置,并禁用了大约44个超过300+的系统调用,默认的配置文件可以在这里找到:https://github.com/moby/moby/blob/master/profiles/seccomp/default.json

    实际上,该配置文件是白名单,默认情况下拒绝访问系统调用,然后将特定的系统调用列入白名单。
seccomp有助于以最低权限运行Docker容器。不建议更改默认seccomp配置文件。运行容器时,除非使用该–security-opt选项覆盖容器,否则它将使用默认配置文件。例如,以下显式指定了一个策略:

$ docker run --rm \
             -it \
             --security-opt seccomp=/path/to/seccomp/profile.json \
             hello-world

运行时不使用默认的seccomp配置文件:

$ docker run --rm -it --security-opt seccomp=unconfined debian:jessie \
    unshare --map-root-user --user sh -c whoami