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