3. 容器运行时安全:容器隔离机制与逃逸防护策略
容器运行时安全是云原生安全基线的核心防线。本章聚焦于容器隔离的底层机制(Namespace / Cgroups)、强制访问控制模块(Seccomp / AppArmor / SELinux)的基础配置,以及容器逃逸的防护策略。理解这些机制并正确配置初始策略组,是构建安全容器环境的前提。
3.1 容器隔离机制:Namespace 与 Cgroups
容器通过 Linux 内核的两大特性实现资源隔离与限制:Namespace 负责“隔离视图”,Cgroups 负责“限制资源”。两者协同工作,为容器提供轻量级的虚拟化环境。
3.1.1 Namespace:进程视图隔离
Namespace 将全局系统资源(如进程 ID、网络栈、挂载点)封装到独立的命名空间中,使容器内的进程只能看到自己的资源视图。关键 Namespace 类型如下:
| Namespace 类型 | 隔离资源 | 安全意义 |
|---|---|---|
| PID | 进程 ID 编号 | 容器内无法看到宿主机或其他容器的进程 |
| Network | 网络设备、IP 地址、路由表 | 容器拥有独立的网络栈,避免网络攻击横向扩散 |
| Mount | 文件系统挂载点 | 容器只能访问自己的文件系统视图 |
| UTS | 主机名与域名 | 容器拥有独立的主机名 |
| IPC | 进程间通信资源(信号量、消息队列) | 防止跨容器 IPC 干扰 |
| User | 用户 ID 与组 ID | 容器内 root 用户映射为宿主机非特权用户 |
| Cgroup | Cgroup 视图 | 容器无法查看宿主机 Cgroup 信息 |
shareProcessNamespace 字段应保持默认 false,避免容器间共享 PID 命名空间。
3.1.2 Cgroups:资源限制与审计
Cgroups(Control Groups)用于限制、记录和隔离进程组的物理资源(CPU、内存、磁盘 I/O、网络带宽)。在安全层面,Cgroups 主要防止“资源耗尽型”攻击(如 Fork Bomb、内存泄漏)。
- CPU 限制: 通过
cpu.shares和cpu.cfs_quota_us防止单个容器抢占所有 CPU 时间。 - 内存限制: 通过
memory.limit_in_bytes设置硬限制,超出则触发 OOM Kill。 - 进程数限制: 通过
pids.max限制容器内最大进程数,防止 Fork Bomb 攻击。 - 设备白名单: 通过
devices.allow控制容器对宿主机设备的访问。
# 示例:通过 cgconfig 配置容器内存限制(单位:字节)
group container-demo {
memory {
memory.limit_in_bytes = 536870912; # 512MB
memory.memsw.limit_in_bytes = 1073741824; # 内存+交换 1GB
}
pids {
pids.max = 100; # 最大 100 个进程
}
}
3.2 强制访问控制:Seccomp / AppArmor / SELinux
Namespace 和 Cgroups 提供了基础隔离,但无法阻止容器内进程发起危险系统调用(如 mount、ptrace、open_by_handle_at)。强制访问控制模块在系统调用层和文件访问层提供细粒度安全策略。
3.2.1 Seccomp:系统调用过滤
Seccomp(Secure Computing Mode)允许容器运行时定义系统调用白名单或黑名单。Docker 默认提供 default 配置文件,阻止约 44 个危险系统调用。
| Seccomp 模式 | 行为 | 适用场景 |
|---|---|---|
SCMP_ACT_ALLOW |
允许系统调用 | 白名单模式中的允许项 |
SCMP_ACT_ERRNO |
拒绝并返回错误(如 EPERM) |
阻止危险系统调用 |
SCMP_ACT_KILL |
立即终止进程 | 检测到恶意行为时强制终止 |
SCMP_ACT_TRAP |
触发 SIGSYS 信号 | 调试与审计场景 |
# 自定义 Seccomp 配置文件示例:仅允许基本系统调用
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": ["read", "write", "open", "close", "mmap", "munmap", "exit", "exit_group"],
"action": "SCMP_ACT_ALLOW"
}
]
}
securityContext.seccompProfile 字段为 Pod 指定 Seccomp 配置。生产环境建议使用 RuntimeDefault 或自定义严格白名单。
3.2.2 AppArmor:路径与网络访问控制
AppArmor 使用“路径匹配”模式,通过加载配置文件(profile)限制程序对文件系统、网络和 Linux 能力的访问。Docker 默认提供 docker-default 配置文件。
# AppArmor 配置文件示例:限制容器只能读取 /data 目录
#include <tunables/global>
profile container-restricted flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
# 允许读取 /data 目录
/data/** r,
# 拒绝写入 /etc 和 /proc
/etc/** wlx,
/proc/** wlx,
# 拒绝网络访问
network,
deny network tcp,
deny network udp,
}
3.2.3 SELinux:标签化强制访问控制
SELinux 通过安全上下文(Security Context)为进程、文件、设备等主体和客体打标签,基于策略规则控制访问。在容器场景中,SELinux 为每个容器分配唯一的 MCS(Multi-Category Security)标签,实现容器间隔离。
- 类型强制(TE): 定义进程类型(如
container_t)与文件类型(如container_file_t)的访问规则。 - 多类别安全(MCS): 为每个容器分配随机类别标签(如
s0:c1,c2),防止容器间相互访问文件。 - 布尔值策略: 通过
getsebool和setsebool动态调整策略(如container_use_devices)。
# 查看容器 SELinux 上下文
docker inspect --format='{{.ProcessLabel}}' <container_id>
# 输出示例:system_u:system_r:container_t:s0:c1,c2
# 启用 SELinux 的 Docker 配置(/etc/docker/daemon.json)
{
"selinux-enabled": true
}
securityContext 同时配置三者。
3.3 容器逃逸防护策略
容器逃逸是指攻击者突破容器隔离边界,获得宿主机或集群其他节点的访问权限。逃逸路径通常分为三类:内核漏洞利用、配置缺陷、能力滥用。
3.3.1 常见逃逸路径与防护矩阵
| 逃逸路径 | 攻击原理 | 防护策略 |
|---|---|---|
| 内核漏洞(如 CVE-2022-0847) | 利用内核提权漏洞突破 Namespace | 及时更新内核、启用 Seccomp 阻止漏洞利用链 |
| 挂载宿主机敏感目录 | 挂载 /proc、/sys、/dev 后修改内核参数 |
禁止挂载宿主机 /proc、/sys;使用只读挂载 |
| Docker Socket 暴露 | 容器内访问 /var/run/docker.sock 创建特权容器 |
禁止挂载 Docker Socket;使用非 root 用户运行容器 |
| Capability 滥用 | 赋予 SYS_ADMIN、SYS_PTRACE 等危险 Capability |
遵循最小 Capability 原则;默认删除所有 Capability 再按需添加 |
特权容器(--privileged) |
容器拥有所有 Capability 并访问所有设备 | 禁止使用特权容器;使用 securityContext.privileged: false |
| User Namespace 未启用 | 容器内 root 等于宿主机 root | 启用 User Namespace 重映射(--userns-remap) |
3.3.2 逃逸防护策略清单
- 最小权限原则: 删除所有 Capability(
--cap-drop=ALL),仅按需添加(如--cap-add=NET_BIND_SERVICE)。 - 只读根文件系统: 设置
readOnlyRootFilesystem: true,防止攻击者写入恶意文件。 - 禁止特权升级: 设置
allowPrivilegeEscalation: false,阻止setuid提权。 - 非 root 用户运行: 在 Dockerfile 中指定
USER指令,或在 Pod 中设置runAsNonRoot: true。 - 启用 Seccomp 严格模式: 使用自定义 Seccomp 配置文件,阻止
mount、ptrace、open_by_handle_at等逃逸关键系统调用。 - AppArmor/SELinux 强制策略: 加载自定义配置文件,限制容器对宿主机文件系统和网络的访问。
- 禁用主机网络与 PID 命名空间: 避免使用
hostNetwork: true和hostPID: true。 - 运行时安全监控: 部署 Falco 或 Tracee 等运行时安全工具,实时检测异常系统调用和文件访问。
3.4 容器运行时安全纵深防御架构
下图展示了容器运行时安全的纵深防御架构,从内核层到应用层形成多层防护。
3.5 初始策略组配置清单
以下为容器运行时安全的初始策略组配置清单,适用于 Kubernetes 环境:
| 策略项 | 推荐配置 | 配置位置 |
|---|---|---|
| Seccomp 配置 | seccompProfile.type: RuntimeDefault |
Pod SecurityContext |
| AppArmor 配置 | container.apparmor.security.beta.kubernetes.io/<container>: runtime/default |
Pod 注解 |
| SELinux 配置 | seLinuxOptions.type: container_t |
Pod SecurityContext |
| Capability 限制 | capabilities.drop: ["ALL"] |
Container SecurityContext |
| 特权模式 | privileged: false |
Container SecurityContext |
| 特权升级 | allowPrivilegeEscalation: false |
Container SecurityContext |
| 只读根文件系统 | readOnlyRootFilesystem: true |
Container SecurityContext |
| 非 root 用户 | runAsNonRoot: true |
Pod SecurityContext |
| User Namespace | hostUsers: false(K8s v1.27+) |
Pod Spec |
| 主机网络/主机 PID | hostNetwork: false、hostPID: false |
Pod Spec |
kube-bench 或 kubectl audit 定期检查集群中 Pod 的安全上下文配置是否符合基线。例如:kubectl get pods -o json | jq '.items[].spec.containers[].securityContext'