修复 K8s SSL/TLS 漏洞(CVE20162183)指南
作者:老 Z,运维架构师,云原生爱好者,目前专注于云原生运维,云原生领域技术栈涉及 Kubernetes、KubeSphere、DevOps、OpenStack、Ansible 等。
前言

测试服务器配置
| 主机名 | IP | CPU | 内存 | 系统盘 | 数据盘 | 用途 |
|---|---|---|---|---|---|---|
| zdeops-master | 192.168.9.9 | 2 | 4 | 40 | 200 | Ansible 运维控制节点 |
| ks-k8s-master-0 | 192.168.9.91 | 4 | 16 | 40 | 200+200 | KubeSphere/k8s-master/k8s-worker |
| ks-k8s-master-1 | 192.168.9.92 | 4 | 16 | 40 | 200+200 | KubeSphere/k8s-master/k8s-worker |
| ks-k8s-master-2 | 192.168.9.93 | 4 | 16 | 40 | 200+200 | KubeSphere/k8s-master/k8s-worker |
| storage-node-0 | 192.168.9.95 | 2 | 8 | 40 | 200+200 | ElasticSearch/GlusterFS |
| storage-node-0 | 192.168.9.96 | 2 | 8 | 40 | 200+200 | ElasticSearch/GlusterFS |
| storage-node-0 | 192.168.9.97 | 2 | 8 | 40 | 200+200 | ElasticSearch/GlusterFS |
| harbor | 192.168.9.89 | 2 | 8 | 40 | 200 | Harbor |
| 合计 | 8 | 22 | 84 | 320 | 2800 |
测试环境涉及软件版本信息
- 操作系统:CentOS-7.9-x86_64
- Ansible:2.8.20
- KubeSphere:3.3.0
- Kubernetes:v1.24.1
- GlusterFS:9.5.1
- ElasticSearch:7.17.5
- Harbor:2.5.1
简介
生产环境 KubeSphere 3.3.0 部署的 Kubernetes 集群在安全评估的时候发现安全漏洞,其中一项漏洞提示 SSL/TLS 协议信息泄露漏洞 (CVE-2016-2183)。
本文详细描述了漏洞产生原因、漏洞修复方案、漏洞修复的操作流程以及注意事项。
漏洞信息及修复方案
漏洞详细信息
漏洞报告中涉及漏洞 SSL/TLS 协议信息泄露漏洞 (CVE-2016-2183) 的具体信息如下:


漏洞分析
| 端口号 | 服务 |
|---|---|
| 2379/2380 | Etcd |
| 6443 | kube-apiserver |
| 10250 | kubelet |
| 10257 | kube-controller |
| 10259 | kube-scheduler |
# ETCD
[root@ks-k8s-master-0 ~]# ss -ntlup | grep Etcd | grep -v "127.0.0.1"
tcp LISTEN 0 128 192.168.9.91:2379 *:* users:(("Etcd",pid=1341,fd=7))
tcp LISTEN 0 128 192.168.9.91:2380 *:* users:(("Etcd",pid=1341,fd=5))
# kube-apiserver
[root@ks-k8s-master-0 ~]# ss -ntlup | grep 6443
tcp LISTEN 0 128 [::]:6443 [::]:* users:(("kube-apiserver",pid=1743,fd=7))
# kubelet
[root@ks-k8s-master-0 ~]# ss -ntlup | grep 10250
tcp LISTEN 0 128 [::]:10250 [::]:* users:(("kubelet",pid=1430,fd=24))
# kube-controller
[root@ks-k8s-master-0 ~]# ss -ntlup | grep 10257
tcp LISTEN 0 128 [::]:10257 [::]:* users:(("kube-controller",pid=19623,fd=7))
# kube-scheduler
[root@ks-k8s-master-0 ~]# ss -ntlup | grep 10259
tcp LISTEN 0 128 [::]:10259 [::]:* users:(("kube-scheduler",pid=1727,fd=7))
相关服务配置文件里使用了 IDEA、DES 和 3DES 等算法。
可以使用 Nmap 或是 openssl 进行验证,本文重点介绍 Nmap 的验证方式。
**注意:**openssl 的方式输出太多且不好直观判断,有兴趣的可以参考命令
openssl s_client -connect 192.168.9.91:10257 -cipher "DES:3DES"。
在任意节点安装测试工具 Nmap ,并执行测试命令。
错误的操作,仅用于说明选择 Nmap 版本很重要,实际操作中不要执行。
# 用 CentOS 默认源安装 nmap
yum install nmap
# 执行针对 2379 端口的 ssl-enum-ciphers 检测
nmap --script ssl-enum-ciphers -p 2379 192.168.9.91
# 结果输出如下
Starting Nmap 6.40 ( http://nmap.org ) at 2023-02-13 14:14 CST
Nmap scan report for ks-k8s-master-0 (192.168.9.91)
Host is up (0.00013s latency).
PORT STATE SERVICE
2379/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds
注意: 分析输出的结果发现并没有任何警告信息。原因是 Nmap 版本过低,需要 7.x 以上才可以。
正确的操作,实际执行的操作:
# 从 Nmap 官网,下载安装新版软件包
rpm -Uvh https://nmap.org/dist/nmap-7.93-1.x86_64.rpm
# 执行针对 2379 端口的 ssl-enum-ciphers 检测
# nmap -sV --script ssl-enum-ciphers -p 2379 192.168.9.91 (该命令输出更为详细也更加耗时,为节省篇幅使用下面简单输出的模式)
nmap --script ssl-enum-ciphers -p 2379 192.168.9.91
# 输出结果如下
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-13 17:28 CST
Nmap scan report for ks-k8s-master-0 (192.168.9.91)
Host is up (0.00013s latency).
PORT STATE SERVICE
2379/tcp open Etcd-client
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (ecdh_x25519) - C
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| compressors:
| NULL
| cipher preference: client
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 0.66 seconds
# 执行针对 2380 端口的 ssl-enum-ciphers 检测
nmap --script ssl-enum-ciphers -p 2380 192.168.9.91
# 输出结果如下
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-13 17:28 CST
Nmap scan report for ks-k8s-master-0 (192.168.9.91)
Host is up (0.00014s latency).
PORT STATE SERVICE
2380/tcp open Etcd-server
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (ecdh_x25519) - C
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| compressors:
| NULL
| cipher preference: client
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 0.64 seconds
# 执行针对 6443 端口的 ssl-enum-ciphers 检测(10250/10257/10259 端口扫描结果相同)
nmap --script ssl-enum-ciphers -p 6443 192.168.9.91
# 输出结果如下
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-13 17:29 CST
Nmap scan report for ks-k8s-master-0 (192.168.9.91)
Host is up (0.00014s latency).
PORT STATE SERVICE
6443/tcp open sun-sr-https
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| TLSv1.3:
| ciphers:
| TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| cipher preference: server
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 0.66 seconds
注意: 扫描结果中重点关注
warnings,64-bit block cipher 3DES vulnerable to SWEET32 attack。
漏洞修复方案
漏洞扫描报告中提到的修复方案并不适用于 Etcd、Kubernetes 相关服务。
针对于 Etcd、Kubernetes 等服务有效的修复手段是修改服务配置文件,禁用 3DES 相关的加密配置。
Cipher Suites 配置参数的选择,可以参考 ETCD 官方文档或是 IBM 私有云文档,网上搜到的很多配置都是参考的 IBM 的文档,想省事的可以拿来即用。
对于配置参数的最终选择,我采用了最笨的方法,即把扫描结果列出的 Cipher 值拼接起来。由于不清楚影响范围,所以保守的采用了在原有配置基础上删除 3DES 相关的配置。
下面的内容整理了 Cipher Suites 配置参数的可参考配置。
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_256_GCM_SHA384
使用该方案时必须严格按照以下顺序配置,我在测试时发现顺序不一致会导致 Etcd 服务反复重启。
ETCD_CIPHER_SUITES=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA
虽然 CIPHER 配置一样,但是在使用下面的顺序时,Etcd 服务反复重启,我排查了好久也没确定根因。也可能是我写的有问题,但是比对多次也没发现异常,只能暂时是认为是顺序造成的。
ETCD_CIPHER_SUITES=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384
注意: 只有 Etcd 服务受到顺序的影响,kube 相关组件顺序不同也没发现异常。
网上搜到的参考文档使用率最高的配置。实际测试也确实好用,服务都能正常启动,没有发现 Etcd 不断重启的现象。如果没有特殊需求,可以采用该方案,毕竟选择越少出安全漏洞的几率也越小。
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
漏洞修复
建议使用以下顺序修复漏洞:
- Etcd
- kube-apiserver
- kube-controller
- kube-scheduler
- kubelet
上面的操作流程中,重点是将 Etcd 的修复重启放在最前面执行。因为 kube 等组件的运行依赖于 Etcd,我在验证时最后升级的 Etcd,当 Etcd 启动失败后(反复重启),其他服务由于无法连接 Etcd,造成服务异常停止。所以先确保 Etcd 运行正常再去修复其他组件。
本文所有操作仅演示了一个节点的操作方法,多节点存在漏洞时请按组件依次执行,先修复完成一个组件,确认无误后再去修复另一个组件。
以下操作是我实战验证过的经验,仅供参考,生产环境请一定要充分验证、测试后再执行!
修复 Etcd
KubeSpere 3.3.0 采用二进制的方式部署的 Etcd,相关配置文件包含 /etc/systemd/system/Etcd.service 和 /etc/Etcd.env,参数配置保存在 /etc/Etcd.env。
# 在文件最后增加配置(用 cat 命令自动配置)
cat >> /etc/Etcd.env