容器横向渗透攻击防护加固服务器配置:容器横向渗透攻击防护
为什么容器会产生横向渗透风险
容器默认共享宿主机的内核,同一个 Docker 网桥下的容器可以互相通信。
一旦某个容器被入侵,攻击者很容易通过内部网络扫描并攻击其他容器,或者提升权限逃逸到宿主机。横向渗透攻击就是利用这种容器间的信任关系逐步扩大战果。
下面从零开始演示如何加固服务器配置。
准备条件:检查环境并备份数据
- 操作系统:CentOS 7.9 / Ubuntu 20.04(本文以 Ubuntu 为例)
- Docker 版本:建议 20.10 以上,命令中用
docker version查看 - 已安装 Docker,并且当前用户能执行
docker命令(如需 sudo 则自行调整) - 重要:操作前先备份重要容器和数据卷,避免配置失误导致服务中断
四步加固配置:从网络到内核
第一步:隔离容器网络,禁止默认桥接通信
Docker 安装后会自动创建一个 docker0 桥接网络,所有容器默认都连在上面。第一步就是不让容器自动加入这个公共网络。
- 编辑 Docker 的 daemon 配置文件
/etc/docker/daemon.json(如果文件不存在则新建):
{
"bridge": "none",
"iptables": true,
"icc": false
}
"bridge": "none"让 Docker 不自动创建默认桥接网络"icc": false禁止容器间默认通信(icc = inter-container communication)
- 重启 Docker 服务:
sudo systemctl restart docker - 之后每次运行容器时,应显式指定使用自定义网络(见下一步)。
第二步:使用用户定义的网络并控制连接
不用默认桥接后,新建一个自定义网络,并只将需要通信的容器加入同一个网络。
这样其他容器无法扫描到该网络内的容器。
docker network create --driver bridge --subnet 172.20.0.0/24 secure_net
运行容器时指定 --network secure_net。
例如:
docker run -d --name web --network secure_net nginx:alpine
如果需要容器之间通信,可以显式将容器连接到同一网络(使用 docker network connect)。
第三步:限制 Capabilities 和 Seccomp,防止权限提升
即使网络隔离,容器内的进程仍然可能拥有不必要的 Linux 能力(capabilities)。
建议去掉默认赋予的危险能力,并启用 Seccomp 安全策略。
运行容器时加上 --security-opt no-new-privileges 和 --cap-drop=ALL 先丢掉所有能力,再按需添加。
例如:
docker run -d --name app \
--network secure_net \
--security-opt no-new-privileges:true \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
nginx:alpine
同时可以启用 Docker 默认的 Seccomp 配置文件:
docker run -d --name app \
--security-opt seccomp=/path/to/default.json \
...
Docker 自带一个默认的 seccomp 配置文件(/usr/share/docker/default-seccomp.json),直接引用即可。
第四步:使用非 root 用户运行容器进程
默认容器内的进程以 root 身份运行,极大增加逃逸风险。
建议在 Dockerfile 中指定普通用户,或者在运行容器时使用 --user 参数。
例如运行一个 Alpine 容器,用 nobody 用户:
docker run -d --name myapp --user 65534:65534 alpine sleep 3600
如果使用官方镜像(如 nginx),可以查阅其文档,通常有预置的 nginx 用户,直接 --user nginx 即可。
避坑说明:这些配置可能影响正常服务
- 禁止 icc 后,如果之前容器依赖互相通信(例如 nginx 反向代理 php-fpm),必须显式连接同一自定义网络,否则访问失败。
--cap-drop=ALL后,很多容器功能会受限,比如 nginx 无法绑定 80 端口,需要加--cap-add=NET_BIND_SERVICE。建议先列出真实所需的能力,参考 Docker 文档。- Seccomp 策略:如果容器使用了系统调用但未在默认配置中放行,可能导致程序崩溃。建议先在测试环境运行一段时间,观察日志。
- 非 root 用户:如果容器需要写日志或操作某些特权目录(如挂载卷),注意目录权限要提前设置。
验证加固效果:几个简单测试
- 测试容器间默认通信是否被禁止:
- 启动两个容器,不指定网络(会尝试加入默认桥接,但已被禁用)。应该无法 ping 通对方的 IP。
- 如果
docker run --rm alpine ping 172.17.0.2提示网络不可达或超时,说明隔离生效。
- 检查自定义网络内的通信:
- 将两个容器都加入
secure_net,它们可以互相 ping 通。只加入一个的则无法 ping。
- 验证 capabilities 限制:
- 进入容器
docker exec -it app sh,执行cat /proc/1/status | grep CapPrm,查看结果。如果00000000...说明大部分能力已被丢弃。
- 检查用户权限:
- 容器内执行
whoami或id,确认是普通用户而不是 root。
通过以上步骤,你已经为服务器上的容器环境构筑了基础的横向渗透攻击防护。
建议定期检查 Docker 的安全配置变更,并结合防火墙(如 ufw)进一步限制外部访问。
如果遇到容器启动异常,优先回看避坑部分的说明。
常见问题解答
Q:启用 icc: false 后,我的单机容器怎么连外网?
A:不影响连接外网。icc 仅控制容器间通信,容器仍可通过宿主机的 iptables 访问外部。
Q:我已经有运行中的容器,怎么应用这些配置?
A:需要删除容器后重新创建。生产环境请先规划停机窗口,或新建测试容器确认无误再迁移。
Q:这些配置会影响 Kubernetes 吗?
A:如果 Docker 被 Kubernetes 使用,建议在 Kubernetes 层面(如 NetworkPolicy、PodSecurityPolicy)控制,Docker daemon 的 icc 配置可能被覆盖。本教程适用于独立 Docker 环境。