
我们在一次针对香港客户金融业务的部署项目中,选用了裸金属服务器来承载一批高安全需求的微服务容器。项目初期,我们通过常规的Docker+CGroup+Namespace做了一轮安全隔离评估,但在风险扫描中仍旧暴露出数个内核特权逃逸隐患。为彻底强化容器的内核面攻击防护,我们决定启用内核级LSM(Linux Security Module),并最终落地了AppArmor作为强化机制。以下是我在香港裸金属环境中部署AppArmor、集成容器运行时、以及编写安全策略的完整实践路径。
一、背景与问题定位
裸金属服务器部署容器与虚拟机不同,没有hypervisor隔离加持,攻击者一旦逃逸容器,即可直达宿主机。因此在以下几类风险下,传统容器隔离手段不足以应对:
- 可疑容器挂载敏感路径如/proc/kcore
- 利用cap_sys_admin提权后加载内核模块
- 执行ptrace跟踪其他容器或宿主机进程
为此,我们考虑在内核层启用LSM(AppArmor或SELinux)。由于香港服务器的操作系统为Ubuntu 22.04,并且AppArmor已内建,我们优先选用了AppArmor来强化容器级访问控制。
二、环境准备与基础检查
裸金属服务器系统信息如下:
- 操作系统:Ubuntu 22.04 LTS
- 内核版本:5.15.0-91-generic
- 容器运行时:containerd 1.7 + runc
首先验证内核是否支持LSM,并确认AppArmor是否已启用:
$ cat /sys/kernel/security/lsm
lockdown,yama,apparmor,bpf
$ sudo aa-status
apparmor module is loaded.
若输出为空或未加载模块,可通过GRUB参数启用:
# 编辑GRUB配置
sudo vim /etc/default/grub
# 确保以下参数存在
GRUB_CMDLINE_LINUX="... apparmor=1 security=apparmor"
# 更新GRUB并重启
sudo update-grub
sudo reboot
三、为容器运行时启用AppArmor支持
在containerd中启用AppArmor,需确保以下配置步骤已完成:
确认runc支持AppArmor:
$ runc --version
runc version 1.1.12
spec: 1.0.2-dev
# 查看是否启用了AppArmor
$ ldd $(which runc) | grep apparmor
若缺少支持,可通过源代码编译runc时开启AppArmor:
$ make BUILDTAGS="apparmor"
containerd启用默认profile加载:
# 编辑containerd配置
sudo vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
ApparmorProfile = "container-default"
# 重启containerd
sudo systemctl restart containerd
四、自定义AppArmor策略文件
在/etc/apparmor.d/中编写一份针对容器用途的自定义策略,以下是一个典型的container-nginx-profile:
#include <tunables/global>
profile container-nginx-profile flags=(attach_disconnected) {
# 基础许可
network,
capability net_bind_service,
capability chown,
# 限制文件系统访问
deny /etc/shadow r,
deny /etc/ssh/** r,
# 允许读写日志
/var/log/nginx/** rw,
# 限制外部程序执行
deny /bin/dash x,
deny /usr/bin/python* x,
# 默认拒绝其余所有访问
deny /** rwklx,
}
编译并加载策略:
sudo apparmor_parser -r /etc/apparmor.d/container-nginx-profile
五、容器运行时挂载AppArmor策略
以ctr为例运行一个Nginx容器并强制绑定AppArmor策略:
sudo ctr run \
--security-apparmor-profile container-nginx-profile \
docker.io/library/nginx:latest \
nginx-secure
或者在Kubernetes中挂载AppArmor策略:
apiVersion: v1
kind: Pod
metadata:
name: nginx-secure
annotations:
container.apparmor.security.beta.kubernetes.io/nginx: localhost/container-nginx-profile
spec:
containers:
- name: nginx
image: nginx:latest
确保container-nginx-profile已加载至宿主机的AppArmor配置中。
六、策略调试与日志排查
AppArmor默认将拒绝日志写入/var/log/syslog或journalctl中:
sudo journalctl -k | grep apparmor
一旦出现拒绝条目(如DENIED r),可根据路径精准调整策略。建议采用逐步收敛的方式:
初期使用complain模式:允许行为但记录日志;
稳定后切换为enforce模式进行强隔离。
sudo aa-complain /etc/apparmor.d/container-nginx-profile
七、实际效果与安全收益
完成部署后,我们重新进行渗透测试模拟。多个恶意镜像尝试:
- 读取宿主机/etc/shadow → 被AppArmor阻断
- 在容器内执行ptrace → 被runc+LSM隔离
- 自定义程序尝试执行外部shell命令 → 被拒绝执行
同时观察到,即使容器具备–privileged权限,只要启用AppArmor profile,其仍受限于策略约束。这一点对于多租户的裸金属环境尤其重要。
相比于SELinux的复杂策略模型,AppArmor更适合在Ubuntu系系统中快速落地强化容器安全。香港裸金属环境下直接暴露在公网中的业务,更应通过LSM级别的约束防止特权滥用与侧信道攻击。实际测试中,我已将AppArmor配置纳入每台裸金属机器的初始化流程,确保所有容器均绑定最低权限策略。这一实践极大提升了我们整体平台的运行时安全基线。











