1. 博客/

Docker配置TLS安全认证

·516 字·3 分钟
Docker CA Openssl

背景
#

通常,我们在配置docker daemon的监听方式为本地的socket和开放TCP端口,docker服务允许远程访问,方便对docker集群的主机执行管理命令及调用等。如果不使用TLS加密docker,任意客户端都可以对docker主机进行远程操作,有很大的安全隐患。而配置TLS后,只有信任的客户端才可以远程访问docker服务。

TLS认证配置
#

  1. 自签名的证书—使用openssl创建私有CA并签发公钥
#生成根证书RSA私钥,123456位私钥文件的密码
$ openssl genrsa -aes256 -passout pass:123456 -out cakey.pem 2048
Generating RSA private key, 2048 bit long modulus
........+++
......................+++
e is 65537 (0x10001)
#生成自签名证书
$ openssl req -new -x509 -days 365 -key cakey.pem -passin pass:123456 -sha256 -out ca.pem -subj "/C=CN/ST=./L=./O=./CN=192.168.196.136"

#生成server私钥
$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
.....................................................................+++
...............+++
e is 65537 (0x10001)
#指定允许通过IP地址访问的IP列表,使用逗号隔开
$ echo subjectAltName=IP:192.168.196.136 > extfile.cnf
$ echo extendedKeyUsage=serverAuth >> extfile.cnf
#生成server证书申请文件
$ openssl req -new -sha256 -key server.key -out server.csr -subj "/CN=server"
#CA签署证书,并颁发server证书
$ openssl x509 -passin pass:123456 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey cakey.pem -CAcreateserial -out server.crt -extfile extfile.cnf
Signature ok
subject=/CN=192.168.196.136
Getting CA Private Key

#生成client私钥
$ openssl genrsa -out client.key 2048
Generating RSA private key, 2048 bit long modulus
.................................................+++
...................................................+++
e is 65537 (0x10001)
#生成client证书申请文件
$ openssl req -new -sha256 -key client.key -out client.csr -subj "/CN=client"
#CA签署证书,并颁发client证书
$ openssl x509 -passin pass:123456 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey cakey.pem -CAcreateserial -out client.crt -extfile extfile.cnf
Signature ok
subject=/CN=client
Getting CA Private Key
  1. 配置docker服务开启TLS认证
#修改daemon.json文件,配置docker服务开启TLS认证
$ cat daemon.json 
{
        "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:3666"],
        "insecure-registries": ["registry:8088"],
        "tlsverify":true,
        "tlscacert":"/etc/docker/ca.pem",
        "tlscert":"/etc/docker/server.crt",
        "tlskey":"/etc/docker/server.key"
}
$ systemctl restart docker

#在本机执行验证命令
$ docker --tlsverify --tlscacert ca.pem --tlscert client.crt --tlskey=client.key -H tcp://192.168.196.136:3666 version   
Client:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-1.12.6-61.git85d7426.el7.centos.x86_64
 Go version:      go1.8.3
 Git commit:      85d7426/1.12.6
 Built:           Tue Oct 24 15:40:21 2017
 OS/Arch:         linux/amd64

Server:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-1.12.6-61.git85d7426.el7.centos.x86_64
 Go version:      go1.8.3
 Git commit:      85d7426/1.12.6
 Built:           Tue Oct 24 15:40:21 2017
 OS/Arch:         linux/amd64
  1. 分发key文件到客户端,验证

    只有有秘钥文件的客户端才能连接到此docker服务器上

$ scp ca.pem client.crt client.key 192.168.196.135:/root/
root@192.168.196.135's password: 
ca.pem                                  100% 1245     1.2KB/s   00:00    
client.crt                              100% 1086     1.1KB/s   00:00    
client.key                              100% 1675     1.6KB/s   00:00    

#登录到135主机
$ pwd
  /root
$ docker --tlsverify --tlscacert ca.pem --tlscert client.crt --tlskey=client.key -H tcp://192.168.196.136:3666 version
Client:
 Version:         1.13.1
 API version:     1.24 (downgraded from 1.26)
 Package version: docker-1.12.6-61.git85d7426.el7.centos.x86_64
 Go version:      go1.9.4
 Git commit:      dded712/1.13.1
 Built:           Tue Jul 17 18:34:48 2018
 OS/Arch:         linux/amd64

Server:
 Version:         1.12.6
 API version:     1.24 (minimum version )
 Package version: docker-1.12.6-61.git85d7426.el7.centos.x86_64
 Go version:      go1.8.3
 Git commit:      85d7426/1.12.6
 Built:           Tue Oct 24 15:40:21 2017
 OS/Arch:         linux/amd64
 Experimental:    false

TLS认证模式
#

  1. 服务端认证模式
选项说明
tlsverify, tlscacert, tlscert, tlskey向客户端发送服务端证书, 校验客户端证书是否由指定的CA(自签名根证书)签发
tls, tlscert, tlskey向客户端发送服务端证书, 不校验客户端证书是否由指定的CA(自签名根证书)签发
  1. 客户端认证模式
选项说明
tls校验服务端证书是否由 公共的CA机构签发
tlsverify, tlscacert校验服务端证书是否由指定的CA(自签名根证书)签发
tls, tlscert, tlskey使用客户端证书进行身份验证, 但不校验服务端证书是否由指定的CA(自签名根证书)签发
tlsverify, tlscacert, tlscert, tlskey使用客户端证书进行身份验证且校验服务端证书是否由指定的CA(自签名根证书)签发

​ 引用上例,我们将ca.pem、server.crt、server.key复制到docker集群的192.168.196.135主机的/etc/docker/目录下,并修改daemon.json开启docker服务TLS认证。此时客户端认证模式选择第四种时,会提示server证书无效,因为在签发证书时指定了允许通过IP地址访问的IP为192.168.196.135。

#登录到135主机
$ cd
$ docker --tlsverify --tlscacert ca.pem --tlscert client.crt --tlskey=client.key -H tcp://192.168.196.135:3666 version   
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: 
error during connect: Get https://192.168.196.135:3666/v1.26/version: x509: certificate is valid for 192.168.196.136, not 192.168.196.135

$ docker --tls --tlscacert ca.pem --tlscert client.crt --tlskey=client.key -H tcp://192.168.196.135:3666 version
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: docker-1.13.1-68.gitdded712.el7.centos.x86_64
 Go version:      go1.9.4
 Git commit:      dded712/1.13.1
 Built:           Tue Jul 17 18:34:48 2018
 OS/Arch:         linux/amd64

Server:
 Version:         1.13.1
 API version:     1.26 (minimum version 1.12)
 Package version: docker-1.13.1-68.gitdded712.el7.centos.x86_64
 Go version:      go1.9.4
 Git commit:      dded712/1.13.1
 Built:           Tue Jul 17 18:34:48 2018
 OS/Arch:         linux/amd64
 Experimental:    false

​ 如果客户端认证模式选择第四种,可以在签发server证书时,将现有docker集群的IP添加到extfile.cnf,然后拷贝到集群中的主机上,分别配置docker服务开启认证即可,而对于后续新添加节点,则需要更新extfile.cnf并重新签发server证书。

$ echo subjectAltName=IP:192.168.196.136,IP:192.168.196.135 > extfile.cnf
$ openssl x509 -passin pass:123456 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey cakey.pem -CAcreateserial -out server.crt -extfile extfile.cnf

​ 如果客户端认证模式选择不校验服务端证书,则无需指定IP,直接拷贝签发的server证书到所有节点即可

Related

如何使用openssl工具创建私有CA
·970 字·5 分钟
Linux CA Openssl
批量export Docker镜像脚本
·395 字·2 分钟
Docker
批量自动构建docker镜像的shell脚本
·580 字·3 分钟
Docker Shell