Docker:19---Docker客户端与服务端TLS认证(Docker Remote API认证)
程序员文章站
2024-01-29 18:17:34
...
一、Docker Remote API的认证
- 在前一篇文章我们介绍了Docker Remote API如何使用:https://blog.csdn.net/qq_41453285/article/details/107642615
- 在前一篇文章中我们介绍了如何连接到Docker Remote API,但是不意味着任何其他人都能连接到同样的API。从安全的角度上看,这存在一点儿安全问题。不过值得感谢的是,自Docker的0.9版本开始Docker Remote API开始提供了认证机制。这种认证机制采用了TLS/SSL证书来确保用户与API之间连接的安全
备注
- 该认证不仅仅适用于API。通过这个认证,还需要配置Docker客户来支持TLS认证。在本文我们也将看到如何对客户端进行配置
- 有几种方法可以对我们的连接进行认证,包括使用一个完整的PKI基础设置,我们可以选择创建自己的证书授权中心(Certificate Authority,CA),或者使用已有的CA。在这里我们将建立自己的证书授权中心,因为这是一个简单、快速的开始
警告
- 这依赖于运行在Docker宿主机上的本地CA。它也不像使用一个完整的证书授权中心那样安全
二、建立证书授权中心
- 下面快速了解一下创建所需CA证书和秘钥的方法,在大多数平台下这个过程都是非常标准的
- 第一步:先要确保系统安装了openssl
which openssl
- 第二步: 默认情况下,宿主机中有一个/etc/docker/目录,待会我们用这个目录来保存我们的CA和相关资料(如果没有这个目录自己创建)
ls /etc/docker
- 第三步:进入上面那个目录,生成一个私钥,命令如下,在创建私钥的过程中,我们需要为CA秘钥设置一个密码(要自己记住这个密码,在新CA中,我们需要用这个秘钥来创建并对证书签名)
cd /etc/docker
echo 01 | sudo tee ca.srl
sudo openssl genrsa -des3 -out ca-key.pem
- 之后会生成一个名为ca-key.pem的新文件,这个文件是我们的CA的秘钥(不要把这个文件透露出去,也不能丢失这个文件)
-
第四步:现在我们来创建一个CA证书,命令如下,回车之后会让你输入:
- 刚才创建的CA的秘钥的密码(刚才上面输入的)
- 然后输入城市名、组织名、邮箱等等信息
sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem
- 上面命令输入之后会传建一个ca.pem文件,这个文件使我们的CA证书,我们后面会使用这个文件来验证连接的安全性
- 现在我们有了自己的CA,让我们用它为我们的Docker服务器创建证书和秘钥
三、创建服务器的整数签名请求和秘钥
- 我们可以用新CA来为Docker服务器进行证书签名请求(cerificate signing request,CSR)和**的签名和验证
- 第一步:让我们从为Docker服务器创建一个秘钥开始,如下所示,同理也需要输入这个**的密码(注意:请设置一个密码,我们将会在使用之前清除这个密码(见下面第4步)。用户只需要在后面的几步中使用密码)
sudo openssl genrsa -des3 -out server-key.pem
- 之后会创建一个**server-key.pem
-
第二步:现在让我们创建服务器的证书签名请求(CSR),如下所示:
- 同理,也要输入上面server-key.pem秘钥的密码
- 然后再输入一系列的信息,直接回车吧,不输入了
- 但是其中的Common Name比较重要,这个选项的值要么为Docker服务器(即从DNS中解析后得到的结果,比如docker.example.com)的FQDN(fully qualified domain name,完全限定域名)形式,要么为*(浙江允许在任何服务器上使用该服务器证书)
sudo openssl req -new -key server-key.pem -out server.csr
- 之后生成一个server.csr文件
- 第三步:现在让我们来对CSR进行签名并生成服务器证书,如下所示,需要输入CA**文件的密码(创建ca-key.pem文件时的密码)
sudo openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem
- 上面命令输入完成之后会生成一个名为server-cert.pem的文件,这个文件就是我们的服务器证书
-
第四步:现在就让我们来清除服务器**的密码,如下所示
- 输入命令之后,我们要输入先前设置的服务器**的密码(见上面第一步)
- 我们不想在Docker守护进程启动的时候再输入一次密码,因此需要清除它
sudo openssl rsa -in server-key.pem -out server-key.pem
- 第五步:现在,让我们为这些文件添加一些更为严格的权限来更好地保护它们,如下所示
sudo chmod 0600 /etc/docker/server-key.pem /etc/docker/server-cert.pem /etc/docker/ca-key.pem /etc/docker/ca.pem
四、配置Docker守护进程
- 好了,现在我们已经得到了证书和秘钥,现在我们可以来配置Docker守护进程使用它们了
-
为了使用这些东西,我们需要修改守护进程的配置文件。在不同的系统中配置文件不同:
- Ubuntu、Debian系统:/etc/default/docker
- Upstart系统:/etc/init/docker.conf
- Red Hat、Redora系统:/etc/sysconfig/docker
- 对于那些使用了Systemd的发布版本:/usr/lib/systemd/docker.service
以ubuntu为例
- 我们使用是一台非server版本的ubuntu。与前面一篇文章的演示案例一样(https://blog.csdn.net/qq_41453285/article/details/107642615),docker安装在桌面版ubuntu的时候,默认的配置文件/etc/default/docker里的配置是无效的(server版并无问题),这个问题在官方文档中有出现
- 因此此处我们修改/lib/systemd/system/docker.service文件
- 第一步:修改/lib/systemd/system/docker.service文件,修改ExecStart选项
- 我们添加了一个-H,让其监听在tcp的2376端口上,这样使得外网可以访问我们的Docker守护进程,从而可以调用Docker Remote API(见前面介绍:https://blog.csdn.net/qq_41453285/article/details/107642615)
- 备注:上面我们让Docker守护进程监听在2376端口,这是Docker中TLS/SSL的默认端口号。对于非认证的链接,只能使用2375这个端口
- 然后使用了--tlsverify标志来启动TLS,然后使用--tlscacert、--tlsscert、--tlskey这3个参数指定了CA证书、证书和**的位置
sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem
- 关于TLS还有很多其他选项可以使用,请参考:https://docs.docker.com/engine/security/https/
- 第二步:之后重启Docker服务,然后再重启Docker守护进程,之后查看守护进程的状态
sudo systemctl daemon-reload sudo service docker restart sudo service docker status
五、创建客户端证书和**
- 我们的服务器已经启用了TLS,下面我们需要为客户端创建和签名证书和**,以保证我们的Docker客户端的安全性
- 备注:实际开发中,客户端应该是在其他机器上(与Docker守护进程不处于同一台)创建这些内容的,但是我们只有一台机器,因此都放在一个机器上面弄了
- 第一步:创建客户端的**,同理,也需要输入一个临时的密码
sudo openssl genrsa -des3 -out client-key.pem
- 之后生成一个cleint-key.pem**文件
-
第二步:现在我们来创建客户端CSR,如下所示
- 需要输入上面创建cleint-key.pem**文件时的密码
- 另外需要输入城市名一些列信息,直接回车
sudo openssl req -new -key client-key.pem -out client.csr
-
第三步:现在我们需要通过添加一些扩展的客户端SSL认证属性,来开启我们的**的客户端身份认证,命令如下
- 需要切换到管理员身份,不能使用sudo来执行echo命令
sudo su
echo extendedKeyUsage = clientAuth > extfile.cnf
- 之后生成一个extfile.cnf文件
-
第四步:现在让我们在自己的CA中对客户端CSR进行签名,如下所示:
- 从之前的root身份退出来
- 此处我们使用CA**的密码创建另一个证书:client-cert.pem
- 需要输入创建ca-key.pem文件时的密码(见文章上面)
exit
sudo openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem -out client-cert.pem -extfile extfile.cnf
- 之后生成一个client-cert.pem证书
-
第四步:同理,我们需要清除client-cert.pem文件中的密码,以便在Docker客户端中使用该文件,如下所示:
- 回车之后需要输入上面创建cleint-key.pem**文件指定的密码
sudo openssl rsa -in client-key.pem -out client-key.pem
六、配置Docker客户端开启认证功能
- 好了,接下来我们刻意配置我们的Docker客户端来使用我们新的TLS配置。之所以需要这么做,是因为Docker守护进程现在已经准备接收来自客户端和API的经过认证的连接
- 备注:上面曾提起过,实际上Docker客户端与服务端应该不在同一台机器上操作,但是此处我们只有一台机器,因此都在一台机器上操作了
- 第一步:在家目录下有一个docker目录(如果没有自己创一个),然后将上面我们创建的客户端的秘钥和证书复制进去
sudo cp ca.pem ~/.docker/ca.pem
sudo cp client-key.pem ~/.docker/key.pem
sudo cp client-cert.pem ~/.docker/cert.pem
sudo chmod 0600 ~/.docker/key.pem ~/.docker/cert.pem
sudo ls ~/.docker/
-
第二步:现在我们就可以来测试从客户端到Docker守护进程的连接了
- 我们使用-H来告诉客户端要连接的Docker主机
- 指定了--tlsverify选项,使我们通过TLS方式连接到Docker守护进程
- 此处我们不需要指定任何证书或者**文件,因为Docker会自己在我们的~/.docker/目录下查找这些文件。如果确实需要执行这些文件,请分别用--tlscasert、--tlscert、--tlskey选项来指定CA证书、证书和**的位置
sudo docker -H=111.229.177.161:2376 --tlsverify info
- 结果如上所示,MMP,竟然出错了
- 查看Docker守护进程的状态信息,也可以看到连接错误的消息,显示的证书错误
sudo service docker status
- 让客户端连接的时候指定 --tlscasert、--tlscert、--tlskey选项来试试,还是出错,估计是证书没配置好。感觉应该是在同一台上配置的原因,以后弄在两台机器上搞搞吧
sudo docker -H=111.229.177.161:2376 --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/client-cert.pem --tlskey=/etc/docker/client-key.pem info
- 备注:如果在连接的时候不指定--tlsverify标志,那么TLS连接会不通过,无法连接到服务器