保护Docker守护进程套接字
预计阅读时间:9分钟
默认情况下,Docker通过非网络UNIX套接字运行。它还可以选择使用SSH或TLS(HTTPS)套接字进行通信。
使用SSH保护Docker守护进程套接字
笔记
给定的对象
USERNAME
必须具有访问远程计算机上的docker套接字的权限。请参阅以非root用户身份管理Docker, 以了解如何授予非root用户访问docker套接字的权限。
以下示例创建一个docker context
以使用SSH并以远程计算机上的用户身份与远程dockerd
守护程序连接的应用程序:host1.example.com
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
上下文切换回默认(本地)守护程序:
$ 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
,以允许将SSH连接重用于docker
CLI的多次调用:
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
使用TLS(HTTPS)保护Docker守护程序套接字
如果您需要通过HTTP(而非SSH)以安全方式访问Docker,则可以通过指定该tlsverify
标志并将Docker的tlscacert
标志指向
受信任的CA证书来启用TLS(HTTPS)。
在守护程序模式下,它仅允许来自由该CA签名的证书进行身份验证的客户端的连接。在客户端模式下,它仅连接到具有该CA签名的证书的服务器。
进阶主题
使用TLS和管理CA是一个高级主题。在生产环境中使用OpenSSL,x509和TLS之前,请先熟悉一下它们。
使用OpenSSL创建CA,服务器和客户端密钥
注意:将
$HOST
以下示例中的所有实例替换为Docker守护程序主机的DNS名称。
首先,在Docker守护程序的主机上,生成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签署公钥:
由于可以通过IP地址和DNS名称建立TLS连接,因此在创建证书时需要指定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
默认umask
密钥为022,您的密钥对于您和您的组是全球可读的且可写的。
为了保护您的钥匙免遭意外损坏,请删除其写权限。要使它们仅供您阅读,请按以下方式更改文件模式:
$ 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
注意:基于TLS的Docker应该在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
,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
使用连接到安全的Docker端口 curl
要用于curl
发出测试API请求,您需要使用三个额外的命令行标志:
$ curl https://$HOST:2376/images/json \
--cert ~/.docker/cert.pem \
--key ~/.docker/key.pem \
--cacert ~/.docker/ca.pem