3. TLS/SSL加密通信

在 Kafka 集群中,TLS/SSL 承担的不只是“把数据加密”这一件事,它同时完成三件事:加密传输内容、验证对端身份、为后续 SASL 认证提供安全信道。理解这一点非常关键,因为很多配置错误并不是加密算法的问题,而是证书链、主机名校验或信任库方向搞反了。本节围绕 Broker、客户端与 REST Proxy 三个角色,把证书签发、密钥库/信任库生成、服务端与客户端配置、以及验证方法串成一条可执行的链路。

一、先厘清密钥库与信任库的方向

Kafka 使用 Java 的 JSSE 体系,因此证书以 JKS 或 PKCS12 格式存放。两个库的职责必须分清:

  • 密钥库(keystore):存放自己的私钥和证书,用于向对端证明“我是谁”。Broker 的 keystore 里放 Broker 证书,客户端的 keystore 里放客户端证书(仅双向认证时需要)。
  • 信任库(truststore):存放信任的 CA 证书,用于验证对端证书是否由可信 CA 签发。Broker 的 truststore 放 CA 证书以验证客户端,客户端的 truststore 放 CA 证书以验证 Broker。
记忆口诀:keystore 证明自己,truststore 验证别人。配置时若把两者写反,典型现象是握手报 unable to find valid certification path to requested target。

二、证书签发与库文件生成

生产环境应使用企业 CA 或自建 CA 签发,而不是直接用自签名证书。下面以自建 CA 为例,演示一条完整链路(示例参数,实际请替换为你的域名与密码策略)。

# 1. 生成 CA 私钥与自签根证书
openssl req -new -x509 -keyout ca.key -out ca.crt -days 3650 \
  -subj "/CN=Kafka-CA,OU=Security,O=Example"

# 2. 为 Broker 生成私钥与 CSR(注意 CN/SAN 必须是客户端可解析的主机名)
keytool -genkeypair -alias broker1 -keyalg RSA -keysize 2048 \
  -keystore broker1.keystore.jks -storetype PKCS12 \
  -validity 3650 -dname "CN=broker1.example.com" \
  -ext SAN=DNS:broker1.example.com

keytool -certreq -alias broker1 -keystore broker1.keystore.jks \
  -file broker1.csr

# 3. 用 CA 签发 Broker 证书
openssl x509 -req -CA ca.crt -CAkey ca.key -in broker1.csr \
  -out broker1.crt -days 3650 -CAcreateserial

# 4. 将 CA 根证书与签发证书导入 Broker keystore,形成完整链
keytool -importcert -alias ca -file ca.crt -keystore broker1.keystore.jks -noprompt
keytool -importcert -alias broker1 -file broker1.crt -keystore broker1.keystore.jks

# 5. 生成 Broker truststore(信任客户端证书的 CA)
keytool -importcert -alias ca -file ca.crt -keystore broker.truststore.jks -noprompt

这里有一个高频踩坑点:Broker 证书的 SAN 必须包含客户端实际连接使用的主机名。如果客户端用 broker1.example.com:9093 连接,而证书 SAN 只有 localhost,即使证书链正确,握手仍会因主机名校验失败而中断。

三、Broker 端 TLS 配置

Broker 通过 listeners 与 advertised.listeners 暴露 TLS 端口,并指定安全协议映射。以下为 server.properties 关键片段:

listeners=SSL://broker1.example.com:9093,PLAINTEXT://broker1.example.com:9092
advertised.listeners=SSL://broker1.example.com:9093,PLAINTEXT://broker1.example.com:9092
ssl.keystore.location=/etc/kafka/ssl/broker1.keystore.jks
ssl.keystore.password=ChangeIt123
ssl.key.password=ChangeIt123
ssl.truststore.location=/etc/kafka/ssl/broker.truststore.jks
ssl.truststore.password=ChangeIt123
ssl.client.auth=required
ssl.enabled.protocols=TLSv1.2,TLSv1.3
ssl.endpoint.identification.algorithm=https

ssl.client.auth 有三个取值:none(仅服务端认证,单向 TLS)、requested(请求但不强制客户端证书)、required(强制双向认证)。若后续要用 mTLS 做客户端身份认证,必须设为 required。ssl.endpoint.identification.algorithm=https 表示启用主机名校验,生产环境不应关闭。

四、客户端与 REST Proxy 配置

Java 客户端通过 security.protocol=SSL 启用 TLS,并指定 truststore 验证 Broker。若 Broker 要求双向认证,客户端还需提供自己的 keystore:

security.protocol=SSL
ssl.truststore.location=/etc/kafka/ssl/client.truststore.jks
ssl.truststore.password=ChangeIt123
ssl.keystore.location=/etc/kafka/ssl/client.keystore.jks
ssl.keystore.password=ChangeIt123
ssl.key.password=ChangeIt123

REST Proxy 作为独立进程,需要同时配置对上游 Broker 的 TLS和对下游客户端的 TLS。前者用 ssl.truststore.* 验证 Broker,后者用 ssl.keystore.* 向客户端证明自己:

# 连接 Broker 的 TLS
ssl.truststore.location=/etc/kafka/ssl/restproxy.truststore.jks
ssl.truststore.password=ChangeIt123

# 对外提供 HTTPS 服务
ssl.keystore.location=/etc/kafka/ssl/restproxy.keystore.jks
ssl.keystore.password=ChangeIt123
ssl.key.password=ChangeIt123

REST Proxy 的 HTTPS 监听端口由 listeners=https://0.0.0.0:8086 指定。注意:REST Proxy 的 keystore 证书 SAN 必须匹配客户端访问它的域名,否则浏览器或 curl 会报证书不匹配。

五、验证与排障

配置完成后,不要直接启动业务,先用工具验证握手链路。以下命令可快速判断证书链与主机名是否正确:

# 验证 Broker TLS 握手与证书链
openssl s_client -connect broker1.example.com:9093 \
  -CAfile ca.crt -servername broker1.example.com

# 验证 REST Proxy HTTPS
curl --cacert ca.crt https://restproxy.example.com:8086/topics

若握手失败,按以下顺序排查:证书链是否完整(是否漏导入 CA)、SAN 是否匹配访问域名、truststore 是否放对方向、密码是否一致、TLS 协议版本是否被双方共同支持。下面这张图把三个角色的证书流向与信任关系集中呈现,便于对照检查。

Kafka TLS 证书流向与信任关系 自建 CA ca.crt / ca.key Broker keystore: broker1 证书+私钥 truststore: CA 根证书 端口: SSL://9093 client.auth=required Kafka 客户端 truststore: CA 根证书 keystore: client 证书(mTLS) security.protocol=SSL 验证 Broker 主机名 REST Proxy truststore: CA 根证书 keystore: restproxy 证书 listeners=https://:8086 对外提供 HTTPS 签发 Broker 证书 签发客户端证书 签发 REST Proxy 证书 TLS 握手 TLS 握手 信任方向说明 CA 签发证书(证书链来源) 客户端 → Broker 握手 REST Proxy → Broker keystore 证明自己 · truststore 验证别人 · SAN 必须匹配访问域名

最后强调一个工程习惯:证书有效期、密码轮换和 CA 变更都应纳入运维流程。Broker 证书过期会导致整个集群不可用,建议在到期前 30 天完成续签并滚动重启。把证书管理当作配置的一部分,而不是一次性任务,TLS 才能真正成为可靠的安全底座。