Docker在安全方面做了些工作,包括:
(1)Docker daemon在以TCP形式提供服务的同时使用传输层安全协议。
(2)在构建和使用镜像时会验证镜像的签名证书。
(3)通过cgroups和namespace对容器进行资源限制和隔离。
(4)提供自定义容器能力(capability)的接口。
(5)通过定义second profile限制容器内进程系统调用的范围。
1.容器安全机制
主要从以下方面进行设计。
1.1.Docker daemon安全
Docker向外界提供服务主要有四种方式,默认是以Unix域套接字的方式与客户端进行通信,这比TCP安全。
为了提高基于TCP通信的安全性,Docker提供了TLS(transport layer security)传输层安全协议。Docker中设置--tlsverify进行安全传输校验,通过--tlscacert(信任的证书)、--tlskey(服务器或客户端密钥)、--tlscert(证书路径)这三个参数来配置。
1.2.镜像安全
Docker提供registry访问权限控制保证镜像安全。
1.3.内核安全
除了六种资源的隔离,还有其他资源未完成隔离,如/proc、/sys、/dev、time、syslog、SELinux等。
1.4.容器间网络安全
iptables规则设定保证网络安全。
1.5.容器能力限制
docker run参数中提供了容器能力配置的接口。
容器默认拥有的能力有:
(1)CHOWN:允许任意更改文件UID和GID
(2)DAC_OVERRIDE:允许忽略文件的读、写、执行访问权限检查
(3)FSETID:允许文件修改后保留setuid/setgid标志位
(4)SETGID:允许修改进程组ID
(5)SETUID:允许修改进程用户ID
(6)SETFCAP:允许向其他进程转移或删除功能
(7)NEW_RAW:允许创建RAW和PACKET套接字
(8)MKNOD:允许使用mknod创建指定文件
(9)SYS_REBOOT:允许使用reboot或kexec_load
(10)SYS_CHROOT:允许使用chroot
(11)KILL:允许发送信号
(12)NET_BIND_SERVICE:允许绑定常用端口号,即小于1024的端口号
(13)AUDIT_WRITE:允许审计日志写入
如何削减能力?使用--cap-drop,如“--cap-drop KILL”。
如何增添能力?使用--cap-add,如“--cap-add SYS_TIME”。
如何查看能力?执行命令“pscap | grep ${CID}”,其中CID为容器进程cid。
1.6.seccomp
seccomp是linux内核特性,可用于限制进程能否调用的系统调用范围,从而减少内核的攻击面,被广泛用于构建沙盒。
使用seccomp的前提是Docker构建时已包含seccomp,且宿主机内核中的CONFIG_SECCOMP已开启。检查内核是否支持seccomp的命令为“cat /boot/config-`uname -r` | grep CONFIG_SECCOMP=”。
然后,我们在Docker中为每个容器编写json格式的seccomp profile赖实现对容器中进程系统调用的限制。
最后启动容器,案例如下:
docker run --rm -it --security-opt seccomp:/path/to/seccomp-profile.json hello-world;
注:默认情况下,docker运行容器时会使用默认的seccomp profile,可用unconfined禁用此profile,案例如下:
docker run --rm -it --security-opt seccomp:unconfined hello-world;
2.Docker安全问题
Docker在安全方面做了不少工作,但Docker安全问题仍然非常多,比如:
2.1.磁盘资源限制问题
所有容器的rootfs最终存储在宿主机,极有可能把磁盘空间耗尽。
2.2.容器逃逸问题
Docker使用操作系统虚拟化,共享内存、内核、CPU及磁盘,可能发生容器逃逸。一旦逃逸,宿主机和所有容器都将受到威胁。
2.3.容器DoS攻击与流量限制问题
随着虚拟化技术的兴起,攻击数据包可能不需要通过物理网卡就可以攻击同一个宿主机下的其他容器。
默认的Docker网络是网桥模式,实际上所有容器和宿主机共用一张物理网卡,如果某个容器抢占大部分带宽,将会影响其他容器的使用。
2.4.超级权限问题
docker run时加上--privileged参数,使容器获得超级权限。这给的权限太多,需要调整容器的能力,以保证容器使用的安全。
3.Docker安全的解决方案
Docker通过一些额外的工具来加强安全。
3.1.SELinux
这是内核实现的MAC(Mandatory Access Control,强制访问控制),可以说SELinux就是一个MAC系统。
Docker daemon启动时加“--selinux-enabled=true” 可启用SELinux。
docker run容器时可指定user、role、type、level等标签信息。
3.2.磁盘限额
目前提供--storge-opt=[ ]来进行磁盘限制,仅支持Device Mapper文件系统的磁盘限额。不支持其他的存储引擎。
3.3.宿主机内容器流量限制
利用linux中的流量控制(traffic controller)模块,原理是为数据包建立队列,并定义队列中数据包的发送规则,实现流量控制。
队列有两种:
(1)无类队列:统一对待进入网卡的数据,队列规定主要有PFIFO_FAST、TBF、SFQ等,流量整形手段是排序、限速以及丢包。
(2)分类队列:对进入网卡的数据包根据不同的需求以分类的方式区分对待。数据包进入分类队列后,由过滤器对数据包进行分类,并返回一个决定,队列根据决定把数据包传入不同的子队列。每个子队列还可以再分类,进行迭代,直到不需要分类为止。
流量控制的4种方式:
(1)SHAPING:流量被限制时,限制传输速率。适用于限制外出的流量。
(2)SCHEDULING:通过调度数据包传输的优先级数据,可以在带宽范围内对不同的传输流按照优先级分配。适用于限制外出的流量。
(3)POLICING:用于处理接受到的数据,对数据流量进行限制。
(4)DROPPONG:如果流量超过设置的阈值就丢弃数据包,向内向外都有效。
常用的无类队列:TBF(token bucket filter)
常见的分类队列:CBQ(class based queue)
3.4.GRSecurity内核安全增强工具
GRSecurity提供内存破坏防御、文件系统增强等各式各样的防御。