Kafka配置SSL加密传输

  |   0 评论   |   6,123 浏览

Kafka官方文档——安全

7.安全

7.1安全概述

在版本0.9.0.0中,Kafka社区增加了许多功能,单独或一起使用,提高了Kafka集群安全性。这些特性被认为是测试版的质量。目前支持以下安全措施:

  • 身份验证:从其它client(生产者和消费者),其他brokers 和工具使用SSL或SASL(Kerberos的),连接brokers

  • 从broker到ZooKeeper连接认证

  • client和broker之间的数据传输,broker之间,或者broker和工具之间的数据加密使用SSL(请注意,当启用SSL,会有性能下降,性能下降的幅度取决于CPU的类型和JVM实现。)

  • 对client的读/写操作的授权

  • 授权是可插拔的,支持与外部授权服务集成

  • 值得注意的是,安全是可选的 - 非安全集群的支持,以及认证,未经认证,加密和非加密的client的混合。下面的指南介绍如何配置,并在client和broker使用的安全功能。


7.2加密和使用SSL认证

Apache的Kafka允许client通过SSL连接。SSL默认情况下被禁止,但可以根据需要开启。

为每个Kafka的broker生成SSL密钥和证书

部署HTTPS的第一步骤是为集群中的每台机器生成密钥和证书。您可以使用Java的keytool实用程序来完成这个任务。我们首先将密钥生成到一个临时密钥库中,以使我们可以导出和后来与CA的签名

keytool -keystore server.keystore.jks -alias cxy7 -validity {validity} -genkey

在上面的命令中您需要指定两个参数:


  1. 密钥库:存储证书的密钥存储文件。密钥库文件包含证书的私钥; 因此,它需要被安全地保持。

  2. 有效期:证书的有效时间/天数。

确保公用名(CN)与服务器的完全限定域名(FQDN)精确相匹配。client拿CN与DNS域名进行比较以确保它确实连接到所需的服务器,而不是恶意的服务器。

创建自己的CA

第一步之后,集群中的每一台机器都有一个公私密钥对、一个标识该机器的证书,但是,这个证书,是未注册的,这意味着攻击者同样可以创建这样一个证书,并用来假装是任何机器。

因此,为集群中的每个机器的证书进行注册,以防止伪造是重要的。证书颁发机构(CA)负责签名证书。CA的就像一个颁发护照的政府,政府给每本护照印章,所以这样的护照很难伪造。其他政府进行验证,以确保护照是真实的。同样,CA给证书签名,并加密,保证签名证书很难伪造。因此,只要CA是真实的和值得信赖的,client确信他们正连接到正宗的机器。

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

生成的CA是一个公私密钥对和证书,用来给其它证书签名,

下一步是将生成的CA添加到**client的truststore**,这样client可以信任这个CA:

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

注:如果通过设置ssl.client.auth配置了Kafka的broker,要求client必须进行身份验证,那么你必须为Kafka的broker提供一个truststore,并且它应该拥有所有client已被签名的CA证书。

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

相比之下,在步骤1中存储每台机器自己的身份的keystore,truststore 存储了所有client应该信任的证书。将证书导入到一个truststore也意味着信任由该证书签名的证书。正如上面的比喻,信任政府(CA)也意味着信任它下发的所有护照(证书)。此属性称为信任链,当部署SSL到一个大Kafka群集上时它是特别有用的。您可以用一个CA为集群中的所有证书签名,并使所有信任该CA的机器共享一个truststore 这样,所有的机器可以为其他计算机进行认证。

签名证书

下一步是用第2步中产生的CA为第一步中产生的所有证书签名,第一步,需要将证书从keystore导出:

keytool -keystore server.keystore.jks -alias cxy7 -certreq -file cert-file

然后用CA签名:

openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days {validity} -CAcreateserial -passin pass:{ca-password}

最后,你需要把CA的证书和签过名的证书导入到keystore:

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

该参数的定义如下:

  1. keystore:密钥库的位置

  2. ca-cert:该CA证书

  3. ca-key:CA的私钥

  4. ca-password:CA的密码

  5. cert-file:该服务器已导出的、未签名的证书

  6. cert-signed:服务器的已签名的证书

这里是上述所有步骤的bash脚本的一个例子。请注意,命令中假设密码是cxy71234,所以使用这个密码或在运行它之前修改它。

 #!/bin/bash
 #Step 1
 keytool -keystore server.keystore.jks -alias cxy7 -validity 365 -genkey
 #Step 2
 openssl req -new -x509 -keyout ca-key -out ca-cert -days 365
 keytool -keystore server.truststore.jks -alias CARoot -import -file ca-cert
 keytool -keystore client.truststore.jks -alias CARoot -import -file ca-cert
 #Step 3
 keytool -keystore server.keystore.jks -alias cxy7 -certreq -file cert-file
 openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 365 -CAcreateserial -passin pass:cxy71234
 keytool -keystore server.keystore.jks -alias CARoot -import -file ca-cert
 keytool -keystore server.keystore.jks -alias cxy7 -import -file cert-signed

配置Kafka的Brokers

Kafka broker支持在多个端口上监听连接。我们需要配置server.properties以下属性,其中必须有一个或多个逗号分隔值:

listeners

如果broker间的通信未启用SSL(请参阅下面的如何启用它),PLAINTEXT 和SSL端口都将是必要的。

listeners=PLAINTEXT://host.name:port,SSL://host.name:port

在broker端需要配置下面的SSL

 ssl.keystore.location=/var/private/ssl/kafka.server.keystore.jks
 ssl.keystore.password=cxy71234
 ssl.key.password=cxy71234
 ssl.truststore.location=/var/private/ssl/kafka.server.truststore.jks
 ssl.truststore.password=cxy71234

下面是值得考虑的可选的设置:

  • ssl.client.auth=none ("required" => 客户端必须进行认证, "requested" => client authentication is requested没有证书的client仍然可以连接. requested的用法是令人气馁的,因为它提供了虚假的安全感,配置错误的client仍然可以连接成功

  • ssl.cipher.suites (Optional). A cipher suite is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS or SSL network protocol. (Default is an empty list)

  • ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1 (list out the SSL protocols that you are going to accept from clients. Do note that SSL is deprecated in favor of TLS and using SSL in production is not recommended)

  • ssl.keystore.type=JKS

  • ssl.truststore.type=JKS


如果要启用Brokers间通信SSL,添加以下到broker的properties文件(默认为PLAINTEXT)

security.inter.broker.protocol = SSL

由于一些国家的进口规定,Oracle默认情况下限制了加密算法的强度。如果需要更强的算法(例如AES 256位密钥),JCE文件必须获得并安装在JDK / JRE。请参阅 JCA提供的文档获取更多信息。


一旦你启动了broker,你应该能够在server.log看到

with addresses: PLAINTEXT -> EndPoint(192.168.64.1,9092,PLAINTEXT),SSL -> EndPoint(192.168.64.1,9093,SSL)

要快速检查服务器的keystore and truststore是否正确安装,您可以运行下面的命令

openssl s_client -debug -connect cxy7:9093 -tls1

(注:TLSv1应该在ssl.enabled.protocols下面)

在此命令的输出中,你应该看到服务器证书的输出:

-----BEGIN CERTIFICATE-----
{variable sized random bytes}
-----END CERTIFICATE-----
subject=/C=US/ST=CA/L=Santa Clara/O=org/OU=org/CN=Sriharsha Chintalapani
issuer=/C=US/ST=CA/L=Santa Clara/O=org/OU=org/CN=kafka/emailAddress=cxy7@cxy7.com

如果证书没有显示出来,或有任何其他错误消息,说明你的密钥库设置不正确。

配置client

SSL只在新的Kafka Producer 和 Consumer中被支持,不支持旧的API。。producer and consumer的配置必须相同

如果broker当中不需要对client进行身份验证,那么下面是一个最小的配置示例:


security.protocol=SSL
ssl.truststore.location=/var/private/ssl/kafka.client.truststore.jks
ssl.truststore.password=cxy71234

如果需要client身份验证,则必须像在步骤1中创建一个keystore ,下面还必须配置:

 ssl.keystore.location=/var/private/ssl/kafka.client.keystore.jks
 ssl.keystore.password=cxy71234
 ssl.key.password=cxy71234

根据自己的需求和Broker配置所需的其他配置设置:

  • ssl.provider(可选)。用于SSL连接的安全性提供者的名称。默认值是JVM的默认安全提供商。

  • ssl.cipher.suites(可选)。密码套件是一个认证、加密,MAC和密钥交换算法的名字集合,用于TLS或SSL网络协议的网络连接的安全设置认证。

  • ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1. It should list at least one of the protocols configured on the broker side

  • ssl.truststore.type=JKS

  • ssl.keystore.type=JKS

使用控制台生产者和控制台消费者的例子:

 kafka-console-producer.sh --broker-list cxy7:9093 --topic cxy7 --producer.config client-ssl.properties
 kafka-console-consumer.sh --bootstrap-server cxy7:9093 --topic cxy7 --new-consumer --consumer.config client-ssl.properties

制作证书

生成证书

为集群中的每台机器生成密钥和证书

keytool -keystore s2.keystore.jks -alias s2.cxy7.com -validity 365 -genkey
keytool -keystore s1.keystore.jks -alias s1.cxy7.com -validity 365 -genkey

注意下面这项要与机器的完全限定域名(FQDN)相同

您的名字与姓氏是什么?
[Unknown]: s1.cxy7.com

生成两个keystore.jks文件,其中包含一个公私密钥对、一个标识该机器的证书

生成CA

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

其中ca-key是公私密钥对,ca-cert是服务器证书

签名证书

将证书从keystore导出

keytool -keystore s2.keystore.jks -alias s2.cxy7.com -certreq -file s2-cert-file
keytool -keystore s1.keystore.jks -alias s1.cxy7.com -certreq -file s1-cert-file

用CA签名

openssl x509 -req -CA ca-cert -CAkey ca-key -in s2-cert-file -out s2-cert-signed -days 365 -CAcreateserial -passin pass:123456
openssl x509 -req -CA ca-cert -CAkey ca-key -in s1-cert-file -out s1-cert-signed -days 365 -CAcreateserial -passin pass:123456

创建truststore

truststore存储了所有其应该信任的证书。将证书导入到一个truststore也意味着信任由该证书签名的证书。

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

将签过名的证书导入到truststore

keytool -keystore s2.truststore.jks -alias s2.cxy7.com -import -file s2-cert-signed
keytool -keystore s2.truststore.jks -alias s1.cxy7.com -import -file s1-cert-signed
keytool -keystore s1.truststore.jks -alias s1.cxy7.com -import -file s1-cert-signed
keytool -keystore s1.truststore.jks -alias s2.cxy7.com -import -file s2-cert-signed

此处配置的是相互信任,s2信任s1的证书,s1信任s2的证书

分发证书

服务端

将s2.keystore.jks、s2.truststore.jks发送到Server端的/usr/local/ssl目录

客户端

将s1.keystore.jks、s1.truststore.jks发送到Client端的/usr/local/ssl目录

配置Kafka

Broker

listeners=PLAINTEXT://:9092,SSL://:9093
ssl.client.auth=required
ssl.keystore.location=/usr/local/ssl/s2.keystore.jks
ssl.keystore.password=123456
ssl.key.password=123456
ssl.truststore.location=/usr/local/ssl/s2.truststore.jks
ssl.truststore.password=123456
ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1
ssl.keystore.type=JKS
ssl.truststore.type=JKS

Client

security.protocol=SSL
ssl.truststore.location=/usr/local/ssl/s1.truststore.jks
ssl.truststore.password=123456
ssl.keystore.location=/usr/local/ssl/s1.keystore.jks
ssl.keystore.password=123456
ssl.key.password=123456
ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1
ssl.truststore.type=JKS
ssl.keystore.type=JKS

可以写在一个单独的配置文件client-ssl.properties中,可供Producer和Consumer同时使用

测试

bin/kafka-topics.sh --zookeeper cxy7:2181 --create --topic c1 --partitions 1 --replication-factor 1
bin/kafka-console-producer.sh --producer.config config/client-ssl.properties --topic c1 -broker-list s2.cxy7.com:9093
bin/kafka-console-consumer.sh --topic c1 --new-consumer --consumer.config config/client-ssl.properties --bootstrap-server cxy7:9093

keytool的使用

查看证书库中的证书

[root@s1 ssl]# keytool -list -keystore s1.keystore.jks 
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
s1.cxy7.com, 2016-4-15, PrivateKeyEntry, 
证书指纹 (SHA1): 43:38:87:84:14:C6:24:CC:ED:21:BD:34:45:4A:AC:ED:D6:57:E3:9D
[root@s1 ssl]# keytool -list -keystore s1.truststore.jks 
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 2 个条目
caroot, 2016-4-15, trustedCertEntry, 
证书指纹 (SHA1): 24:52:CD:83:FA:22:5B:26:54:28:54:94:95:FC:69:42:7D:83:56:21
s2.cxy7.com, 2016-4-15, trustedCertEntry, 
证书指纹 (SHA1): A8:82:DD:12:C5:8B:7C:DF:05:69:77:30:62:24:A9:E2:E3:DA:A9:20
[root@s2 ssl]# keytool -list -keystore s2.keystore.jks
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
s2.cxy7.com, 2016-4-15, PrivateKeyEntry, 
证书指纹 (SHA1): 02:D5:E2:37:1D:9A:49:82:E0:76:B6:0D:67:90:8A:D5:7F:72:6A:2D
[root@s2 ssl]# keytool -list -keystore s2.truststore.jks 
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 2 个条目
caroot, 2016-4-15, trustedCertEntry, 
证书指纹 (SHA1): 24:52:CD:83:FA:22:5B:26:54:28:54:94:95:FC:69:42:7D:83:56:21
s1.cxy7.com, 2016-4-15, trustedCertEntry, 
证书指纹 (SHA1): 21:85:BF:5B:14:8F:7F:B9:40:56:36:7F:37:F4:AB:3D:62:26:4E:B2

删除证书

keytool -delete -alias dx.cxy7.com -keystore dx.truststore.jks


读后有收获可以支付宝请作者喝咖啡