基于PaaS云平台的容器安全研究
2021-07-07柯研
柯研
(工业和信息化部电子第五研究所,广东 广州 511370)
0 引言
容器正在改变应用程序的运行、设计、开发和部署方式。其提供了一种简单的方法,可以打包应用程序,并从开发到测试系统无缝地传输到生产系统。其还有助于确保不同环境(包括物理服务器、虚拟机、公共或私有云)之间的一致性。
随着容器的普及,许多企业在选择时都会考虑基于容器的PaaS云平台。从安全的角度来看,容器提供了一些优势,但它们也面临一些自身的安全挑战。当使用基于容器的PaaS云平台时,安全性问题尤为重要[1]。
1 机制
通常,部署到PaaS云平台的应用程序的每个实例都在自己独立的环境中运行,即容器。这个容器使用操作系统特性和部署PaaS云平台的虚拟和物理基础结构的特性隔离进程、内存和文件系统[2]。
PaaS云平台通过将内核资源划分成不同命名空间实现容器隔离。隔离的级别设置为防止同一主机的多个容器检测到对方。每个容器包括一个私人的根文件系统,包括进程ID、名称空间、网络的命名空间、命名空间和安装。
PaaS云平台使用OverlayFS以如下方式创建容器文件系统。
a)只读基本文件系统
该文件系统具有最低限度的操作系统包集和所有容器所共有的特定于安全性的修改。容器可以共享相同的只读基本文件系统,因为所有的写入都应用于读写层。
b)一个特定于容器的读写层
该层每个容器是唯一的,其大小受XFS项目配额的限制。配额防止读写层溢出到未分配的空间中。
资源控制使用Linux控件组进行管理。将每个容器与其自己的cgroup或作业对象关联,限制了容器可能使用的内存量。与其他容器的相对CPU份额相比,Linux cgroup还要求容器使用公平的CPU份额。
每个容器都放在自己的cgroup中。cgroup使每个容器相对于其他容器使用公平的CPU份额。这防止了主机VM上的过度订阅,即其中一个或多个容器占用CPU,而没有为其他容器留下计算资源。
cgroup基于共享的方式分配CPU时间。CPU共享并不是CPU总使用率的直接百分比,而是在给定的时间窗口中,相对于其他容器持有的共享。可以在cgroup中总体分配的CPU总量是主机VM中可能运行的其他进程留下的。
一般来说,cgroup提供了两种限制CPU使用的可能性:CPU核绑定和CPU带宽,后者在PaaS云平台中使用。
a)CPU核绑定
它由将cgroup绑定到特定CPU核组成。cgroup可以消耗的CPU周期的实际数量仅限于绑定CPU核上可用的部分。
b)CPU带宽
使用进程调度程序设置cgroup的权重。进程调度器根据每个cgroup所持有的共享,相对于其他组所持有的共享在cgroup之间划分可用的CPU周期。
例如:考虑两个cgroup,一个持有两个共享份额,另一个持有4个。假设进程调度程序可以管理60个CPU周期,第一个拥有两个共享份额的cgroup将获得这些可用CPU周期的1/3,因为它持有整个共享份额的1/3。同样,第二个cgroup将获得40个周期,因为它持有2/3的共享份额。
根据可用CPU总功率的百分比计算CPU使用率是相当复杂的,并且随着各种容器的CPU需求的波动而定期执行。具体来说,cgroup获得的CPU周期百分比可以通过将它持有的cpu.share除以当前正在执行CPU活动的所有cgroup的cpu.share之和来计算:
process_cpu_share_percent=cpu.shares/sum_cpu_shares*100
在PaaS云平台中,cgroup共享介于10~1 024之间,而1 024是默认的。cgroup获取的实际共享量可以从cgroup配置的cpu.share文件中读取,在/sys/fs/cgroup/cpu的容器中可用。
分配给应用程序cgroup的共享量取决于应用程序声明在清单中需要的内存量。PaaS云平台将分配的共享数量与内存量成线性关系,一个应用实例请求8G内存获得1 024个共享的上限。
process_cpu.shares=max((application_memory/8),1024)
考虑3个进程P1、P2、P3,cpu.shares值分别为5、20及30。
P1是活动的,而P2和P3不需要CPU。因此,P1可以使用整个CPU。当P2加入并正在执行一些实际工作(例如请求传入)时,将按以下方式计算P1和P2之间的CPU份额:
1)P1->5/(5+20)=0.2=20%
2)P2->20/(5+20)=0.8=80%
3)P3(idle)
在某个时候,进程P3也加入进来。然后再重新计算CPU份额:
1)P1->5/(5+20+30)=0.090 9≈~9%
2)P2->20/(5+20+30)=0.363≈~36%
3)P3->30/(5+20+30)=0.545≈~55%
如果P1变为空闲,则P2和P3之间重新计算CPU份额:
1)P1(idle)
2)P2->20/(20+30)=0.4=40%
3)P3->30/(20+30)=0.6=60%
如果P3完成或变为空闲,则P2可以消耗所有CPU时钟周期,因为将执行另一次重新计算。
cgroup共享份额是进程可以获得的最小保证CPU共享份额。只有当同一主机上的进程竞争资源时,此限制才会生效。
2 PaaS云平台的入站和出站流量
2.1 网络概述
主机VM只有一个IP地址。如果按照建议使用VLAN上的集群配置部署,那么所有通信量都会通过以下级别的网络地址转换,如图1所示。
图1 PaaS云平台的入站和出站流量
1)入站请求从负载均衡器通过路由器流向主机单元,然后流入应用程序容器。路由器确定哪个应用程序实例接收每个请求。
2)出站流量从应用程序容器流到单元格,然后流到单元格虚拟网络接口上的网关。此网关可能是对外部网络的NAT,取决于IaaS平台。
2.2 网络流量规则
管理员配置规则以控制容器网络通信量。这就是容器如何在PaaS云平台之外发送流量,并从外部(Internet)接收流量。这些规则可以阻止外部网络和内部组件之间的系统访问,并确定应用程序是否可以通过虚拟网络接口建立连接。
管理员在两个级别配置这些规则:
1)应用程序安全组(ASGs)在容器级别应用网络流量规则。
2)容器到容器的网络策略决定了应用程序到应用程序的通信。在PaaS云平台内部,应用程序可以直接相互通信,但是容器与外部PaaS云平台是隔离的。
3 容器安全
PaaS云平台通过以下措施确保容器的安全:
1)默认情况下在非特权容器中运行应用程序实例;
2)通过限制功能和访问权限来加固容器;
3)只允许从应用程序容器到公共地址的出站连接,这是默认设置,管理员可以通过配置ASGs来更改此行为。
3.1 容器类型
容器类型有两种:非特权容器类型和特权容器类型。通常,PaaS云平台默认在非特权容器中运行所有应用程序实例和任务。此措施通过消除容器内root权限的威胁来提高安全性[3]。
尽管现在默认情况下所有应用程序实例和任务都在非特权容器中运行,但管理员可以通过自定义其部署清单和重新部署来覆盖这些默认值。
3.2 加固
PaaS云平台以下列方式减轻了容器突破和拒绝服务攻击。
a)使用完整的Linux名称空间(IPC、Network、Mount、PID、User和UTS)来提供在同一主机上运行的容器之间的隔离。
b)在非特权容器中,PaaS云平台将容器用户名称空间中的UID/GID 0(Root)映射到主机上的另一个UID/GID,以防止应用程序突破容器的情况在主机上继承UID/GID 0。
1)对所有容器使用相同的UID/GID。
2)将除UID 0以外的所有UID映射到自己,将容器命名空间中的UID 0映射到容器名称空间之外的MAX_UID-1。
3)容器root用户不授予主机root权限。
c)将/proc和/sys以只读权限挂载到容器内。
d)不允许非特权用户和非特权容器中的所有用户访问dmesg。
e)建立一个特定于容器的OverlayFS挂载。将根文件系统移动到此OverlayFS中,以便将容器与主机系统的文件系统隔离开来。
f)不调用容器文件系统中的任何二进制或脚本,以消除根文件系统中对脚本和二进制文件的依赖。
g)通过绑定挂载或其他方法避免容器中的二进制文件加载另外的二进制文件,而是当它需要在容器中运行二进制时,通过从/proc/self/exe读取它来重新执行相同的二进制。
h)为网络通信的每个容器建立虚拟以太网对。
1)该对中的一个接口位于容器的网络命名空间内,是容器内唯一可访问的非环回接口。
2)另一个接口保留在主机网络命名空间中,并桥接到容器端接口。
3)出口白名单规则根据管理员配置的应用程序安全组(ASGs)应用于这些接口。
4)首包日志功能也可以应用于TCP白名单规则上。
5)在主机上建立DNAT规则,使流量从主机接口进入容器端接口上的白名单端口。
i)使用特定于容器的具有指定磁盘配额容量的XFS配额以应用磁盘配额。
j)通过内存cgroup限制总内存使用配额,如果某个容器的内存使用量超过配额则销毁该容器。
k)通过cpu.share控件组对容器中的进程的CPU使用量施加合理使用限制。
l)使用cgroup限制对设备的访问,但将下列安全设备节点加入白名单[4]:
1)/dev/full
2)/dev/fuse
3)/dev/null
4)/dev/ptmx
5)/dev/pts/*
6)/dev/random
7)/dev/tty
8)/dev/tty0
9)/dev/tty1
10)/dev/urandom
11)/dev/zero
12)/dev/tap
13)/dev/tun
m)删除所有容器进程的下列Linux功能。每次丢弃的功能都限制root用户可以执行的操作[5]。
1)CAP_DAC_READ_SEARCH
2)CAP_LINUX_IMMUTABLE
3)CAP_NET_BROADCAST
4)CAP_NET_ADMIN
5)CAP_IPC_LOCK
6)CAP_IPC_OWNER
7)CAP_SYS_MODULE
8)CAP_SYS_RAWIO
9)CAP_SYS_PTRACE
10)CAP_SYS_PACCT
11)CAP_SYS_BOOT
12)CAP_SYS_NICE
13)CAP_SYS_RESOURCE
14)CAP_SYS_TIME
15)CAP_SYS_TTY_CONFIG
16)CAP_LEASE
17)CAP_AUDIT_CONTROL
18)CAP_MAC_OVERRIDE
19)CAP_MAC_ADMIN
20)CAP_SYSLOG
21)CAP_WAKE_ALARM
22)CAP_BLOCK_SUSPEND
23)CAP_SYS_ADMIN(针对非特权容器)
4 结束语
在使用基于容器的PaaS云平台时,安全性问题尤为重要。因此,本文介绍了PaaS云平台的容器机制,描述了PaaS云平台保护Linux上承载应用实例的容器的方法,概述了容器隔离和容器网络,并描述了PaaS云平台管理员为其部署自定义容器网络流量规则和PaaS云平台通过在非特权容器中运行应用程序实例并加强它们来保护容器的方法。