容器横向渗透攻击防护加固服务器完整配置
容器横向渗透攻击是攻击者从一个被攻陷的容器内,利用网络、配置或权限漏洞,横向移动控制其他容器甚至宿主机的行为。
如果你的服务器上运行着多个容器且缺乏安全隔离,一次突破可能演变成整个环境沦陷。
下面从五个层面给出完整的加固步骤,每步都有命令和配置示例,复制执行即可。
1. 系统内核层:阻止跨容器资源穿透
容器共享宿主机内核,必须限制关键内核参数防止逃逸。
操作步骤如下:
打开 /etc/sysctl.d/99-container-security.conf 文件(如果没有则新建):
vi /etc/sysctl.d/99-container-security.conf
写入以下内容:
kernel.dmesg_restrict=1
kernel.kptr_restrict=2
kernel.yama.ptrace_scope=1
net.core.bpf_jit_enable=0
net.ipv4.tcp_syncookies=1
kernel.dmesg_restrict=1:禁止非特权容器查看内核日志,防止信息泄露。kernel.kptr_restrict=2:隐藏内核符号地址,增大提权难度。kernel.yama.ptrace_scope=1:限制ptrace调用,阻止跨容器进程调试。net.core.bpf_jit_enable=0:禁用 BPF JIT 编译器,防止利用 BPF 攻击。
保存后执行 sysctl -p /etc/sysctl.d/99-container-security.conf 生效。
2. Docker 守护进程:安全基线配置
Docker 自身配置不当是横向渗透的常见入口。
编辑 /etc/docker/daemon.json:
vi /etc/docker/daemon.json
写入:
{
"icc": false,
"iptables": true,
"userland-proxy": false,
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"no-new-privileges": true
}
"icc": false:禁止容器间默认通信,隔离所有容器,必须通过自定义网络才能互通。"userland-proxy": false:关闭用户态代理,减少攻击面。"no-new-privileges": true:容器内禁止通过 suid 等获得新特权。
重启 Docker:systemctl restart docker。
3. 网络隔离:限制容器间流量
即便关闭了 ICC,仍需用自定义网络并配合 iptables 进一步精细控制。
创建隔离网络:
docker network create --driver bridge --internal isolate-net
--internal 参数让该网络不连接外部,适合敏感服务。
如果希望部分容器可以互相通信,使用 --link 或 --net-alias,但务必审计出必要端口。
示例:运行一个 web 容器并只允许它访问后端数据库:
docker run -d --network isolate-net --name web --network-alias web-app nginx
docker run -d --network isolate-net --name db --network-alias db-server mariadb
使用 iptables 记录并丢弃未授权的容器间流量:
iptables -A DOCKER-USER -i docker0 -j LOG --log-prefix "DOCKER-FORBIDDEN: "
iptables -A DOCKER-USER -i docker0 -j DROP
(如果使用了自定义网桥,替换 docker0 为实际网桥名)
4. 用户权限与 Capabilities:最小化容器内权限
不要以 --privileged 运行容器,并移除不必要的 Linux Capabilities。
运行容器时指定:
docker run -d --cap-drop=ALL --cap-add=NET_BIND_SERVICE --security-opt=no-new-privileges:true my-app
--cap-drop=ALL:移除全部高危权限。--cap-add=NET_BIND_SERVICE:只添加绑定低端口(小于1024)所需能力。--security-opt=no-new-privileges:true:防止通过 setuid 提升权限。
在 Dockerfile 中尽量避免使用 USER root,改用 USER appuser。
如果容器必须读取宿主机某些文件,使用 --read-only 挂载只读卷:
docker run -v /var/data:/data:ro --read-only ...
5. 高频问题解答 & 避坑说明
Q1:关闭 ICC 后容器间如何通信?
将需要互通的容器加入同一个自定义 bridge 网络(如 docker network create mynet),然后 docker run --network mynet。
Q2:/var/run/docker.sock 暴露给容器会怎样?
容器内若挂载了 /var/run/docker.sock,就获得了 Docker 守护进程控制权,可直接创建特权容器完成逃逸。严禁将 docker.sock 挂载给非信任容器。
Q3:如何验证加固效果?
用 docker run --rm -it alpine sh 进入一个容器,执行 capsh --print 查看 Capabilities 是否只剩 NET_BIND_SERVICE;执行 ip link 检查是否只能访问本容器网络;尝试 ping 其他容器,应为超时。
避坑提醒:
- 修改内核参数前备份原文件;生产环境先在测试机验证。
- 关闭 ICC 后,如果使用 docker-compose 定义的容器,必须显式声明网络才能互相发现。
- 如果使用 Kubernetes,网络策略(NetworkPolicy)是更优方案,本文步骤适用于原生 Docker 或单机环境。
按照以上五步操作后,你的服务器在容器层面已经具备基本的横向渗透防御能力。
定期检查容器运行时安全事件(如 grep "DOCKER-FORBIDDEN" /var/log/messages)有助于及时发现异常流量。
后续可以继续配置 Seccomp、AppArmor 或 Falco 等增强工具,进一步提升纵深防御效果。