19.3 内核能力机制

能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制。传统的Unix系统对进程权限只有根权限(用户id为0,即为root用户)和非根权限(用户非root用户)两种粗粒度的区别。

Linux内核自2.2版本起支持能力机制,它将权限划分为更加细粒度的操作能力,既可以作用在进程上,也可以作用在文件上。

例如,一个Web服务进程只需要绑定一个低于1024的端口的权限,并不需要完整的root权限。那么它只需要被授权net_bind_service能力即可。此外,还有很多其他的类似能力来避免进程获取root权限。

默认情况下,Docker启动的容器被严格限制只允许使用内核的一部分能力,包括chown、dac_override、fowner、kill、setgid、setuid、setpcap、net_bind_service、net_raw、sys_chroot、mknod、setfcap、audit_write,等等。

使用能力机制对加强Docker容器的安全性有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括ssh、cron、syslogd、硬件管理工具模块(例如负载模块)、网络配置工具,等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理,例如:

·ssh访问被宿主主机上的ssh服务来管理;

·cron通常应该作为用户进程执行,权限交给使用它服务的应用来处理;

·日志系统可由Docker或第三方服务管理;

·硬件管理无关紧要,容器中也就无需执行udevd以及类似服务;

·网络管理也都在主机上设置,除非特殊需求,容器不需要对网络进行配置。

从上面的例子可以看出,大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。包括:

·禁止任何文件挂载操作;

·禁止直接访问本地主机的套接字;

·禁止访问一些文件系统的操作,比如创建新的设备、修改文件属性等;

·禁止模块加载。

这样,就算攻击者在容器中取得了root权限,也不能获得本地主机的较高权限,能进行的破坏也有限。

不恰当地分配了内核能力,会导致容器内应用获取破坏本地系统的权限。例如,早期的Docker版本曾经不恰当的继承CAP_DAC_READ_SEARCH能力,导致容器内进程可以通过系统调用访问到本地系统的任意文件目录。

默认情况下,Docker采用白名单机制,禁用了必需的一些能力之外的其他权限,目前支持CAP_CHOWN、CAP_DAC_OVERRIDE、CAP_FSETID、CAP_FOWNER、CAP_MKNOD、CAP_NET_RAW、CAP_SETGID、CAP_SETUID、CAP_SETFCAP、CAP_SETPCAP、CAP_NET_BIND_SERVICE、CAP_SYS_CHROOT、CAP_KILL、CAP_AUDIT_WRITE等。

当然,用户也可以根据自身需求来为Docker容器启用额外的权限。