通过etcd集群搭建了解pki安全认证-02

0 阅读

上一篇文章中介绍了etcd集群的搭建已经将对外的服务接口http转为https,本文将继续介绍在如何将集群间的peer通信从http转换成https。

0. 实验环境

参考《通过etcd集群搭建了解pki安全认证-01》建立etcd集群。本文介绍重建集群和不重建集群两种情况下启用节点间https通信的方法。

1. 准备peer证书

和server证书一样,3个节点的peer证书其实也可以共用一个,但是同样会带来之前提到的集群节点变化时的证书管理问题。并且集群间通信双方就是物理节点,不可能使用统一的域名或者虚拟IP,因此,好的实践是为每个节点配置自己的peer证书。

为3个节点创建peer证书请求文件所需配置:

# cfssl print-defaults csr > etcd1-peer-csr.json
# vi etcd1-peer-csr.json

修改后内容如下,以节点k8s1为例:

# cat etcd1-peer-csr.json
{
    "CN": "ETCD Peer on k8s1",
    "hosts": [
        "192.168.56.41"
    ],
    "key": {
        "algo": "ecdsa",
        "size": 256
    },
    "names": [
        {
            "C": "US",
            "L": "CA",
            "ST": "San Francisco"
        }
    ]
}

创建服务器peer证书, 并拷贝到相应的节点上:

# cfssl gencert -ca=rootca.pem -ca-key=rootca-key.pem -config=ca-config.json -profile=peer etcd1-peer-csr.json | cfssljson -bare etcd1-peer
# cfssl gencert -ca=rootca.pem -ca-key=rootca-key.pem -config=ca-config.json -profile=peer etcd2-peer-csr.json | cfssljson -bare etcd2-peer
# cfssl gencert -ca=rootca.pem -ca-key=rootca-key.pem -config=ca-config.json -profile=peer etcd3-peer-csr.json | cfssljson -bare etcd3-peer
# scp /etc/etcd/pki/etcd2-peer*.pem k8s2:/etc/etcd/pki/
# scp /etc/etcd/pki/etcd3-peer*.pem k8s3:/etc/etcd/pki/

2. 重建集群以启用https

集群节点的peer访问端点存储在数据目录,因此修改ETCD_INITIAL_CLUSTER参数后,最简单让其生效的方法就是重建集群。

注意:这种方法将丢失已有数据,一般在新建集群时使用。

在所有节点上修改etcd配置文件,将peer的url修改为https,配置相关证书,以k8s1为例,涉及参数如下:

ETCD_LISTEN_PEER_URLS="https://192.168.56.41:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.56.41:2380"
ETCD_INITIAL_CLUSTER="k8s1=https://192.168.56.41:2380,k8s2=https://192.168.56.42:2380,k8s3=https://192.168.56.43:2380"
ETCD_PEER_CERT_FILE="/etc/etcd/pki/etcd1-peer.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/pki/etcd1-peer-key.pem"
ETCD_PEER_CLIENT_CERT_AUTH="true"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/pki/rootca.pem"

在所有节点上删除已有实例,重启etcd。

# systemctl stop etcd
# rm -rf /var/lib/etcd/default.etcd
# systemctl start etcd

3. 不重建集群启用https

3.1 修改1个节点的peer通信端点

步骤如下:

  1. 查看节点列表,获取节点标识
[root@k8s1 pki]# etcdctl --ca-file /etc/etcd/pki/rootca.pem --cert-file /etc/etcd/pki/etcdctl.pem --key-file /etc/etcd/pki/etcdctl-key.pem member list
1a3c142a6a5e6e84: name=k8s3 peerURLs=http://192.168.56.43:2380 clientURLs=https://192.168.56.43:2379 isLeader=false
7c1dfc5e13a8008a: name=k8s2 peerURLs=http://192.168.56.42:2380 clientURLs=https://192.168.56.42:2379 isLeader=true
c920522ba9a75e17: name=k8s1 peerURLs=http://192.168.56.41:2380 clientURLs=https://192.168.56.41:2379 isLeader=false
  1. 修改k8s3节点的peer url为https
[root@k8s1 pki]# etcdctl --ca-file /etc/etcd/pki/rootca.pem --cert-file /etc/etcd/pki/etcdctl.pem --key-file /etc/etcd/pki/etcdctl-key.pem member update 1a3c142a6a5e6e84 https://192.168.56.43:2380
Updated member with ID 1a3c142a6a5e6e84 in cluster
  1. 重新检查节点列表和集群健康状态
[root@k8s1 pki]# etcdctl --ca-file /etc/etcd/pki/rootca.pem --cert-file /etc/etcd/pki/etcdctl.pem --key-file /etc/etcd/pki/etcdctl-key.pem member list
1a3c142a6a5e6e84: name=k8s3 peerURLs=https://192.168.56.43:2380 clientURLs=https://192.168.56.43:2379 isLeader=false
7c1dfc5e13a8008a: name=k8s2 peerURLs=http://192.168.56.42:2380 clientURLs=https://192.168.56.42:2379 isLeader=true
c920522ba9a75e17: name=k8s1 peerURLs=http://192.168.56.41:2380 clientURLs=https://192.168.56.41:2379 isLeader=false

[root@k8s1 pki]# etcdctl --ca-file /etc/etcd/pki/rootca.pem --cert-file /etc/etcd/pki/etcdctl.pem --key-file /etc/etcd/pki/etcdctl-key.pem cluster-health
member 1a3c142a6a5e6e84 is healthy: got healthy result from https://192.168.56.43:2379
member 7c1dfc5e13a8008a is healthy: got healthy result from https://192.168.56.42:2379
member c920522ba9a75e17 is healthy: got healthy result from https://192.168.56.41:2379

可以看到k8s3的peer地址已经是https了,但实际上此时k8s3的侦听地址没有修改,https所需要的相关证书都没有配置,https通信是不可能建立的,因此事实上此时与k8s3的通信仍然是fallback到http上。在k8s3上抓包分析,可以看到结果如下:

etcd2380-fallback-http1.jpg

客户端不断发出https请求,但是作为服务器的k8s3没有任何响应,最后使用http进行发送raft协议消息。

3.2 修改k8s3的peer工作端口为https

修改k8s3配置中的工作端口和相关证书,这些证书的生成方法参考上一篇文章的第6节。

涉及参数如下:

ETCD_LISTEN_PEER_URLS="https://192.168.56.43:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.56.43:2380"
ETCD_PEER_CERT_FILE="/etc/etcd/pki/etcd3-peer.pem"      
ETCD_PEER_KEY_FILE="/etc/etcd/pki/etcd3-peer-key.pem"
ETCD_PEER_CLIENT_CERT_AUTH="true"                       
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/pki/rootca.pem"

然后重启k8s3上的etcd。上述配置在k8s3启动了服务器端的https通信,并且要求进行客户端验证,而作为客户端的k8s1和k8s2还没有相关配置,因此https通信仍然会失败,与k8s3的通信仍然fallback到http上。

在k8s3上可看到如下出错日志和数据包:

Oct 26 08:15:56 k8s3 etcd[2857]: rejected connection from "192.168.56.41:41164" (error "remote error: tls: bad certificate", ServerName "")

etcd2380-fallback-http2.jpg

可以看到服务器端已经返回了peer证书,但客户端无法验证该证书导致https失败。

3.3 在k8s1和k8s2上配置上客户端所需证书

涉及的参数主要是客户端自身的证书和私钥,以及用于验证k8s3的根CA证书:

ETCD_PEER_CERT_FILE="/etc/etcd/pki/etcd1-peer.pem"      
ETCD_PEER_KEY_FILE="/etc/etcd/pki/etcd1-peer-key.pem"                      
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/pki/rootca.pem"

然后重启两个节点上的etcd,发现k8s3上的报错随即停止,至此,完成了k8s3上https通信的转换。在k8s3上抓包分析,可看到完整的https证书交互建立连接的过程。

etcd2380-fallback-https.jpg

3.4. 对其余节点到重复上述步骤

如果先在节点上修改配置文件启用https URL,再使用etcdctl指令修改集群的peer访问端点,在两步之间的时间里,实际上是客户端使用http协议访问服务器的https服务,这段时间实际集群间的通信是失败的。可在服务器上看到https请求被拒绝的错误:

Oct 26 08:34:50 k8s2 etcd[9579]: rejected connection from "192.168.56.41:39714" (error "tls: first record does not look like a TLS handshake", ServerName "")

因此,一个比较好的实践是先使用etcdct指令修改访问端点,再修改服务器配置文件启用https。

更新于

本文遵守 CC-BY-NC-4.0 许可协议。

Creative Commons License

欢迎转载,转载需注明出处,且禁止用于商业目的。

上篇AWS临时授权-01
下篇通过etcd集群搭建了解pki安全认证-01