保护 Docker 守护进程套接字
默认情况下,Docker 通过非网络化的 UNIX socket 运行。它还可以 选择使用 SSH 或 TLS (HTTPS) socket 进行通信。
使用 SSH 保护 Docker 守护进程套接字
注意
指定的
USERNAME必须拥有在远程机器上访问 Docker Socket 的权限。请参见 以非 root 用户身份管理 Docker 以了解如何授予非 root 用户访问 Docker Socket 的权限。
The following example creates a
docker context
to connect with a remote dockerd daemon on host1.example.com using SSH, and
as the docker-user user on the remote machine:
$ 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 上下文切换回默认(本地)守护进程:
$ 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 守护进程 socket
如果您需要以安全的方式通过 HTTP(而非 SSH)访问 Docker,
您可以指定 tlsverify 标志来启用 TLS (HTTPS),并将 Docker 的
tlscacert 标志指向受信任的 CA 证书。
在守护进程模式下,它仅允许由该 CA 签名的证书进行身份验证的客户端连接。在客户端模式下,它仅连接到拥有由该 CA 签名的证书的服务器。
重要
使用 TLS 和管理 CA 是一个高级主题。在生产环境中使用之前,请先熟悉 OpenSSL、x509 和 TLS。
使用 OpenSSL 创建 CA、服务器和客户端密钥
注意
将以下示例中
$HOST的所有出现替换为您 Docker 守护进程主机的 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 守护进程主机的 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 守护进程密钥的扩展用途属性设置为仅用于服务器身份验证:
$ 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 守护进程中运行的授权插件会接收连接 Docker 客户端的证书信息。
对于客户端身份验证,请创建客户端密钥和证书签名请求:
注意
为简化接下来的几个步骤,您也可以在此 Docker 守护进程的主机上执行此操作。
$ 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
With a default umask of 022, your secret keys are world-readable and
writable for you and your group.
为防止密钥意外损坏,请移除其写权限。要确保仅您本人可读,请按以下方式更改文件模式:
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
证书可以是世界可读的,但您可能希望移除写权限以防止意外损坏:
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
现在您可以配置 Docker 守护进程,使其仅接受提供由您的 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 守护进程主机的 DNS 名称。
$ docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=$HOST:2376 version
注意
Docker over TLS 应运行在 TCP 端口 2376 上。
警告
如上例所示,当您使用证书认证时,无需在运行
docker客户端时指定sudo或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,tlskeyset: 验证客户端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