kafka使用ssl加密和认证

1 篇文章 0 订阅
1 篇文章 0 订阅

  学习过kafka的人都知道,kafka的默认端口是9092,且消费kafka消息的命令也极其简单。现在随着kafka在消息传输应用中使用的越来越广泛,那么生产环境中消息的保密性也变的重要了,所以生产环境使用ssl来认证kafka是比较必要的。Apache kafka 允许clinet通过SSL连接,SSL默认是不可用的,需手动开启。

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

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

上面  server.keystore.jks 与 {validity} 均为自定义参数:

keystore: 密钥仓库存储证书文件。密钥仓库文件包含证书的私钥(保证私钥的安全)。

validity: 证书的有效时间,天

如我输入命令如下:依次是 密码—重输密码—名与姓—组织单位—组织名—城市—省份—国家两位代码—密码—重输密码,后面告警不用管,此步骤要注意的是,名与姓这一项必须输入域名,如 "localhost",切记不可以随意写,我曾尝试使用其他字符串,在后面客户端生成证书认证的时候一直有问题。

keytool -keystore server.keystore.jks -alias localhost -validity 3650 -genkey
Enter keystore password:
Re-enter new password:
What is your first and last name?
  [Unknown]:  localhost
What is the name of your organizational unit?
  [Unknown]:  CH-kafka
What is the name of your organization?
  [Unknown]:  kafkadev
What is the name of your City or Locality?
  [Unknown]:  shanghai
What is the name of your State or Province?
  [Unknown]:  shanghai
What is the two-letter country code for this unit?
  [Unknown]:  CH
Is CN=localhost, OU=CH-kafka, O=kafkadev, L=shanghai, ST=shanghai, C=CH correct?
  [no]:  yes

Enter key password for <localhost>
	(RETURN if same as keystore password):  
Re-enter new password: 

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore server.keystore.jks -destkeystore server.keystore.jks -deststoretype pkcs12".

完成上面步骤,可使用命令 keytool -list -v -keystore server.keystore.jks 来验证生成证书的内容

2、通过第一步,集群中的每台机器都生成一对公私钥,和一个证书来识别机器。但是,证书是未签名的,这意味着攻击者可以创建一个这样的证书来伪装成任何机器。

因此,通过对集群中的每台机器进行签名来防止伪造的证书。证书颁发机构(CA)负责签名证书。CA的工作机制像一个颁发护照的政府。政府印章(标志)每本护照,这样护照很难伪造。其他政府核实护照的印章,以确保护照是真实的。同样,CA签名的证书和加密保证签名证书很难伪造。因此,只要CA是一个真正和值得信赖的权威,client就能有较高的保障连接的是真正的机器。如下,生成的CA是一个简单的公私钥对证书,用于签名其他的证书,下面为输入命令,依次提示输入为 密码—重输密码—国家两位代码—省份—城市—名与姓—组织名—组织单位—名与姓(域名)—邮箱 ,此输入步骤与上面生成证书世输入步骤相反,输入值要与第一步一致,邮箱可不输入

openssl req -new -x509 -keyout ca-key -out ca-cert -days 3650
Generating a 2048 bit RSA private key
.........................................................................+++
..................+++
writing new private key to 'ca-key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CH
State or Province Name (full name) []:shanghai
Locality Name (eg, city) [Default City]:shanghai
Organization Name (eg, company) [Default Company Ltd]:kafkadev
Organizational Unit Name (eg, section) []:CH-kafka
Common Name (eg, your name or your server's hostname) []:localhost
Email Address []:

将生成的CA添加到**clients' truststore(客户的信任库)**,以便client可以信任这个CA:

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

3、签名证书,用步骤2生成的CA来签名所有步骤1生成的证书,首先,你需要从密钥仓库导出证书:

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

然后用CA签名:{validity},{ca-password} 两个为参数,

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

最后,你需要导入CA的证书和已签名的证书到密钥仓库:
 

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

上文中的各参数解释如下:

  1. keystore: 密钥仓库的位置
  2. ca-cert: CA的证书
  3. ca-key: CA的私钥
  4. ca-password: CA的密码
  5. cert-file: 出口,服务器的未签名证书
  6. cert-signed: 已签名的服务器证书

上面步骤所有执行脚本如下:注意密码修改为自己的密码,以防混淆,所有步骤密码最好设为同一个

#!/bin/bash
#Step 1
keytool -keystore server.keystore.jks -alias localhost -validity 3650 -keyalg RSA -genkey
#Step 2
openssl req -new -x509 -keyout ca-key -out ca-cert -days 3650
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 localhost -certreq -file cert-file
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 3650 -CAcreateserial -passin pass:123456
keytool -keystore server.keystore.jks -alias CARoot -import -file ca-cert
keytool -keystore server.keystore.jks -alias localhost -import -file cert-signed
#Step 4
keytool -keystore client.keystore.jks -alias localhost -validity 3650 -keyalg RSA -genkey

4、配置kafka broker,通过server.properteis 配置,最少监听1个端口,用逗号分隔

如果broker之间通讯未启用SSL(参照下面,启动它),PLAINTEXT和SSL端口是必须要配置,这里我使用了9093为ssl端口,如果想要broker内部通信也使用ssl 要配置 security.inter.broker.protocol=SSL(不建议,kakfa内部通信使用ssl可能影响速度)

listeners=PLAINTEXT://host.name:9092,SSL://host.name:9093

SSL配置 

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

 5、配置Kafka客户端,创建client-ssl.properties 文件,内容如下

security.protocol=SSL
ssl.truststore.location=/home/server.keystore.jks
ssl.truststore.password=123456

消费命令如下:

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

有时候我们会用python来消费kafka的数据,python KafkaConsumer消费消息使用的是 pem证书,此时要使用原来的jks证书生成pem证书,如下命令

keytool -exportcert -alias localhost -keystore server.keystore.jks -rfc -file certificate.pem
keytool -exportcert -alias CARoot -keystore server.keystore.jks -rfc -file ca-root.pem

python中消费主要代码如下:

def startConsumer():
    consumer = KafkaConsumer('test_topic',
                             bootstrap_servers='...',
                             group_id='test-gp',
                             security_protocol='SSL',
                             auto_offset_reset='earliest',
                             ssl_check_hostname=False,
                             ssl_cafile='/home/ssl/ca-root.pem',
                             ssl_certfile='/home/ssl/certificate.pem')
    for message in consumer: 
        value = message.value.decode()
        print(value)

 

本文参照了博客 https://www.orchome.com/171,亲自动手实践过,有些地方有修改,有些地方原文写的更多一些

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值