###下文中所有的 $HOST 都使用docker daemon的host的DNS,基本就是服务器ip
我们要做的是,在dockerd中 使用 tlservify 和 tlscacert 标识来信任一个 CA 证书。
1.在Docker Daeom的Host机上创建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]:CN
State or Province Name (full name) [Some-State]:Shanghai
Locality Name (eg, city) []:Shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:GiantRoot Inc
Organizational Unit Name (eg, section) []:cloud server
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:jusesgod@163.com
**确保$HOST是客户端用来连接Daemon的名称。
2.创建服务器证书
$ 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
3.通过我们的CA证书,给公钥签名
A:设置允许访问的连接,允许通过$HOST和 127.0.0.1访问
$ echo subjectAltName = DNS:$HOST,IP:127.0.0.1 >> extfile.cnf
**如果$HOST是ip地址的话,就不用写DNS:******了,直接写IP:XXXXXXXX
B:设置Docker Daemon的键的扩展用法属性设置为仅用于 服务器身份验证
$ echo extendedKeyUsage = serverAuth >> extfile.cnf
C:生成签名证书
$ 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
4.生成客户端证书
$ 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:
最后可以删除两个证书文件,还有那些额外的配置文件
$ rm -v client.csr server.csr extfile.cnf extfile-client.cnf
为了保护CA的只读性,删除证书的写属性
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
现在可以这样启动dockerd
$ dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
**注意在docker.service文件中的配置:
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server-cert.pem --tlskey=/root/.docker/server-key.pem -H 0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock
客户端
$ docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=$HOST:2376 version
最后通过服务器测试访问:
$ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=106.12.80.25 version
Client: Docker Engine - Community
Version: 25.0.3
API version: 1.44
Go version: go1.21.6
Git commit: 4debf41
Built: Tue Feb 6 21:17:10 2024
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 25.0.3
API version: 1.44 (minimum version 1.24)
Go version: go1.21.6
Git commit: f417435
Built: Tue Feb 6 21:16:08 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.28
GitCommit: ae07eda36dd25f8a1b98dfbf587313b99c0190bb
runc:
Version: 1.1.12
GitCommit: v1.1.12-0-g51d5e94
docker-init:
Version: 0.19.0
GitCommit: de40ad0
失败结果:
$ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=106.12.80.25 version
Client: Docker Engine - Community
Version: 25.0.3
API version: 1.44
Go version: go1.21.6
Git commit: 4debf41
Built: Tue Feb 6 21:17:10 2024
OS/Arch: linux/amd64
Context: default
error during connect: Get "https://106.12.80.25:2375/v1.24/version": tls: failed to verify certificate: x509: certificate is valid for 127.0.0.1, not 106.12.80.25
在idea中配置:
Engin API URL:https://106.12.80.25:2375
certificates folder:证书所在目录
就能安全访问了。
参考文档:
Docker文档:Protect the Docker daemon socket | Docker Docs
Docker配置tls中文文档 Docker开启安全的TLS远程连接访问方式_docker_脚本之家 (jb51.net)