界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

hardening-docker-daemon-configuration

hardening-docker-daemon-configuration

【部署与运维】通过配置 daemon.json 实现用户命名空间重映射、TLS 认证、无根模式(rootless mode)和 CIS Benchmark 控制措施,对 Docker daemon 进行安全加固。

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: hardening-docker-daemon-configuration description: 通过配置 daemon.json 实现用户命名空间重映射、TLS 认证、无根模式(rootless mode)和 CIS Benchmark 控制措施,对 Docker daemon 进行安全加固。 domain: cybersecurity subdomain: container-security tags: [docker, daemon-hardening, container-security, cis-benchmark, rootless, userns-remap] version: "1.0" author: mahipal license: Apache-2.0

Docker Daemon 配置安全加固

概述

Docker daemon(dockerd)以 root 权限运行并控制所有容器操作。通过 /etc/docker/daemon.json、TLS 证书、用户命名空间重映射和网络限制对其配置进行加固,对于防止权限提升、横向移动和容器逃逸攻击至关重要。

前置条件

  • 已安装 Docker Engine 24.0+
  • Docker 宿主机上的 root 或 sudo 权限
  • OpenSSL,用于生成 TLS 证书
  • 了解 Linux 命名空间和 cgroups

核心加固 daemon.json

{
  "icc": false,
  "userns-remap": "default",
  "no-new-privileges": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  },
  "storage-driver": "overlay2",
  "live-restore": true,
  "userland-proxy": false,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 32768
    },
    "nproc": {
      "Name": "nproc",
      "Hard": 4096,
      "Soft": 2048
    }
  },
  "seccomp-profile": "/etc/docker/seccomp/default.json",
  "default-address-pools": [
    {
      "base": "172.17.0.0/16",
      "size": 24
    }
  ],
  "iptables": true,
  "ip-forward": true,
  "ip-masq": true,
  "experimental": false,
  "metrics-addr": "127.0.0.1:9323",
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "default-runtime": "runc",
  "runtimes": {
    "runsc": {
      "path": "/usr/local/bin/runsc",
      "runtimeArgs": ["--platform=ptrace"]
    }
  }
}

各配置项说明

禁用容器间通信(ICC)

{
  "icc": false
}

防止默认桥接网络上的容器相互通信。每个容器必须使用显式的 --link 或带有发布端口的用户自定义网络。

启用用户命名空间重映射

{
  "userns-remap": "default"
}

将容器 root(UID 0)映射到宿主机上的高位非特权 UID。这可防止容器逃逸后在宿主机上获得 root 权限。

# 验证 userns-remap 已激活
cat /etc/subuid
# 输出:dockremap:100000:65536

cat /etc/subgid
# 输出:dockremap:100000:65536

# 验证容器 UID 映射
docker run --rm alpine id
# uid=0(root) gid=0(root) —— 但宿主机 UID 为 100000+

禁用新权限提升

{
  "no-new-privileges": true
}

防止容器进程通过 setuid/setgid 二进制文件或能力提升获取额外权限。

启用在线恢复

{
  "live-restore": true
}

在 daemon 停机期间保持容器运行,支持在不重启容器的情况下升级 daemon。

禁用用户态代理

{
  "userland-proxy": false
}

使用 iptables 规则而非 docker-proxy 进行端口转发,减少攻击面并提升性能。

远程 Docker API 的 TLS 配置

生成 CA 和服务器证书

# 创建 CA
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem \
  -subj "/CN=Docker CA"

# 创建服务器密钥和 CSR
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=docker-host" -sha256 -new -key server-key.pem -out server.csr

# 创建含 SAN 的 extfile
echo "subjectAltName = DNS:docker-host,IP:10.0.0.5,IP:127.0.0.1" > extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf

# 签署服务器证书
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile extfile.cnf

# 创建客户端密钥和证书
openssl genrsa -out key.pem 4096
openssl req -subj "/CN=client" -new -key key.pem -out client.csr
echo "extendedKeyUsage = clientAuth" > extfile-client.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out cert.pem -extfile extfile-client.cnf

# 设置权限
chmod 0400 ca-key.pem key.pem server-key.pem
chmod 0444 ca.pem server-cert.pem cert.pem

# 移至 Docker TLS 目录
sudo mkdir -p /etc/docker/tls
sudo cp ca.pem server-cert.pem server-key.pem /etc/docker/tls/

为 daemon.json 配置 TLS

{
  "tls": true,
  "tlsverify": true,
  "tlscacert": "/etc/docker/tls/ca.pem",
  "tlscert": "/etc/docker/tls/server-cert.pem",
  "tlskey": "/etc/docker/tls/server-key.pem",
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}

客户端连接

docker --tlsverify \
  --tlscacert=ca.pem \
  --tlscert=cert.pem \
  --tlskey=key.pem \
  -H=tcp://docker-host:2376 version

Docker Socket 保护

# 限制 socket 所有权
sudo chown root:docker /var/run/docker.sock
sudo chmod 660 /var/run/docker.sock

# 审计 Docker socket 访问
sudo auditctl -w /var/run/docker.sock -k docker-socket

# 永远不要将 Docker socket 挂载到容器中
# 错误示例:docker run -v /var/run/docker.sock:/var/run/docker.sock ...

无根模式 Docker

# 安装无根模式 Docker
curl -fsSL https://get.docker.com/rootless | sh

# 配置环境
export PATH=$HOME/bin:$PATH
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

# 启动无根模式 daemon
systemctl --user start docker
systemctl --user enable docker

# 验证无根模式
docker info | grep -i rootless
# Rootless: true

内容信任(镜像签名)

# 启用 Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# 仅拉取已签名的镜像
docker pull library/alpine:3.18
# 若镜像未签名则失败

# 签名并推送镜像
docker trust sign myregistry/myapp:1.0

Seccomp 配置文件

# 查看默认 seccomp 配置文件
docker info --format '{{.SecurityOptions}}'

# 使用自定义 seccomp 配置文件
docker run --security-opt seccomp=/etc/docker/seccomp/custom.json alpine

# 验证 seccomp 已启用
docker inspect --format='{{.HostConfig.SecurityOpt}}' container_name

AppArmor 配置文件

# 检查 AppArmor 状态
sudo aa-status

# 使用自定义 AppArmor 配置文件
docker run --security-opt apparmor=docker-custom alpine

# 加载自定义配置文件
sudo apparmor_parser -r /etc/apparmor.d/docker-custom

验证命令

# 检查 daemon 配置
docker info

# 验证 userns-remap
docker info --format '{{.SecurityOptions}}'

# 检查 ICC 设置
docker network inspect bridge --format '{{.Options}}'

# 使用 Docker Bench 审计
docker run --rm --net host --pid host \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /etc:/etc:ro \
  docker/docker-bench-security

最佳实践

  1. 永远不要在没有 TLS 的情况下暴露 Docker daemon —— 远程访问始终使用 --tlsverify
  2. 启用用户命名空间重映射 —— 将容器 root 映射到非特权宿主机 UID
  3. 禁用 ICC —— 防止默认桥接网络上的容器间通信
  4. 使用无根模式 —— 尽量以非 root 用户运行 Docker daemon
  5. 启用内容信任 —— 仅拉取已签名的镜像
  6. 配置日志轮换 —— 防止日志文件填满磁盘
  7. 使用 seccomp 配置文件 —— 限制容器可用的系统调用
  8. 审计 Docker socket —— 监控对 /var/run/docker.sock 的访问
  9. 定期运行 Docker Bench —— 自动化 CIS Benchmark 检查
  10. 保持 Docker 更新 —— 及时应用安全补丁
我的收藏