原创文章,转载请务必将下面这段话置于文章开头处。 本文转发自:字母哥博客,原文链接 http://www.zimug.com/463.html
Docker容器的的本质是宿主机上的进程.通过namespace实现资源隔离,cgroups实现资源的限制,通过写时复制的机制完成高效的文件操作.docker实现的核心技术-namespace 和 cgroups,其实并不是什么新技术,准确的说namespace 和 cgroups是linux的相关技术.docker对这种技术进行了封装,提高可操作性。
容器经常拿来和虚拟机进行对比,容器的好处就不多说了!主要说说:容器的缺点-隔离性低导致的安全性较低. 通常来说,容器相比虚拟机还是不够安全的..
这就要从虚拟机和容器的底层实现机制来对比,
namespace | 隔离内容 | 内核版本 |
---|---|---|
UTS | 主机名与域名 | Linux 2.6.19 |
IPC | 信号量,消息队列和共享内存 | Linux 2.6.19 |
PID | 进程编号 | Linux 2.6.24 |
Network | 网络设备,网络栈,端口 | 始于Linux 2.6.24 完成于 Linux 2.6.29 |
Mount | 文件挂载 | Linux 2.4.19 |
User | 用户用户组 | 始于 Linux 2.6.23 完成于 Linux 3.8 |
为提升安全性,您的linux内核请升级版本大于3.8 docker1.10开始支持User namespace,但不是默认开启的.《Docker 安全之用户资源隔离》
这6种资源隔离看上去比较完备,但是仍然有很多的资源没有隔离,比如:
这将宿主机的资源暴露给了容器的访问者,会导致安全问题!
同时笔者认为,docker容器安全的痛点也仅限于互联网公有云环境下。对于企业内部私有云也算不上痛点,通过对docker进行安全加固可以达到生产环境的安全级别的要求!欢迎批判!,第4章节,我们将看看如何提升docker容器安全!
容器的资源隔离程度相对虚拟机较低,与宿主机共享内核.导致容器的安全性低.那么是不是说容器相对于虚拟机,在安全性上完全没有自己的优势呢?
笔者认为,还是有的:
User namespace是从docker1.10开始被支持,并且不是默认开启的.
docker 使用namespace进行资源隔离,其中一种是user namespace.user namespace主要隔离了安全相关的标识符和属性,包括用户ID,用户组Id,root目录,key(密钥)以及特殊权限.
默认的情况下,docker容器使用的root用户和宿主机的root用户是同一个用户,尽管可以限制容器内root用户的权限(capability),但本质上仍然和宿主机root用户是同一个用户.
有了user namespace之后,我们就可以将宿主机上的普通用户映射为容器的root用户,这样容器中的实际用户为普通用户权限,可以将容器的安全程度提高一个等级!
关于具体的实现步骤,请查看我的这篇文章: 《Docker 安全之用户资源隔离》
默认情况下,运行docker命令需要访问本地的Unix Socket.也可以通过HTTP的方式完成远程访问.
如果你需要以安全的方式在网络中访问docker,最好使用TLS,指定tlsverify参数,设置tlscacert参数指向一个可信的CA证书.在这种方式下,只有经过CA权限验证通过的客户端才能访问docker deamon.
具体内容请访问官网:《Protect the Docker daemon socket》
我们可以将容器的服务端口分为两种
笔者认为安全的组网方式就是:尽量不使用端口映射的方式将容器端口映射到宿主机.端口暴露的越少,安全性就越高.
什么是尽量?如何尽量?
我采用overlay的网络,或者叫应用层网络,覆盖网络,但这绝不是唯一的方法. docker 1.9为我们提供了官方的跨宿主机组网方式overlay(还有其他的网络工具也是这种方式).容器应用的网络构建于物理网络之上,在逻辑上又独立于物理网络.
举个例子:ZF的各个部门是都一个宿主机,容器(职能人员)之间可以跨宿主机沟通.部门级别之间的沟通是物理网络,各部门的职能人员之间的沟通是应用网络. 最后形成的沟通结论,对外发布,交给新闻发言人,这个新闻发言人是物理网络对外服务的接口.
同样: 对于第一种直接为用户提供服务的端口,可以采用端口映射的方式映射到宿主机,他就是发言人. 对于第二种端口的消息,应用网络内部处理,不对外发布。
实现方式可以参考:《基于consul的Docker-overlay跨多宿主机容器网络》
什么是capability?
简单地说,就是执行调用操作的权限.Linux将超级用户的权限进行分组,每一组代表了所能执行的系统调用操作. 如果是root用户,剥夺它的某些capability,那么它将无法调用对应的系统操作.如果是普通用户,对它赋予某些capability,它也可以完成某些超级用户才能做的系统调用. capability为系统的权限管理,提供了更加细粒度的权限划分.
容器默认拥有的capability(能力)包括:
查看容器的capability(能力) 通过docker ps 和docker inspect 获得容器进程的id,查看容器的默认能力
$ pscap |grep 165536
1411 19337 165536 top chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
移除容器的capability(能力) 使用--cap-drop移除能力,运行容器
docker run -it --cap-drop SETGID --cap-drop SETUID ubuntu:14.04 top
通过docker ps 和docker inspect 获得容器进程的id,查看容器的现有能力.setuid和setgid的能力被移除
1411 19803 165536 top chown, dac_override, fowner, fsetid, kill, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
为容器新增capability(能力) 使用--cap-add增加能力,运行容器
docker run -it --cap-add SYS_TIME ubuntu:14.04 top
通过docker ps 和docker inspect 获得容器进程的id,查看容器的现有能力.新增了sys_time能力
1411 20101 165536 top chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, sys_time, mknod, audit_write, setfcap
Linux都有哪些capability(能力)?
capabilities - overview of Linux capabilities
Docker 可以设置容器的文件系统为只读模式.这样可以禁止,脚本注入方式的攻击,因为脚本无法保存.
$ docker run --rm -ti --read-only ubuntu bash
注意:此方法不能与user namespace 同时使用