docker配置tls (二) 生成tls脚本

一、生成tls脚本

#!/usr/bin/env bash
# -------------------------------------------------------------
# 自动创建 Docker TLS 证书
# -------------------------------------------------------------
:<<!
author: lanwp
date: 2019/4/17
des:    docker tls数字证书创建。
            subjectAltName 不设置服务器端subjectAltName不设置(不校验 serverIP,所有服务器均可用)
            subjectAltName 设置多个 subjectAltName = DNS:docker166,IP:192.168.72.166,IP:127.0.0.1
        自动创建 Docker TLS 证书

        服务器证书
            ca.pem
            server-cert.pem
            server-key.pem
        客户端使用
            cert.pem
            ca.pem
            key.pem
!

PASSWORD="123456" #私钥密码
DAYS=36500
#IP=""

COUNTRY="CN"
STATE="省" # 省 可选
CITY="市" # 市 可选
ORGANIZATION="公司名称" # 组织 可选
ORGANIZATIONAL_UNIT="Dev" # 组织-单位可选
COMMON_NAME="test"  # 域名或者IP,必须填写
EMAIL="test@163.com" # 可选 test@163.com

function noCode() {
    #---
    # 创建ca-key.pem 和 ca.pem
    #openssl genrsa -out ca-key.pem 4096
    openssl genrsa -aes256 -passout "pass:${PASSWORD}" -out ca-key.pem 4096  # -passout "pass:$PASSWORD" 不用输入私钥privateKey
    openssl req -new -x509 -days ${DAYS} -key "ca-key.pem" -sha256 -out "ca.pem" -passin "pass:${PASSWORD}" -subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORGANIZATION}/OU=${ORGANIZATIONAL_UNIT}/CN=${COMMON_NAME}/emailAddress=${EMAIL}"

    #---
    # Generate Server key
    openssl genrsa -out "server-key.pem" 4096
    # Generate Server Certs.
    openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key.pem" -out server.csr

    # echo subjectAltName = DNS:docker166,IP:192.168.72.166,IP:127.0.0.1 >> extfile.cnf
    # echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf
    echo "extendedKeyUsage = serverAuth" >> extfile.cnf
    # Generate server-cert.pem
    openssl x509 -req -days ${DAYS} -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf -passin "pass:${PASSWORD}"

    rm -f extfile.cnf

    #---
    # Generate Cient
    openssl genrsa -out "key.pem" 4096

    openssl req -subj '/CN=client' -new -key "key.pem" -out client.csr
    echo extendedKeyUsage = clientAuth >> extfile.cnf
    openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:${PASSWORD}" -CA "ca.pem" -CAkey "ca-key.pem" -CAcreateserial -out "cert.pem" -extfile extfile.cnf

    rm -vf client.csr server.csr extfile.cnf

    chmod -v 0400 ca-key.pem key.pem server-key.pem
    chmod -v 0444 ca.pem server-cert.pem cert.pem
}

# 保存目录
setSaveCaDir() {
    # 运行脚本的路径   当前运行脚本文件名basename和目录dirname
    local BASE_PATH = $PWD
    if [ -d "$BASE_PATH/ssl" ];then
        echo "文件夹存在"
    else
        echo "文件夹不存在"
        mkdir $PWD/ssl
    fi

    cd $PWD/ssl
}

setSaveCaDir
noCode

二、证书放到目标docker

docker 服务端证书配置

docker 1.12.6

系统

容器版本
docker1.12.6
系统版本CentOS Linux release 7.2.1511 (Core)

-----这里配置 -H fd:// 也可以-----
centos推荐配置 unix://
修改文件 /usr/lib/systemd/system/docker.service,添加ExecStart添加-H fd://

[root@docker227 ~]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTIONS  $DOCKER_STORAGE_OPTIONS  $DOCKER_NETWORK_OPTIONS

修改文件中/etc/sysconfig/docker-network

DOCKER_NETWORK_OPTIONS="--tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server-cert.pem --tlskey=/root/.docker/server-key.pem -H=0.0.0.0:2376 -H=0.0.0.0:2375"

docker -H使用

tcp监听配置同时监听2375和 2376

# 默认为对应主机的2375端口
docker -H 192.168.72.166 ps   
# 指定端口
docker -H 192.168.72.166:2376 ps

例子

[root@localhost ~]# docker -H localhost:2375 ps
Get http://localhost:2375/v1.26/containers/json: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?
[root@localhost ~]# docker -H localhost ps
Get http://localhost:2375/v1.26/containers/json: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?
[root@localhost ~]# docker -H localhost:2376 ps
Cannot connect to the Docker daemon at tcp://localhost:2376. Is the docker daemon running?

docker 1.3.1和 docker-ce 1.18.09

docker.service文件配置

方法一:自己添加一个文件/etc/sysconfig/docker-network

EnvironmentFile=-/etc/sysconfig/docker-network
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:// $DOCKER_NETWORK_OPTIONS

[root@docker111 ~]# cat /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=" --tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server-cert.pem --tlskey=/root/.docker/server-key.pem -H=0.0.0.0:2376"

方法二:
/usr/lib/systemd/system/docker.service文件中直接添加所有

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:// $DOCKER_NETWORK_OPTIONS  --tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server-cert.pem --tlskey=/root/.docker/server-key.pem -H 0.0.0.0:2376

-H 0.0.0.0:2376 效果等同于 -H=0.0.0.0:2376

官网配置参考 https://docs.docker.com/engine/reference/commandline/dockerd/
docker 1.13版本以上使用 unix:// 本机使用docker命令不需要使用证书
1.12.x fd://

官网摘抄片段

On Systemd based systems, you can communicate with the daemon via Systemd socket activation, use dockerd -H fd://. Using fd:// will work perfectly for most setups but you can also specify individual sockets: dockerd -H fd://3. If the specified socket activated files aren’t found, then Docker will exit. You can find examples of using Systemd socket activation with Docker and Systemd in the Docker source tree.

You can configure the Docker daemon to listen to multiple sockets at the same time using multiple -H options:

# listen using the default unix socket, and on 2 specific IP addresses on this host.

$ sudo dockerd -H unix:///var/run/docker.sock -H tcp://192.168.59.106 -H tcp://10.10.10.2

仅供参考有人说ubuntu 还是用 fd:// centos使用 unix://

本地测试证书

增加 -H fd:// 后容器本地客户端访问本机可以不需要指定证书

[root@docker227 ~]# docker version
Client:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.4
 Git commit:   78d1802
 Built:        Wed Jan 11 00:23:16 2017
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.4
 Git commit:   78d1802
 Built:        Wed Jan 11 00:23:16 2017
 OS/Arch:      linux/amd64

本机上使用外部IP测试

[root@docker227 ~]# docker -H 192.168.14.227 version
Client:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.4
 Git commit:   78d1802
 Built:        Wed Jan 11 00:23:16 2017
 OS/Arch:      linux/amd64
Get http://192.168.14.227:2375/v1.24/version: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?

否则需要证书如下

[root@docker110 ~]# docker version
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: 
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

本地按局域网模拟远程访问

[root@docker110 ~]# docker -H 192.168.72.110 version
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: 
Get http://192.168.72.110:2375/v1.26/version: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?


[root@docker110 ~]# docker --tls -H 192.168.72.110 version
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: docker-1.13.1-94.gitb2f74b2.el7.centos.x86_64
 Go version:      go1.10.3
 Git commit:      b2f74b2/1.13.1
 Built:           Tue Mar 12 10:27:24 2019
 OS/Arch:         linux/amd64

Server:
 Version:         1.13.1
 API version:     1.26 (minimum version 1.12)
 Package version: docker-1.13.1-94.gitb2f74b2.el7.centos.x86_64
 Go version:      go1.10.3
 Git commit:      b2f74b2/1.13.1
 Built:           Tue Mar 12 10:27:24 2019
 OS/Arch:         linux/amd64
 Experimental:    false

–tls 表示不校验服务端主机IP
–tlsverify 校验主机IP

  • docker服务器主机IP无效,说明可能不是真是服务器或没有设置服务器有效IP

      [root@docker110 ~]# docker --tlsverify -H 192.168.72.110 version
      Client:
       Version:         1.13.1
       API version:     1.26
       Package version: 
      error during connect: Get https://192.168.72.110:2375/v1.26/version: x509: cannot validate certificate for 192.168.72.110 because it doesn't contain any IP SANs
    

curl测试 docker https

Connecting to the secure Docker port using curl
To use curl to make test API requests, you need to use three extra command line flags:

$ curl https://$HOST:2376/images/json \
  --cert ~/.docker/cert.pem \
  --key ~/.docker/key.pem \
  --cacert ~/.docker/ca.pem

https://docs.docker.com/engine/security/https/

验证服务端证书

[root@docker110 ~]# curl https://192.168.72.111:2376/images/json --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem 
curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.

增加 -k 不验证服务端证书
curl https://192.168.72.111:2376/version --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert

[root@docker110 ~]# curl https://192.168.72.111:2376/version --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem -k
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"18.09.0","Details":{"ApiVersion":"1.39","Arch":"amd64","BuildTime":"2018-11-07T00:19:08.000000000+00:00","Experimental":"false","GitCommit":"4d60db4","GoVersion":"go1.10.4","KernelVersion":"3.10.0-957.1.3.el7.x86_64","MinAPIVersion":"1.12","Os":"linux"}}],"Version":"18.09.0","ApiVersion":"1.39","MinAPIVersion":"1.12","GitCommit":"4d60db4","GoVersion":"go1.10.4","Os":"linux","Arch":"amd64","KernelVersion":"3.10.0-957.1.3.el7.x86_64","BuildTime":"2018-11-07T00:19:08.000000000+00:00"}

httpClient和dockerClient

dockerClient基于httpclient请求dockerApi

使用docker pem证书生成httpClient

        DockerCertificatesStore dockerCertificatesStore = null;
        try {
            dockerCertificatesStore = new DockerCertificates(Paths.get(getDockerCaDir()));
        } catch (DockerCertificateException e) {
            e.printStackTrace();
        }
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLContext(dockerCertificatesStore.sslContext()).setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();

使用docker.keystore

根据docker的证书转化为keystore,https方式请求dockerApi

private static SSLConnectionSocketFactory getSSLConnectionSocketFactory() throws Exception {
        String curClassPath = DockerApi.class.getClassLoader().getResource("").getPath();
        String keyStorePath = new File(curClassPath + "/dockertls/certificate/docker.keystore").getPath();

        // docker使用证书将对应的pem证书转为jks证书
        InputStream in = new FileInputStream(new File(keyStorePath));
        KeyStore keyStore = KeyStore.getInstance("jks");

        String password = dockerKeyStorePass; // 证书密码,生成证书时指定
        try {
            keyStore.load(in, password.toCharArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            in.close();
        }
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, (password).toCharArray())
                .loadTrustMaterial(new TrustSelfSignedStrategy())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext, new String[] { "TLSv1" }, null,
                new NoopHostnameVerifier()); // 不验证server服务器
        return sslsf;
    }

    public CloseableHttpClient getHttpclientSsl(){
		CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sSLConnectionSocketFactory)
                .build();
        return httpclient;
    }

生成keystore脚本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值