使用TLS解决Docker API暴露2375端口的问题
问题起因
由于本人开发环境是在 Windows,开发完成后需要使用 Dockerfile 打包镜像,这个过程需要有一个 Docker 服务完成,Windows 安装 Docker 会影响到很多环境,我又不想本地开虚拟机使用 Docker,于是我就索性使用服务器上的 Docker,并放开了 2375 端口,这个是 Docker 默认 API 的端口,于是就可以很愉快的打包发布了。
但是没过几天,我就收到阿里云的告警,服务器负载长时间在 100%,服务器卡得不行,上服务器一看,不知道为什么多了几个没见过的 Docker 镜像以及很多不认识的容器,于是判断服务器应该是被黑客入侵了,被用来挖矿了,而入侵的入口就是 Docker 的 2375端口。
解决方法
解决方法最简单的就是尽量不要启用 API 功能,或者把默认端口改一下,但是这个也是只能解决一时的问题,后来查询资料,找到了使用 TLS 通信机制的解决方法。解决方法的过程如下:
- 生成一系列证书和文件
# 创建一个文件夹,用于存放需要用到的证书等信息 mkdir -p ~/docker-certs cd ~/docker-certs # 生成一个 CA(证书颁发机构)私钥,CA私钥用于为服务器或客户端证书生成签名。这个签名证明了该证书是由可信的 CA 颁发的。当服务器或客户端收到证书时,它会用 CA 的公钥来验证证书的签名。如果验证通过,意味着该证书确实是由该 CA 颁发的,确保了证书持有者的身份合法性。 openssl genrsa -aes256 -out ca-key.pem 4096 # 生成 key 的过程中,可能会出现要求输入 Enter pass phrase for ca-key.pem,这个相当于私钥的密码,能够进一步保证私钥的安全,哪怕别人获取到你的私钥,也不能直接使用,要输入密码。 # 用 CA私钥自签名生成一个 CA 的证书,CA证书用于验证 CA 身份的合法性,要信任某个证书,关键就是要信任CA的证书。 openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem # 创建服务器端私钥和证书 openssl genrsa -out server-key.pem 4096 openssl req -new -key server-key.pem -out server.csr # CA 为服务端证书签名 openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem # 创建客户端私钥和证书 openssl genrsa -out key.pem 4096 openssl req -new -key key.pem -out client.csr # 签署客户端证书 openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem
- 移除不必要的 CSR 文件
rm -v server.csr client.csr
- 设置权限
chmod -v 0400 ca-key.pem key.pem server-key.pem chmod -v 0444 ca.pem server-cert.pem cert.pem
- 修改 /usr/lib/systemd/system/docker.service 文件
ExecStart 那改成:vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd \ --tlsverify \ --tlscacert=/root/docker-certs/ca.pem \ --tlscert=/root/docker-certs/server-cert.pem \ --tlskey=/root/docker-certs/server-key.pem \ -H tcp://0.0.0.0:2376 -H unix://var/run/docker.sock \ -H fd:// --containerd=/run/containerd/containerd.sock
- 重启 Docker 服务
systemctl daemon-reload && systemctl restart docker
- 客户端所在机器找个地方存放 ca.pem、cert.pem、key.pem 三个文件,并且添加以下三个环境变量:
DOCKER_HOST=tcp://你 docker 所在的IP地址:2376 DOCKER_CERT_PATH=存放三个文件的地方 DOCKER_TLS_VERIFY=1
- 然后测试即可