3、Kafka SSL配置:Broker端SSL配置、客户端SSL配置、单向认证与双向认证
说到Kafka的安全配置,SSL这块是绕不过去的坎。很多团队一开始图省事,用明文端口跑着,直到某天运维发现某个消费者居然能随意消费所有Topic的数据——嗯,这时候才想起来要上加密和认证。
SSL配置说白了就两件事:传输加密和身份认证。传输加密保证数据在网络上不被窃听,身份认证保证连接进来的客户端确实是它声称的那个身份。我习惯把SSL配置拆成三个层面来讲:Broker端怎么配、客户端怎么配、以及单向认证和双向认证的区别。
核心要点:SSL配置的关键在于证书链的信任关系。单向认证只验证Broker身份,双向认证还要验证客户端身份。生产环境建议至少使用单向认证,敏感业务必须上双向认证。
3.1 Broker端SSL配置
Broker端配置SSL,核心就是告诉Kafka:你要监听SSL端口,并且把你的证书和私钥准备好。我见过不少新手在这步卡住,其实说白了就三个步骤。
3.1.1 生成Broker证书
首先得给Broker生成一个证书。你可以用自签名证书,也可以用CA签发的证书。测试环境自签名就够了,生产环境我建议用内部CA或者商业CA。
# 生成Broker的keystore,包含私钥和证书
keytool -keystore kafka.server.keystore.jks \
-alias localhost \
-validity 365 \
-genkey -keyalg RSA \
-storepass changeit \
-keypass changeit \
-dname "CN=kafka-broker-01, OU=Dev, O=MyCompany, L=Beijing, ST=Beijing, C=CN"
这里有个坑——CN字段的值。客户端连接时如果用了主机名验证,CN必须和Broker的主机名匹配。我曾经遇到过因为CN写成了IP地址,结果客户端死活连不上,折腾了半天才发现是主机名校验的问题。
3.1.2 配置server.properties
证书生成好之后,在server.properties里配置SSL监听器和证书路径。我个人习惯把SSL配置单独放在一个区域,方便维护。
# 监听器配置
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9093
advertised.listeners=PLAINTEXT://kafka-broker-01:9092,SSL://kafka-broker-01:9093
# SSL基础配置
ssl.keystore.location=/etc/kafka/secrets/kafka.server.keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeit
# 信任证书配置(用于验证客户端证书)
ssl.truststore.location=/etc/kafka/secrets/kafka.server.truststore.jks
ssl.truststore.password=changeit
# 客户端认证模式:none(单向)/ requested(可选)/ required(双向)
ssl.client.auth=required
注意:ssl.client.auth参数决定了认证模式。设置为none就是单向认证,只验证Broker;设置为required就是双向认证,客户端也必须提供证书。生产环境如果开启双向认证,记得先确认所有客户端都配好了证书,否则连不上。
3.1.3 配置SSL协议和密码套件
嗯,这里要提一下安全性的细节。默认的SSL配置可能不够安全,我建议显式指定协议版本和密码套件。
# 只允许TLS 1.2和TLS 1.3
ssl.protocol=TLS
ssl.enabled.protocols=TLSv1.2,TLSv1.3
# 限制密码套件,禁用弱加密
ssl.cipher.suites=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
你想想看,如果还开着TLS 1.0或者弱密码套件,那跟没加密有什么区别?我在一次安全审计中就吃过这个亏,被安全团队要求整改,后来就把密码套件白名单写死了。
3.2 客户端SSL配置
客户端配置相对简单一些,主要取决于你用单向认证还是双向认证。咱们先看单向认证的情况。
3.2.1 单向认证的客户端配置
单向认证下,客户端只需要验证Broker的证书。所以客户端只需要配置truststore,里面放CA证书或者Broker证书。
# 生成客户端的truststore,导入CA证书
keytool -keystore kafka.client.truststore.jks \
-alias CARoot \
-import -file ca-cert \
-storepass changeit -noprompt
然后在客户端代码或者配置文件里这样配:
# 生产者/消费者配置
security.protocol=SSL
ssl.truststore.location=/path/to/kafka.client.truststore.jks
ssl.truststore.password=changeit
# 可选:关闭主机名验证(测试环境用)
# ssl.endpoint.identification.algorithm=
小技巧:ssl.endpoint.identification.algorithm这个参数默认是HTTPS,会验证Broker证书的CN是否匹配主机名。测试环境可以置空跳过验证,但生产环境千万别关——关了等于放弃了防中间人攻击的能力。
3.2.2 双向认证的客户端配置
双向认证下,客户端不仅要验证Broker,还要向Broker证明自己的身份。所以客户端需要配置keystore,把自己的证书发给Broker。
# 生成客户端的keystore
keytool -keystore kafka.client.keystore.jks \
-alias client \
-validity 365 \
-genkey -keyalg RSA \
-storepass changeit \
-keypass changeit \
-dname "CN=kafka-client-01, OU=Dev, O=MyCompany, L=Beijing, ST=Beijing, C=CN"
# 用CA签名客户端证书
keytool -keystore kafka.client.keystore.jks \
-alias client \
-certreq -file client-cert-req \
-storepass changeit
# 然后用CA签名...(省略CA签名步骤)
# 导入CA证书和签名后的客户端证书
keytool -keystore kafka.client.keystore.jks \
-alias CARoot \
-import -file ca-cert \
-storepass changeit -noprompt
keytool -keystore kafka.client.keystore.jks \
-alias client \
-import -file client-cert-signed \
-storepass changeit -noprompt
客户端配置变成这样:
security.protocol=SSL
ssl.truststore.location=/path/to/kafka.client.truststore.jks
ssl.truststore.password=changeit
ssl.keystore.location=/path/to/kafka.client.keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeit
3.3 单向认证 vs 双向认证
这两种模式怎么选?我直接说结论:大部分场景单向认证就够了。为什么?因为传输加密已经保证了数据安全,单向认证保证了客户端连接的是真正的Broker。但如果你需要精确控制谁可以连接Kafka,那就得上双向认证。
| 对比维度 | 单向认证 | 双向认证 |
|---|---|---|
| 验证方向 | 客户端验证Broker | 双方互相验证 |
| 客户端证书 | 不需要 | 需要 |
| 配置复杂度 | 低 | 高 |
| 证书管理成本 | 低(只需管理Broker证书) | 高(每个客户端都要证书) |
| 安全等级 | 中(防窃听、防伪造Broker) | 高(防窃听、防伪造、防未授权客户端) |
| 适用场景 | 内部网络、信任客户端环境 | 跨网络、多租户、敏感数据 |
我的建议:如果公司内部网络相对安全,单向认证配合ACL(后面章节会讲)就够用了。如果Kafka暴露在公网或者跨机房通信,或者有合规要求(比如金融、医疗),必须上双向认证。我曾经帮一个金融客户做架构,他们要求每个微服务都有独立的客户端证书,证书过期自动轮换——那套体系虽然维护成本高,但安全团队非常满意。
3.4 常见问题与避坑指南
SSL配置看着简单,实际踩坑的人不少。我整理了几个高频问题。
3.4.1 证书过期
证书过期是最常见的问题。Broker证书过期了,所有客户端都连不上。我建议在运维监控里加上证书过期告警,提前30天通知。
# 检查证书过期时间
keytool -list -v -keystore kafka.server.keystore.jks -storepass changeit | grep "Valid"
3.4.2 主机名验证失败
客户端报SSLHandshakeException: No name matching xxx found,十有八九是CN不匹配。要么改证书CN,要么在客户端关掉主机名验证(不推荐生产用)。
3.4.3 密码套件不兼容
Broker和客户端支持的密码套件对不上,也会握手失败。检查一下两端ssl.cipher.suites配置是否一致。
曾经踩过的坑:有一次我在升级Kafka集群时,把Broker的TLS版本从1.2改成了只支持1.3,结果老版本的Java客户端(JDK 8早期版本)不支持TLS 1.3,所有消费者都连不上了。从那以后,我每次改SSL配置都会先灰度一台Broker,确认客户端兼容性再全量推。
3.5 验证SSL配置是否生效
配置完了怎么验证?我一般用OpenSSL命令行工具快速测试。
# 测试SSL连接
openssl s_client -connect kafka-broker-01:9093 -tls1_2
# 如果能看到"BEGIN CERTIFICATE"和"Verify return code: 0 (ok)",说明SSL配置正确
也可以用Kafka自带的工具验证:
# 用控制台生产者测试SSL连接
kafka-console-producer.sh \
--broker-list kafka-broker-01:9093 \
--topic test-topic \
--producer.config /path/to/ssl-client.properties
嗯,到这里SSL配置的核心内容就讲完了。记住一句话:证书是信任的基石,配置是安全的保障。别嫌麻烦,该配的配好,该监控的监控起来,后面才能睡得安稳。