保护 Docker 守护进程套接字
默认情况下,Docker 通过非网络化的 UNIX socket 运行。它也可以选择使用 SSH 或 TLS (HTTPS) socket 进行通信。
使用 SSH 保护 Docker daemon socket
注意
给定的
USERNAME
必须具有访问远程机器上 docker socket 的权限。 请参考 以非root用户身份管理Docker 了解如何授予非root用户对 docker socket 的访问权限。
以下示例创建一个 docker context
,以使用 SSH 连接到 host1.example.com
上的远程 dockerd
daemon,并在远程机器上以 docker-user
用户身份运行。
$ docker context create \
--docker host=ssh://docker-user@host1.example.com \
--description="Remote engine" \
my-remote-engine
my-remote-engine
Successfully created context "my-remote-engine"
创建上下文后,使用 docker context use
将 docker
CLI 切换为使用它,并连接到远程引擎。
$ docker context use my-remote-engine
my-remote-engine
Current context is now "my-remote-engine"
$ docker info
<prints output of the remote engine>
使用 default
上下文切换回默认(本地)daemon。
$ docker context use default
default
Current context is now "default"
或者,使用 DOCKER_HOST
环境变量临时切换 docker
CLI 以使用 SSH 连接到远程主机。这不需要创建上下文,对于使用不同引擎创建临时连接非常有用。
$ export DOCKER_HOST=ssh://docker-user@host1.example.com
$ docker info
<prints output of the remote engine>
SSH 提示
为了获得最佳的 SSH 用户体验,请按如下方式配置 ~/.ssh/config
以允许为多次调用 docker
CLI 重用 SSH 连接。
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
使用 TLS (HTTPS) 保护 Docker daemon socket
如果您需要 Docker 以安全的方式通过 HTTP 而不是 SSH 可访问,您可以通过指定 tlsverify
标志并将 Docker 的 tlscacert
标志指向受信任的 CA 证书来启用 TLS (HTTPS)。
在 daemon 模式下,它只允许来自由该 CA 签名的证书进行身份验证的客户端的连接。在客户端模式下,它只连接到由该 CA 签名的证书的服务器。
重要
使用 TLS 和管理 CA 是一个高级主题。在生产环境中使用它之前,请熟悉 OpenSSL、x509 和 TLS。
使用 OpenSSL 创建 CA、服务器和客户端密钥
注意
将以下示例中所有出现的
$HOST
替换为 Docker daemon 主机的 DNS 名称。
首先,在 Docker daemon 的主机上,生成 CA 私钥和公钥。
$ openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
..............................................................................++
........++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem:
Verifying - Enter pass phrase for ca-key.pem:
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:Queensland
Locality Name (eg, city) []:Brisbane
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
Organizational Unit Name (eg, section) []:Sales
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:Sven@home.org.au
现在您有了 CA,您可以创建服务器密钥和证书签名请求 (CSR)。确保“公用名称”与您用于连接到 Docker 的主机名匹配。
注意
将以下示例中所有出现的
$HOST
替换为 Docker daemon 主机的 DNS 名称。
$ openssl genrsa -out server-key.pem 4096
Generating RSA private key, 4096 bit long modulus
.....................................................................++
.................................................................................................++
e is 65537 (0x10001)
$ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
接下来,我们将使用我们的 CA 签名公钥。
由于 TLS 连接可以通过 IP 地址以及 DNS 名称建立,因此在创建证书时需要指定 IP 地址。例如,要允许使用 10.10.10.20
和 127.0.0.1
建立连接。
$ echo subjectAltName = DNS:$HOST,IP:10.10.10.20,IP:127.0.0.1 >> extfile.cnf
将 Docker daemon 密钥的扩展使用属性设置为仅用于服务器身份验证。
$ 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
Signature ok
subject=/CN=your.host.com
Getting CA Private Key
Enter pass phrase for ca-key.pem:
授权插件 提供更细粒度的控制,以补充来自相互 TLS 的身份验证。除了上述文档中描述的其他信息外,在 Docker daemon 上运行的授权插件还会接收连接 Docker 客户端的证书信息。
对于客户端身份验证,请创建客户端密钥和证书签名请求。
注意
为了简化接下来的几个步骤,您也可以在 Docker daemon 的主机上执行此步骤。
$ openssl genrsa -out key.pem 4096
Generating RSA private key, 4096 bit long modulus
.........................................................++
................++
e is 65537 (0x10001)
$ 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
Signature ok
subject=/CN=client
Getting CA Private Key
Enter pass phrase for ca-key.pem:
生成 cert.pem
和 server-cert.pem
后,您可以安全地删除两个证书签名请求和扩展配置文 件。
$ rm -v client.csr server.csr extfile.cnf extfile-client.cnf
使用默认的 umask
022,您的密钥对您和您的组来说是世界可读的和可写的。
为了保护您的密钥免受意外损坏,请删除其写权限。要使其只能由您读取,请按如下方式更改文件模式。
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
证书可以是世界可读的,但您可能希望删除写访问权限以防止意外损坏。
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
现在您可以使 Docker daemon 仅接受来自提供您的 CA 信任的证书的客户端的连接。
$ dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
要连接到 Docker 并验证其证书,请提供您的客户端密钥、证书和受信任的 CA。
提示
此步骤应在您的 Docker 客户端机器上运行。因此,您需要将您的 CA 证书、服务器证书和客户端证书复制到该机器。
注意
将以下示例中所有出现的
$HOST
替换为 Docker daemon 主机的 DNS 名称。
$ docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=$HOST:2376 version
注意
使用 TLS 的 Docker 应在 TCP 端口 2376 上运行。
警告
如上例所示,当您使用证书认证时,无需使用 `sudo` 或 `docker` 组运行 `docker` 客户端。这意味着任何拥有密钥的人都可以向您的 Docker 守护进程发出任何指令,从而赋予他们对托管守护进程的机器的 root 访问权限。请像保护 root 密码一样保护这些密钥!
默认安全
如果您想默认保护您的 Docker 客户端连接,您可以将文件移动到主目录中的 `.docker` 目录——并设置 `DOCKER_HOST` 和 `DOCKER_TLS_VERIFY` 变量(而不是在每次调用时传递 `-H=tcp://$HOST:2376` 和 `--tlsverify`)。
$ mkdir -pv ~/.docker
$ cp -v {ca,cert,key}.pem ~/.docker
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
Docker 现在默认情况下安全连接。
$ docker ps
其他模式
如果您不想进行完全的双向身份验证,您可以通过混合使用标志以各种其他模式运行 Docker。
守护进程模式
- 设置 `tlsverify`、`tlscacert`、`tlscert`、`tlskey`:验证客户端
- `tls`、`tlscert`、`tlskey`:不验证客户端
客户端模式
- `tls`:基于公共/默认 CA 池验证服务器
- `tlsverify`、`tlscacert`:基于给定的 CA 验证服务器
- `tls`、`tlscert`、`tlskey`:使用客户端证书进行身份验证,不基于给定的 CA 验证服务器
- `tlsverify`、`tlscacert`、`tlscert`、`tlskey`:使用客户端证书进行身份验证,并基于给定的 CA 验证服务器
如果找到,客户端会发送其客户端证书,因此您只需要将密钥放入 `~/.docker/{ca,cert,key}.pem`。或者,如果您想将密钥存储在其他位置,您可以使用环境变量 `DOCKER_CERT_PATH` 指定该位置。
$ export DOCKER_CERT_PATH=~/.docker/zone1/
$ docker --tlsverify ps
使用 `curl` 连接到安全的 Docker 端口
要使用 `curl` 发出测试 API 请求,您需要使用三个额外的命令行标志。
$ curl https://$HOST:2376/images/json \
--cert ~/.docker/cert.pem \
--key ~/.docker/key.pem \
--cacert ~/.docker/ca.pem