如何提升docker容器安全性

时间:2022-07-25
本文章向大家介绍如何提升docker容器安全性,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

向您推荐

原创文章,转载请务必将下面这段话置于文章开头处。 本文转发自:字母哥博客,原文链接 http://www.zimug.com/463.html

Dcoker入门与实践系列文章

1.Docker的核心原理

Docker容器的的本质是宿主机上的进程.通过namespace实现资源隔离,cgroups实现资源的限制,通过写时复制的机制完成高效的文件操作.docker实现的核心技术-namespace 和 cgroups,其实并不是什么新技术,准确的说namespace 和 cgroups是linux的相关技术.docker对这种技术进行了封装,提高可操作性。

2.容器安全的痛点

容器经常拿来和虚拟机进行对比,容器的好处就不多说了!主要说说:容器的缺点-隔离性低导致的安全性较低. 通常来说,容器相比虚拟机还是不够安全的..

2.1为什么容器不够安全

这就要从虚拟机和容器的底层实现机制来对比,

  • 虚拟机在hypervisor的基础上构建虚拟操作系统,有自己的操作系统内核.容器与宿主机是共用同一个内核的.
  • 虚拟机也不是绝对安全的.找到HyperVisor的弱点,攻克SELinux控制,就可以攻破虚拟机,染指宿主机。但这是非常难的.
  • 容器的隔离技术使用的是namespace,但namesapce的资源隔离仅限于以下6个方面

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种资源隔离看上去比较完备,但是仍然有很多的资源没有隔离,比如:

  • SELinux
  • Cgroups
  • file systems under /sys
  • /proc/sys, /proc/sysrq-trigger, /proc/irq, /proc/bus
  • /dev/mem
  • /dev/sd* file system devices

这将宿主机的资源暴露给了容器的访问者,会导致安全问题!

同时笔者认为,docker容器安全的痛点也仅限于互联网公有云环境下。对于企业内部私有云也算不上痛点,通过对docker进行安全加固可以达到生产环境的安全级别的要求!欢迎批判!,第4章节,我们将看看如何提升docker容器安全!

3.docker容器安全也有自己的优势

容器的资源隔离程度相对虚拟机较低,与宿主机共享内核.导致容器的安全性低.那么是不是说容器相对于虚拟机,在安全性上完全没有自己的优势呢?

笔者认为,还是有的:

  1. 可以禁止SSH访问,防止很多正面攻击
  2. 容器暴露的端口有限,容器的本质是宿主机的进程,他只需要暴露非常有限的端口来提供服务.
  3. 可以利用容器云控制容器的生命周期,使其在不影响服务的情况下,尽可能的短命.攻击短生命周期的容器意义并不大.
  4. 容器的文件系统分层,镜像层是只读的,只有容器层可写.容器层文件的生命周期与容器相同(不是数据卷).

4.如何提升容器安全性

4.1 使用User namespace

User namespace是从docker1.10开始被支持,并且不是默认开启的.

docker 使用namespace进行资源隔离,其中一种是user namespace.user namespace主要隔离了安全相关的标识符和属性,包括用户ID,用户组Id,root目录,key(密钥)以及特殊权限.

默认的情况下,docker容器使用的root用户和宿主机的root用户是同一个用户,尽管可以限制容器内root用户的权限(capability),但本质上仍然和宿主机root用户是同一个用户.

有了user namespace之后,我们就可以将宿主机上的普通用户映射为容器的root用户,这样容器中的实际用户为普通用户权限,可以将容器的安全程度提高一个等级!

关于具体的实现步骤,请查看我的这篇文章: 《Docker 安全之用户资源隔离》

4.2 使用OpenSSL保护docker daemon

默认情况下,运行docker命令需要访问本地的Unix Socket.也可以通过HTTP的方式完成远程访问.

如果你需要以安全的方式在网络中访问docker,最好使用TLS,指定tlsverify参数,设置tlscacert参数指向一个可信的CA证书.在这种方式下,只有经过CA权限验证通过的客户端才能访问docker deamon.

具体内容请访问官网:《Protect the Docker daemon socket》

4.3 安全的组网方式

我们可以将容器的服务端口分为两种

  • 第一种:直接为用户提供服务的端口,如:web应用常用8080
  • 第二种:为其他应用的提供服务的端口.

笔者认为安全的组网方式就是:尽量不使用端口映射的方式将容器端口映射到宿主机.端口暴露的越少,安全性就越高.

什么是尽量?如何尽量?

我采用overlay的网络,或者叫应用层网络,覆盖网络,但这绝不是唯一的方法. docker 1.9为我们提供了官方的跨宿主机组网方式overlay(还有其他的网络工具也是这种方式).容器应用的网络构建于物理网络之上,在逻辑上又独立于物理网络.

举个例子:ZF的各个部门是都一个宿主机,容器(职能人员)之间可以跨宿主机沟通.部门级别之间的沟通是物理网络,各部门的职能人员之间的沟通是应用网络. 最后形成的沟通结论,对外发布,交给新闻发言人,这个新闻发言人是物理网络对外服务的接口.

同样: 对于第一种直接为用户提供服务的端口,可以采用端口映射的方式映射到宿主机,他就是发言人. 对于第二种端口的消息,应用网络内部处理,不对外发布。

实现方式可以参考:《基于consul的Docker-overlay跨多宿主机容器网络》

4.4 限制docker容器的capability

什么是capability?

简单地说,就是执行调用操作的权限.Linux将超级用户的权限进行分组,每一组代表了所能执行的系统调用操作. 如果是root用户,剥夺它的某些capability,那么它将无法调用对应的系统操作.如果是普通用户,对它赋予某些capability,它也可以完成某些超级用户才能做的系统调用. capability为系统的权限管理,提供了更加细粒度的权限划分.

容器默认拥有的capability(能力)包括:

  • CHOWN: 更改文件UID和GID的能力
  • DAC_OVERRIDE:忽略文件的读,写,执行访问权限的检查的能力
  • FOWNER:越过可执行文件的拥有者权限检查,执行操作的能力
  • FSETID:文件修改后保留setuid/setgid标志位
  • SETGID:改变进程组id的能力
  • SETUID:改变进程用户ID的能力
  • SETFCAP:向security.capability写入能力属性的能力
  • NET_RAW:创建RAW和PACKET套接字的能力
  • MKNOD:使用mknod创建特殊文件的能力
  • SYS_REBOOT:允许使用reboot或者kexec_load.kexec_load功能是加载新的内核作为reboot重新启动所需的内核
  • SYS_CHROOT:使用chroot的能力
  • KILL:越过权限检查,发送信号的能力
  • NET_BIND_SERVICE:绑定常用端口的能力(端口号小于1024)
  • AUDIT_WRITE:允许审计日志写入的能力

查看容器的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

4.5 文件系统只读保护

Docker 可以设置容器的文件系统为只读模式.这样可以禁止,脚本注入方式的攻击,因为脚本无法保存.

$ docker run --rm -ti --read-only ubuntu bash

注意:此方法不能与user namespace 同时使用

……未完待续,欢迎持续关注我的博客!