共计 4718 个字符,预计需要花费 12 分钟才能阅读完成。
自从我写完 Docker 安全系列的那两篇文章之后, 已经过去有一段时间了. 本文主要是来谈谈在那之后 Docker 的新的变化, 包含一些新增的特性的介绍.
调整 Capabilities
在上一篇文章中, 我提到过容器的隔离是基于 Linux 的 Capability 机制实现的.
Linux 的 Capability 机制允许你将超级用户相关的高级权限划分成为不同的小单元. 目前 Docker 容器默认只用到了以下的Capability.
CHOWN, DAC_OVERRIDE, FSETID, FOWNER, MKNOD, NET_RAW, SETGID, SETUID, SETFCAP, SETPCAP, NET_BIND_SERVICE, SYS_CHROOT, KILL, AUDIT_WRITE
有些情况下,你也许需要调整上面罗列的特性。比如你正在构建一个容器,你用它来执行 ntpd 或是 crony,为此它们要能够修改宿主的系统时间。由于不具备 CAP_SYS_TIME 特性,容器无法工作。为了应对这种情况,在 Docker 之前的版本中,容器必须以提权模式运行(使用 –privileged 选项),这会禁用所有安全机制。
在 Docker 的 1.3 版中,新添了 –cap-add 和 –cap-drop 选项。要让一个 ntpd 容器跑起来,你现在只要执行以下命令:
docker run -d --cap-add SYS_TIME ntpd
就可以将 SYS_TIME 特性添加到你的容器中。
再举个例子,如果你确定你的容器不会改变任何进程的 UID 和 GID,那完全可以将这些特性从你的容器中移除,这样会更安全:
docker run --cap-drop SETUID --cap-drop SETGID --cap-drop FOWNER Fedora /bin/sh
命令示例,用于查看启用的特性:
# pscap | grep 2912
运行结果示例:
5417 2912 root sh chown, dac_override, fsetid, kill, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
或者你可以先移除所有特性,然后再把一个添加回去:
docker run --cap-drop ALL --cap-add SYS_TIME ntpd /bin/sh
查看启用的特性:
# pscap | grep 2382
5417 2382 root sh sys_time
SELinux 标签调整
和特性类似,我们增加了在运行时调整 SELinux 标签的功能。
如果你看过图解 SELinux 一书,你就知道我们可以根据类别和 MCS/MLS 等级来区分进程。我们使用类别来保护宿主不受容器影响。而我们也能通过调整类别来控制容器的哪些网络端口能够输入和输出。目前我们所有运行着的容器都是 svirt_net_lxc_t。该类别允许所有网络端口都能处于监听状态,也允许所有网络端口都能对外发起连接。我们可以通过调整 SELinux 类别标签来增强容器的安全性。
针对常规 SELinux 和 Apache httpd,我们默认只允许 Apache 进程在 Apache 端口(http_port_t)上进行监听。
# sudo sepolicy network -t http_port_t
http_port_t: tcp: 80,81,443,488,8008,8009,8443,9000
与此同时,端口上的所有传出连接也被我们屏蔽了。这有助于我们对 Apache 进程的锁定,即使有黑客利用像 ShellShock 那样的安全漏洞破坏了应用程序,我们也能防止应用程序变成制造垃圾信息的机器人,同时阻止进程对其他系统发起攻击。就像《Hotel California》中所唱的那样:“你可以随时入住,但休想离开”。
然而,对于容器而言,如果你在一个容器中运行 Apache 服务程序,一旦应用程序被成功入侵,Apache 进程将会连接任何网络端口并成为制造垃圾信息的机器人,也可能会通过网络攻击其他宿主和容器。
为使用 SELinux 的容器创建新的策略类别相当容易。首先你需要创建一个 SELinux TE(Type Enforcement)文件:
# cat > docker_apache.te << _EOF
policy_module(docker_apache,1.0)
# This template interface creates the docker_apache_t type as a
# type which can be run as a docker container. The template
# gives the domain the least privileges required to run.
virt_sandbox_domain_template(docker_apache)
# I know that the apache daemon within the container will require
# some capabilities to run. Luckily I already have policy for
# Apache and I can query SELinux for the capabilities.
# sesearch -AC -s httpd_t -c capability
allow docker_apache_t self: capability {chown dac_override kill setgid setuid net_bind_service sys_chroot sys_nice sys_tty_config} ;
# These are the rules required to allow the container to listen
# to Apache ports on the network.
allow docker_apache_t self:tcp_socket create_stream_socket_perms;
allow docker_apache_t self:udp_socket create_socket_perms;
corenet_tcp_bind_all_nodes(docker_apache_t)
corenet_tcp_bind_http_port(docker_apache_t)
corenet_udp_bind_all_nodes(docker_apache_t)
corenet_udp_bind_http_port(docker_apache_t)
# Apache needs to resolve names against a DNS server
sysnet_dns_name_resolve(docker_apache_t)
# Permissive domains allow processes to not be blocked by SELinux
# While developing and testing your policy you probably want to
# run the container in permissive mode.
# You want to remove this rule, when you are confident in the
# policy.
permissive docker_apache_t;
_EOF
# make -f /usr/share/selinux/devel/Makefile docker_apache.pp
# semodule -i docker_apache.pp
现在,你可以使用新的类别运行容器:
# docker run -d –security-opt type:docker_apache_t httpd
这样就使得这个容器运行在比一般容器更严格的 SELinux 安全机制下。要注意的是,你也许要关注下审计日志,确认你的应用是否需要额外的 SELinux 放行规则。
你可以通过 audit2allow 命令添加这些规则,将这些规则追加到已有的 .te 文件中,然后重新编译安装。
# grep docker_apache_t /var/log/audit/audit.log | audit2allow >> docker_apache.te
# make -f /usr/share/selinux/devel/Makefile docker_apache.pp
# semodule -i docker_apache.pp
多级安全模式
目前,我们使用 MCS 分离以确保出容器并不允许交互或者与其他容器交互,除非他是通过网络。某些政府系统要求不同类型的政策 MLS(多级安全)。使用 MLS, 你标记基于他们将被看见的数据级别的处理。MLS 说,如果你的容器将被处理 Topsecret 数据,那么它应该运行在 Topsecret. 我们增加了选项到 Docker, 允许管理员设置的容器在特定的水平上运行。其中应该满足 MLS 系统的需求。
docker run -d –security-opt label:level:TopSecret –security
这将能使 Docker 容器两者都运行于交替类型,和水平上,并且会防止容器使用并不是在同一标签上的数据。通过鉴定,在这一点上这并没有消失,但是我们将愿意帮助第三方 MLS 用户建立解决方案。
调整 空间
在其他安全论坛上,我已经讨论了如何把命名空间 (namespaces) 可以被认为是一种安全机制,由于它会消除一个进程在系统(PID 命名空间)上看到其他进程的能力。网络空间 (network namespace) 可以消除从你的命名空间看到其他网络的能力。IPC(进程间通信)命名空间具有阻止 Container 调用其它容器 IPC 的能力。
Docker 现在已经有能力放松这些限制。你可以和容器共享主机命名空间:
–pid=host 让容器共享主机 pid 命名空间
–net=host 让容器共享主机网络命名空间
–ipc=host 让容器共享主机 ipc 命名空间
请注意,为了让上述的设置生效,让容器共享主机的 PID 或 IPC 命名空间, 我们还需要禁用 SELinux 权限分隔限制。
docker run -ti –pid=host –net=host –ipc=host rhel7 /bin/sh
你可能想要读有关这个主题的额外信息 Super Privileged Containers。
Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
在 Docker 中使用 MySQL http://www.linuxidc.com/Linux/2014-01/95354.htm
在 Ubuntu Trusty 14.04 (LTS) (64-bit)安装 Docker http://www.linuxidc.com/Linux/2014-10/108184.htm
Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
Ubuntu 14.04 安装 Docker http://www.linuxidc.com/linux/2014-08/105656.htm
阿里云 CentOS 6.5 模板上安装 Docker http://www.linuxidc.com/Linux/2014-11/109107.htm
Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里
英文原文:Tuning Docker with the newest security enhancements
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-06/119163.htm