Docker安全性(二)——带来了新的安全功能给Docker
本篇翻译自Daniel J Walsh的一篇开源文章:http://opensource.com/business/14/9/security-for-docker
作者的演讲视频:http://v.youku.com/v_show/id_XODQwNjUwNTIw.html
在这系列的第一篇Docker的安全性,我写了“容器中不包含”。在第二篇文章中,我将讨论为什么我们这样做并且我们正在对它做什么。
Docker,红帽和开源社区正在共同努力,使Docker更安全。当我看到安全容器中,我期待防止容器内的进程主机,我也期待来保护彼此的容器。与Docker,我们使用的是分
层的安全方法,这是“结合多个缓解安全控制,以保护资源和数据的做法。”
基本上,我们希望把尽可能多的安全屏障,尽可能防止爆发。如果特权进程可以突破的一个容纳机制,我们希望下一个阻止他们。与Docker,我们要采取的Linux尽可能多的
安全机制的优势。
幸运的是,红帽企业版Linux(RHEL)7,我们得到了大量的安全功能。
文件系统保护
只读挂载点
一些Linux内核文件系统必须被安装在容器中的环境或过程将无法运行。幸运的是,大多数这些文件系统可被安装为“只读”。大多数应用程序不应该需要写入这些文件系统。
Docker挂载这些文件系统放入容器中的“只读”的挂载点。
. /sys
. /proc/sys
. /proc/sysrq-trigger
. /proc/irq
. /proc/bus
通过安装这些文件系统为只读,特权容器进程不能给他们写信。它们不能影响主机系统。当然,我们也阻挡特权容器进程的能力,重新装入文件系统的读/写。我们阻止安装
任何文件系统的所有内部容器的能力。我将解释我们如何阻止挂载,当我们到达的能力。
写入时复制的文件系统
Docker使用写入时复制文件系统。这意味着容器中可以使用相同的文件系统映像为基准,为容器。当容器的内容写入到图像,它被写入到一个容器特定的文件系统。这样可
以防止一个容器无法看到,即使他们写信给同一个文件系统映像另一个容器的变化。同样重要的是,一个容器不能改变图像内容,以实现该进程中的另一容器中。
能力
Linux的能力是在他们的主页很好地解释了:
对于执行权限检查的目的,传统的UNIX实现区分两类进程:特权进程(其有效用户ID为0,被称为超级用户或root)和非特权进程(其有效的UID不为零)。特权进程绕过所
有内核权限检查,同时非特权进程受到完全权限基于过程的凭证检查(通常是:有效的UID,有效的GID,并补充组列表)。内核2.2开始,Linux的划分与传统的超级用户相
关的成不同的单元,被称为功能,可以独立启用和禁用的权限。能力是每个线程属性。
删除功能可能会导致应用程序突破,这意味着我们有功能性,可用性和安全性之间的平衡在Docker。下面是功能,Docker使用当前列表:CHOWN,dac_override,fowner,杀
,setgid的,setuid的,setpcap,net_bind_service,net_raw,sys_chroot,mknod的,setfcap和audit_write。
它是不断争论来回哪些功能应该被允许或默认拒绝。Docker允许用户操控默认列表与Docker运行命令行选项。
删除功能
Docker中删除几个这样的功能,包括以下内容:
CAP_SETPCAP修改过程的能力
CAP_SYS_MODULE插入/删除内核模块
CAP_SYS_RAWIO修改内核内存
CAP_SYS_PACCT配置进程记帐
CAP_SYS_NICE修改优先流程
CAP_SYS_RESOURCE覆盖资源限制
CAP_SYS_TIME修改系统时钟
CAP_SYS_TTY_CONFIG配置tty设备
CAP_AUDIT_WRITE写审计日志
CAP_AUDIT_CONTROL配置审计子系统
CAP_MAC_OVERRIDE忽略内核MAC政策
CAP_MAC_ADMIN配置MAC配置
CAP_SYSLOG修改内核的printk行为
CAP_NET_ADMIN配置网络
CAP_SYS_ADMIN捕获所有
让我们来看看在表中更接近在过去几个。通过删除CAP_NET_ADMIN一个容器,容器进程不能修改系统网络,这意味着分配IP地址的网络设备,建立路由规则,修改iptables的
。
所有的网络是由容器设置的开始前的Docker守护进程。可以从容器以外,但尚未内部管理容器中网络接口。
CAP_SYS_ADMIN是特殊的能力。我相信这是内核包罗万象的能力。当内核工程师设计新的功能到内核中,他们应该选择最匹配的是什么功能允许的能力。或者,他们应该创建
一个新的能力。问题是,原本有32只的能力插槽可用。如有疑问内核工程师也只是回落到使用CAP_SYS_ADMIN。这是事物的列表,根据CAP_SYS_ADMIN所允
许:/usr/include/linux/capability。
让安全注意键配置 允许随机设备的管理
允许检查和磁盘配额的配置 允许设置的域名
允许设置主机名 允许调用的bdflush()
允许装载()和umount(),建立新的SMB连接 允许一些autofs的root的ioctl
让nfsservctl 允许VM86_REQUEST_IRQ
允许读取字母/写PCI配置 允许irix_prctl在MIPS(setstacksize)
让冲洗的m68k的(sys_cacheflush)的所有缓存 允许删除信号灯
用来代替CAP_CHOWN为“CHOWN”IPC消息队列,信号量和共享内存 允许共享内存段锁定/解锁
允许在/套接字凭据关 允许伪造的PID通过转掉期
允许设置预读和冲洗缓冲块设备上 允许设置几何软盘驱动器
允许开/关在XD驱动 允许MD设备施用转动的DMA(主要是上述情况,但一些额外的ioctl)
允许访问到NVRAM设备 允许apm_bios的管理,串行和BTTV(TV)设备
允许ISDN CAPI支持驱动程序制造商的命令 允许读取PCI配置空间非标准化的部分
允许在SBPCD驱动DDI调试的ioctl 允许设置串口
允许发送原始QIC-117命令 允许启用/禁用标记排队的SCSI控制器和发送任意的SCSI命令
允许设置加密密钥对回文件系统 允许设置区回收政策
允许调整IDE驱动程序
两个最重要的特性,从容器中取出CAP_SYS_ADMIN确实是停止从执行安装系统调用或修改名称空间的进程。你不想让你的容器进程挂载随机文件系统或重新安装只读文件系统
。
--cap-add --cap-drop
Docker来说也有一个特点,你可以调整你的容器需要的功能。这意味着你可以删除功能的容器不需要。例如,如果你的容器不需要setuid和setgid可以删除此访问执行:
docker run --cap-drop setuid --cap-drop setgid -ti rhel7 /bin/sh
你甚至可以删除所有功能或添加他们都:
docker run --cap-add all --cap-drop sys-admin -ti rhel7 /bin/sh
此命令会增加,除了SYS-admin的所有功能。
命名空间
一些Docker设置为进程的命名空间来运行也提供了一些安全。
PID命名空间
该PID命名空间隐藏的是,除了那些在当前容器中运行的系统上运行的所有进程。如果你不能看到其他进程,这使得它更难攻击的过程。你不能轻易strace的或ptrace的他们
。而且,杀进程的命名空间的PID1会自动容器,这意味着管理员可以很容易地阻止容器内杀死所有的进程。
网络空间
网络名称空间可用于实现安全性。管理员可以设置在容器的网络路由规则和iptables使得容器内的进程,只能使用特定的网络。我能想象的人设置了三个过滤容器:
?一个只允许在公共互联网上沟通。
?一个只允许专用Intranet通信。
?一个连接到其他两个集装箱,邮件中继来回容器中之间,但阻止不适当的内容。
cgroup中
一种类型的系统上的攻击可以被描述为一个拒绝服务。这是一个过程的过程或组使用的所有资源的系统上,以防止其他进程的执行。 cgroup中可以使用的控制资源的任何
Docker容器可以使用的量,以减轻此。例如,CPU cgroup中可以设置这样,管理员仍然可以登录到一个系统,其中一个Docker容器试图主宰CPU和杀死它。新的cgroup正在研
发中,以帮助控制过程,使用过多的资源,如打开的文件或进程数。Docker将这些cgroup的优势,因为他们成为可用。
设备的cgroup
Docker采用特殊的cgroup,使您可以指定哪些设备节点可以在容器内使用的优势。它的块的处理,从创建和使用可用于攻击的主机设备的节点。
设备节点允许进程改变内核的配置。控制该设备的节点可用controlls什么一个过程是能够做到在主机系统上。
下面的设备节点都在容器中默认创建。
/dev/console,/dev/null,/dev/zero,/dev/full,/dev/tty*,/dev/urandom,/dev/random,/dev/fuse
该Docker图像也安装为nodev,这意味着,即使一个设备节点被图像中的预先创建的,它不能被用于由进程容器内进行通话的内核。
注意:设备节点的创建也可以阻止通过除去CAP_MKNOD能力。Docker已经选择不这样做,以允许进程创建一组设备节点的限制。在期货部分,我将提--opt命令行选项,我想
用它来消除这种能力。
AppArmor
AppArmor中可以Docker容器中上支持它的系统。但我用RHEL和Fedora,不支持AppArmor的,所以你必须在其他地方进行调查这一安全机制。 (此外,我使用SELinux的你很
清楚。)
SELinux
首先,一些关于SELinux的:
?SELinux的是一个标签制度
?每个进程都有一个LABEL
?每个文件,目录和系统对象有一个LABEL
?标记过程和标记对象之间的策略规则控制访问
?内核强制执行的规则
SELinux的实现了强制访问控制系统。这意味着一个对象的业主无法控制或自由裁量权的访问对象。内核强制执行强制访问控制。我描述了如何SELinux的执法工作在视觉引
导SELinux策略执行(以及随后,SELinux的图画书)。
我会用一些从该文章中的漫画来描述我们如何使用SELinux的控制允许Docker容器进程的访问。我们使用两种类型的SELinux执法的Docker容器。
执法型
类型强制保护从进程主机在容器内
我们使用运行Docker容器的默认类型是svirt_lxc_net_t。运行所有容器进程与这种类型。
在容器内的所有内容都标有svirt_sandbox_file_t类型。
svirt_lxc_net_t被允许管理标记svirt_sandbox_file_t任何内容。
svirt_lxc_net_t也能读/在/ usr执行大多数标签的主机上。
流程运行witht他svirt_lxc_net_t都不允许打开/写入系统上的任何其他标签。它不允许读取/ var,/root,/家庭等任何默认标签
基本上,我们希望允许进程读取/执行系统的内容,但我们希望不是允许它使用任何“数据”在系统上,除非它是在容器中,默认情况下。
问题
如果所有的容器进程都运行与svirt_lxc_net_t,所有的内容都标有svirt_sandbox_file_t,不会容器进程被允许在攻击其他容器中拥有其他容器和内容正在运行的进程?
这是多类别安全执法进来,如下所述。
另一种类型
请注意,我们在类型标签使用的“网”。我们这是用来表示这种类型的可以使用完整的网络。我工作的一个补丁,以Docker,以允许用户指定替代类型的用于容器。例如,你
可以指定喜欢的东西:
docker run -ti --security-opt label:type:lxc_nonet_t rhel7 /bin/sh
然后在容器内的进程将不会被允许使用任何网络端口。同样,我们可以很容易地编写一个Apache的政策,将只允许在容器上的Apache端口上侦听,但不允许连接出任何端口
。使用这种类型的政策,你可以防止你的容器成为垃圾邮件的僵尸,即使它被破解,而黑客获得容器内的Apache进程的控制权。
多类别安全执法
多类别安全(MCS)保护其他容器中一个容器
多类别安全性是基于多级安全(MLS)。 MCS需要SELinux的标签MLS场的最后一个组件的优势。的MCS执行保护彼此容器。当容器被推出Docker守护选择一个随机的MCS标签,
例如S0:C1,C2,分配给该容器。Docker守护标签的所有与本MCS标签在容器中的内容。当守护程序启动容器过程中,它告诉内核来标记具有相同MCS标签的过程。内核只允
许容器进程读/只要处理的MCS标签文件系统内容的MCS标签匹配写自己的内容。从读/写内容的内核模块容器进程标有不同的MCS标签。
防止了黑客攻击容器进程攻击不同的容器。Docker守护进程负责保证没有容器使用相同的MCS标签。这是一个视频我做了展示会发生什么,如果一个OpenShift容器能够获得
root的系统。相同的基本策略用于限制Docker容器。
正如我上面提到的,我工作的一个补丁Docker,让不同的SELinux内容的规范。我将允许管理员指定容器的标签。
docker run --ti --rm --label-opt level:TopSecret rhel7 /bin/sh
这让人们开始在多级安全(MLS)的环境中运行容器中,这可以为那些需要MLS环境是有益的
SELinux的陷阱
文件系统支持
目前,SELinux的将只与设备映射器后端的工作。 SELinux的不与BTFS工作。 BTRFS不支持背景下挂载标签的是,防止了SELinux的重新标记的所有内容,当容器,通过mount
命令启动。内核工程师们正在为这个和潜在Overlayfs一个修复,如果它被合并到容器中。
卷挂载
因为类型增强只允许容器进程中读取容器中/写svirt_sandbox_file_t,卷安装可能是一个问题。卷挂载是一个目录只是一个绑定挂载放入容器内,那里的目录的标签不改变
。为了使容器进程读/写的内容,你需要改变的类型标签svirt_sandbox_file_t。
卷挂载在/var/lib/myapp
chcon -Rt svirt_sandbox_file_t /var/lib/myapp
我写了一个补丁Docker尚未合并上游来自动设置这些标签。随着补丁,你将Docker重新标记卷到任何一个自有品牌“Z”或共享的标签,“Z”自动。
docker run -v /var/lib/myapp:/var/lib/myapp:Z ...
docker run -v /var/lib/myapp:/var/lib/myapp:z ...
希望这将很快得到合并。
底线
我们已经增加了很多安全机制,使Docker容器中不是运行在裸机上应用程序更安全,但你仍然需要保持良好的安全做法,因为我对这个问题的第一篇文章中谈到。
?仅运行来自可靠来源应用程序
?一个企业质量主机上运行的应用程序
?定期安装更新
?删除的权限尽快
?非root尽可能运行
?注意你的日志
?setenforce1
我对Docker的安全下一篇文章将介绍我们正在努力的将是什么,以进一步保护Docker容器。
本篇翻译自Daniel J Walsh的一篇开源文章:http://opensource.com/business/14/9/security-for-docker