Add more content and fix format

This commit is contained in:
Baohua Yang
2026-02-25 21:06:21 -08:00
parent dd449bc84f
commit ecab788013
119 changed files with 566 additions and 496 deletions

View File

@@ -1,20 +1,86 @@
## 18.3 Docker 服务端防护
## 18.3 服务端防护
运行一个容器或应用程序的核心是通过 Docker 服务端Docker 服务的运行目前需要 root 权限因此其安全性十分关键
Docker 守护进程`dockerd`是容器生命周期的核心驱动力默认情况下Docker 服务的运行需要极高的系统特权root 权限因此其安全性关系到整台宿主机的生死存亡
首先确保只有可信的用户才可以访问 Docker 服务Docker 允许用户在主机和容器间共享文件夹同时不需要限制容器的访问权限这就容易让容器突破资源限制例如恶意用户启动容器的时候将主机的根目录 `/` 映射到容器的 `/host` 目录中那么容器理论上就可以对主机的文件系统进行任意修改了这听起来很疯狂但是事实上几乎所有虚拟化系统都允许类似的资源共享而没法禁止用户共享主机根文件系统到虚拟机系统
如果 Docker 守护进程的访问控制没有做好恶意攻击者可以通过 Docker API 轻易地启动一个特权容器并将宿主机的根目录`/`挂载到容器中从而完全接管服务器
这将会造成很严重的安全后果因此当提供容器创建服务时 (例如通过一个 web 服务器)要更加注意进行参数的安全检查防止恶意的用户用特定参数来创建一些破坏性的容器
为了加强对服务端的保护我们需要从访问控制通信加密和权限最小化三个维度进行加固
为了加强对服务端的保护Docker REST API (客户端用来跟服务端通信) 0.5.2 之后使用本地的 Unix 套接字机制替代了原先绑定在 127.0.0.1 上的 TCP 套接字因为后者容易遭受跨站脚本攻击现在用户使用 Unix 权限检查来加强套接字的访问安全
### 18.3.1 限制 API 访问
用户仍可以利用 HTTP 提供 REST API 访问建议使用安全机制确保只有可信的网络或 VPN或证书保护机制 (例如受保护的 stunnel ssl 认证) 下的访问可以进行此外还可以使用 [HTTPS 和证书](https://docs.docker.com/engine/security/https/)来加强保护
Docker 客户端`docker` 命令通过 REST API 与守护进程进行通信
最近改进的 Linux 命名空间机制将可以实现使用非 root 用户来运行全功能的容器这将从根本上解决了容器和主机之间共享文件系统而引起的安全问题
在早期版本中Docker 有时会绑定在 `127.0.0.1` TCP 套接字上但这容易遭遇跨站脚本跨协议攻击现在的发行版默认使用 Unix Domain Socket`/var/run/docker.sock`并依赖文件系统的权限控制
终极目标是改进 2 个重要的安全特性
#### 原则 1决不可将无认证的 TCP 端口暴露在公网
* 将容器的 root 用户[映射到本地主机上的非 root 用户](https://docs.docker.com/engine/security/userns-remap/),减轻容器和主机之间因权限提升而引起的安全问题;
* 允许 Docker 服务端在[ root 权限 (rootless 模式)](https://docs.docker.com/engine/security/rootless/) 下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。
这是最常见的 Docker 被入侵抓去挖矿的原因绝不能在没有任何安全控制的情况下强行开启 `-H tcp://0.0.0.0:2375`
最后建议采用专用的服务器来运行 Docker 和相关的管理服务 (例如管理服务比如 ssh 监控和进程监控管理工具 nrpecollectd )其它的业务服务都放到容器中去运行
如果业务确实需要远程访问 Docker 守护进程**必须启用 TLS 认证机制**让客户端和服务端互相进行证书校验
#### 开启 TLS 认证双向加密
利用安全机制确保只有经过授权的主机网络并在强证书保护下进行通信
1. 首先使用 `openssl` 或基于本地 CA 工具生成一套客户端与服务器的证书
2. 配置 Docker 守护进程通常是 `daemon.json` `dockerd` 启动参数指定证书路径
```bash
dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
```
3. 客户端想要连接时也必须出示客户端证书
> [!TIP]
> 配置 TLS 生成证书的完整步骤可以查阅 [Docker 官方 TLS 文档](https://docs.docker.com/engine/security/protect-access/)。在现代编排系统(如 Kubernetes通常会有自动化方案管理这些凭据。
### 18.3.2 保护本地 Socket 访问
哪怕不开启网络端口本地的 `/var/run/docker.sock` 也需要谨慎对待
任何被授予该 Socket 读写权限的用户通常被加入 `docker` 用户组等同于拥有了对宿主机的零成本提权途径无需密码的免密 `sudo` 权限
> [!CAUTION]
> 永远不要将不可信的普通用户加入到 `docker` 用户组中同样在容器编排时尽量避免将宿主机的 `/var/run/docker.sock` 直接映射给普通容器使用这种模式被称为 Docker-in-Docker (DinD) Docker-out-of-Docker (DooD)存在极高的越权风险
### 18.3.3 Rootless 模式 (非特权运行)
为了从根本上解决拥有 Docker socket 就是 root的问题Docker 在近年推出了 **Rootless 模式**
Rootless 模式允许在完全局限于非 `root` 用户的环境中运行 Docker 守护进程`dockerd`和容器该模式利用了现代 Linux 内核的 User Namespace 技术和非特权网络命名空间实现
#### 配置运行 Rootless Docker
要在非 root 环境中运行 Docker只需要简单几步
1. 安装必要的依赖通常是 `uidmap` 工具包以便系统支持 `newuidmap` `newgidmap`
```bash
$ sudo apt-get install uidmap
```
2. 切换到一个没有任何 `sudo` 权限的普通用户假设用户名为 `testuser`
```bash
$ su - testuser
```
3. 运行 Docker 官方提供的 Rootless 安装脚本
```bash
$ curl -fsSL https://get.docker.com/rootless | sh
```
4. 配置环境变量指向新创建的私有 socket
```bash
$ export DOCKER_HOST=unix:///run/user/1000/docker.sock
$ docker version
```
安装并暴露相应的配置后该用户的环境将能独立启动属于他自己的 Docker Daemon即使由于某些未知 0-Day 漏洞使得攻击者突破了容器他们也只会受限于 `testuser` 这个非特权用户所在的有限系统环境内
### 18.3.4 结语
保障 Docker 服务端的安全主要是做减法关闭不必要的网络监听点严管 Socket 访问权限而一旦基础系统条件允许**毫不犹豫地在生产环境启用 Rootless 模式**将是一项划算的安全加固选择