在 kafka 的 broker 和 client 之间加入 SSL 双向认证

单向认证

首先实现单向的认证,即,client 对 broker 的认证。就像浏览器对服务器的认证一样。
注:密钥生成过程中的密码统一为123456

为broker生成keystore

第一步是为集群的每台机器生成密钥和证书,可以使用java的keytool来生产。我们将生成密钥到一个临时的密钥库,之后我们可以导出并用CA签名它。
keytool 使用可以参考java中Keytool的使用总结

keytool -genkey -keystore server.keystore.jks -alias localhost -validity 365 -keyalg RSA 

生成CA

通过第一步,集群中的每台机器都生成了一个证书来识别机器。但是,证书是未签名的,这意味着攻击者可以创建一个这样的证书来假装成任何机器。因此需要对这些证书进行签名来防止伪造。
在浏览网站的时候,使用HTTPS的网站的证书是由受信任的第三方颁发的,那么这里可以模拟一个假的CA中心,只要支持签名即可。
下面使用 OpenSSL 来生成一个私钥和一个证书,有效期为365天

openssl req -new -x509 -keyout ca-key -out ca-cert -days 365

然后会生成 ca-key 和 ca-cert 两个文件。

ca-key:模拟CA的私钥
ca-cert:模拟CA的证书
签名

用上一步生成的 CA 来签名第一步生成的证书,证书哪里来?从第一步生成的 server.keystore.jks 里面导出来。
导出证书,命名为 server.crt。

keytool -keystore server.keystore.jks -alias localhost -certreq -file server.crt

然后用刚才在第二步生成的CA的私钥对刚才导出的证书签名,签名后的证书命名为 server-signed.crt。

openssl x509 -req -CA ca-cert -CAkey ca-key -in server.crt -out server-signed.crt -days 365 -CAcreateserial -passin pass:test123

命令成功执行后,会生成两个文件server-signed.crt和 ca-cert.srl,ca-cert.srl 是 ca-cert的序列号文件,由-CAcreateserial参数生成的
最后,将CA的证书和已经签名的证书导入秘钥仓库:

keytool -keystore server.keystore.jks -alias CARoot -import -file ca-cert
keytool -keystore server.keystore.jks -alias localhost -import -file server-signed.crt

使 client 信任broker

为了使 client 信任broker,就需要将broker端的证书加入到客户端信任库里面,那么,按照道理来说,想让client信任所有的broker,那么就需要将所有的broker的证书添加到client的信任列表里面,那么就增加了不好操作性,比如说我新增了一个broker,难道还要挨个通知client增加信任吗?当然不可能。
证书签名体系中,有一个信任链的概念,就是说,如果使用证书A签名了证书B、C、D,那么只要信任了 A,就会信任B、C、D。这样来说就好办了,只要信任CA的证书,就可以信任所有它签名的证书

keytool -keystore client.truststore.jks -alias CARoot -import -file ca-cert

启动broker

在 config/server.properties 文件里面修改如下项:
listeners如果只支持SSL的话,就需要把 security.inter.broker.protocol 也配置为 SSL,即内部交流方式也为SSL。

listeners=PLAINTEXT://192.168.3.146:6667,SSL://192.168.3.146:6668
ssl.endpoint.identification.algorithm= #解决dns匹配问题 忽略对证书主机ip匹配
ssl.key.password=123456
ssl.keystore.location=/usr/hdp/3.1.4.0-315/kafka/conf/cert/server.keystore.jks
ssl.keystore.password=123456

查看日志,无错为启动成功。

启动客户端

这一步,需要把上面生成的 client.truststore.jks 放到客户端侧。
我使用的是java客户端,以消费者为例,连接broker的配置需要额外添加一下几行:

props.put("ssl.endpoint.identification.algorithm", "");
props.put("security.protocol", "SSL");
props.put("ssl.truststore.location", "E:\\cert\\client.truststore.jks");
props.put("ssl.truststore.password", "123456");

验证结果

经过测试,结果正确。
到这里,就可以实现client对broker的认证,如果是任意的一个broker,client是会拒绝连接的。但是,在kafka应用里面,好像并不是很实用,除了数据的加密。更多情况下,broker要防止任意的client进行连接,不能让client随意连接,那么就需要增加broker对client的认证。
其实原理和上面的是一样的,就是为client生成证书,然后让broker信任。增加broker对client的认证

增加broker对client的认证

首先生成各种证书

#为client生成证书
keytool -genkey -keystore client.keystore.jks -alias localhost -validity 365 -keyalg RSA
#为client生成CA
openssl req -new -x509 -keyout ca-key -out ca-cert -days 365
#导出证书
keytool -keystore client.keystore.jks -alias localhost -certreq -file client.crt
#签名
openssl x509 -req -CA ca-cert -CAkey ca-key -in client.crt -out client-signed.crt -days 365 -CAcreateserial -passin pass:123456
#导入
keytool -keystore client.keystore.jks -alias CARoot -import -file ca-cert
keytool -keystore client.keystore.jks -alias localhost -import -file client-signed.crt

keytool -keystore server.truststore.jks -alias CARoot -import -file ca-cert

配置broker

ssl.client.auth=required
ssl.truststore.location=/usr/hdp/3.1.4.0-315/kafka/conf/cert/server.truststore.jks
ssl.truststore.password=123456

启动。

配置client

在client端,增加连接参数:

props.put("ssl.key.password", "123456");
props.put("ssl.keystore.location", "E:\\cert\\client.keystore.jks");
props.put("ssl.keystore.password", "123456");

启动client

我以消费者为例,看是否能够连接成功,如果能够连接成功,那就也就意味着配置成功了。
幸运的,连接成功了,模拟发送数据也能够接收到。

总结

没啥可总结的,把配置合在一起贴一下吧。

broker 配置 server.properties:

listeners=PLAINTEXT://192.168.3.146:6667,SSL://192.168.3.146:6668
ssl.client.auth=required
ssl.endpoint.identification.algorithm=
ssl.key.password=123456
ssl.keystore.location=/usr/hdp/3.1.4.0-315/kafka/conf/cert/server.keystore.jks
ssl.keystore.password=123456
ssl.truststore.location=/usr/hdp/3.1.4.0-315/kafka/conf/cert/server.truststore.jks
ssl.truststore.password=123456

client

props.put("security.protocol", "SSL");
props.put("ssl.truststore.location", "E:\\cert\\client.truststore.jks");
props.put("ssl.truststore.password", "123456");
props.put("ssl.key.password", "123456");
props.put("ssl.keystore.location", "E:\\cert\\client.keystore.jks");
props.put("ssl.keystore.password", "123456");
props.put("ssl.endpoint.identification.algorithm", "");

整体执行的shell命令 重新整理

keytool -genkey -keystore server.keystore.jks -alias localhost -validity 3650 -keyalg RSA   -storepass 123456 -keypass 123456 -dname "CN=MyName, OU=MyOrgUnit, O=MyOrg, L=MyCity, ST=MyState, C=MyCountry"
openssl req -new -x509 -days 3650 -keyout ca-key.pem -out ca-cert.pem -passout pass:123456
keytool -keystore server.keystore.jks -alias localhost -certreq -file server.crt -storepass 123456 -keypass 123456
openssl x509 -req -CA ca-cert -CAkey ca-key -in server.crt -out server-signed.crt -days 3650 -CAcreateserial -passin pass:123456
openssl x509 -req -CA ca-cert.pem -CAkey ca-key.pem -in server.crt -out server-signed.crt -days 3650 -CAcreateserial -passin pass:123456
keytool -keystore server.keystore.jks -alias CARoot -import -file ca-cert.pem -storepass 123456 -keypass 123456
keytool -keystore server.keystore.jks -alias localhost -import -file server-signed.crt -storepass 123456 -keypass 123456
keytool -keystore client.truststore.jks -alias CARoot -import -file ca-cert.pem -storepass 123456 -keypass 123456

keytool -genkey -keystore client.keystore.jks -alias localhost -validity 3650 -keyalg RSA -storepass 123456 -keypass 123456 -dname "CN=MyName, OU=MyOrgUnit, O=MyOrg, L=MyCity, ST=MyState, C=MyCountry"
keytool -keystore client.keystore.jks -alias localhost -certreq -file client.crt -storepass 123456 -keypass 123456
openssl x509 -req -CA ca-cert -CAkey ca-key -in client.crt -out client-signed.crt -days 3650 -CAcreateserial -passin pass:123456
openssl x509 -req -CA ca-cert.pem -CAkey ca-key.pem -in client.crt -out client-signed.crt -days 3650 -CAcreateserial -passin pass:123456
keytool -keystore client.keystore.jks -alias CARoot -import -file ca-cert.pem -storepass 123456 -keypass 123456
keytool -keystore client.keystore.jks -alias localhost -import -file client-signed.crt -storepass 123456 -keypass 123456
keytool -keystore server.truststore.jks -alias CARoot -import -file ca-cert.pem -storepass 123456 -keypass 123456

Logo

Kafka开源项目指南提供详尽教程,助开发者掌握其架构、配置和使用,实现高效数据流管理和实时处理。它高性能、可扩展,适合日志收集和实时数据处理,通过持久化保障数据安全,是企业大数据生态系统的核心。

更多推荐