Kafka再探3A

本篇博文主要内容为Kafka中SSL相关加密认证配置
实验环境延续上篇初探中的compose,配置同样写在环境变量中

Easyrsa进行CA管理

安装部署

  • easyrsa是openvpn项目研发的CA管理工具,简化了用openssl签发管理证书的过程
  • keytool是jdk自带的密钥证书处理工具,主要用来处理java程序常用的证书格式jks
    • 一个jks文件中可以存储私钥、对应证书和CA证书
  • 本文使用的ca管理容器镜像如下
FROM alpine:3.10
  
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add easy-rsa openjdk10 bash && \
    mkdir /pki && echo "alias easyrsa=/usr/share/easy-rsa/easyrsa" > /root/.bashrc

WORKDIR /pki
CMD sleep 10000
  • 主要内容除了安装jdk和easyrsa外,还有建立别名,因为把easyrsa二进制程序拷贝到其他的地方,或者软链到其他地方,使用起来会有找不到各种文件的问题
    • Easy-RSA error: Failed to update /etc/openvpn/pki/safessl-easyrsa.cnf
    • Easy-RSA error: Unknown cert type 'server'
  • 容器的编排同样通过compose
    • 通过volume把pki管理的根目录传出容器,从而被其他容器挂载,从而利用其中签发证书与私钥
services:
  keytool:
    build:
      context: ./keytool/
    volumes:
      - "./keytool/pki:/pki"
    networks:
      ninestates: {}
省略其他service

运行使用

pem格式部分
  • 进入容器 docker exec -it infra_keytool_1 bash

  • 初始化pki文件夹 easyrsa init-pki

  • 创建新的CA名为caroot echo caroot | easyrsa build-ca nopass

  • 创建私钥、创建签发请求、签发证书一条龙

    • easyrsa --batch --subject-alt-name="DNS:broker1.kafka.cluster,IP:172.26.0.2" build-server-full broker1 nopass
      *build-server-full 服务端证书
    • build-client-full 客户端证书
    • build-serverClient-full 客户端+服务端证书
    • 那么问题来了,客户端证书、服务端证书的区别是什么?
      1. 客户端证书只用于签名校验身份,服务端证书还可以用于加密key密钥
      2. 证书extension中的Key Usage字段会写明此证书用于客户端还是服务端
  • 上面的一条龙还可以分解为:

    • 创建私钥、创建签发请求:easyrsa --batch --subject-alt-name="DNS:broker1.kafka.cluster,IP:172.26.0.2" --req-cn="broker1" gen-req broker1 nopass
    • 签发证书:easyrsa --subject-alt-name="DNS:broker1.kafka.cluster,IP:172.26.0.2" sign-req server broker1
  • 创建签发请求时的参数

    • --req-cn 或者 nopass前面的字符串 都代表着证书的CN
    • subject-alt-name简写SAN,是x509证书的扩展,其中可以逗号分隔容纳很多个域名或者IP,对于拥有多个域名的场景非常方便
  • 查看得到的csr、crt相关的命令

    • 查看csr
      • openssl req -in pki/reqs/broker1.req -text -noout
      • easyrsa show-req broker1
    • 查看crt
      • openssl x509 -in pki/issued/broker1.crt -text -noout
      • easyrsa show-cert broker1
jks格式部分
  • 要让java能够使用easyrsa管理的证书,需要进行证书的格式转换
  • ca.crt.pem 转换为 truststore.jks
    • keytool -import -noprompt -alias caroot -file pki/ca.crt -keystore jks/truststore.jks -storepass 123456
    • 可以看出truststore.jks中仅储存CA的根证书,用于对其信任并校验其他由其签发的证书
  • server.crt&key 转换为 server.jks
    • server.jks包含三个实体:私钥、私钥对应的证书、CA的根证书
    • 但是jdk的keytool的import命令只能把证书,不能把私钥,导入进jks格式文件
    • 然而keytool可以把pkcs12格式(可以包含多个证书、私钥)转化为jks
    • 所以就有了以下过程
NAME=client1
openssl pkcs12 -export -name key -in pki/issued/$NAME.crt -inkey pki/private/$NAME.key -out jks/$NAME.p12 -passout pass:somepwd
#or easyrsa export-p12 $NAME

keytool -importkeystore -srckeystore jks/$NAME.p12 -srcstoretype PKCS12 -destkeystore jks/$NAME.jks -srcstorepass somepwd -deststorepass 123456 --alias key
keytool -import -noprompt -alias caroot -file pki/ca.crt -keystore jks/$NAME.jks -storepass 123456
keytool -import -noprompt -alias crt -file pki/issued/$NAME.crt -keystore jks/$NAME.jks -storepass 123456
  • 承上
    • importkeystore把pkcs12格式(p12后缀)中的私钥转化为jks格式的私钥
    • 注意importkeystore命令仅导入p12中的私钥,尽管easyrsa export-p12中三个实体内容是都有的(openssl转换的仅包含私钥)
    • 所以需要后面的两个import把证书导入进去
    • 第一条import导入了ca证书
    • 第二条import导入了私钥对应的证书
  • 最后查看生成好的jks证书,应该有三条实体,一个PriviateKey,两个Certificate
    • keytool --list -keystore jks/broker1.jks -storepass 123456
    • 结果应类似这样
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 3 entries

key, Oct 12, 2020, PrivateKeyEntry, 
Certificate fingerprint (SHA-256): 9C:DC:2A:06:C0:7E:10:9E:9E:0B:70:4F:6A:0B:A9:8C
caroot, Oct 13, 2020, trustedCertEntry, 
Certificate fingerprint (SHA-256): 9D:D2:8D:24:BE:59:FC:0E:FE:5F:BC:68:E4:ED:A8:52
crt, Oct 13, 2020, trustedCertEntry, 
Certificate fingerprint (SHA-256): 9C:DC:2A:06:C0:7E:10:9E:9E:0B:70:4F:6A:0B:A9:8C
  • 附查看p12格式证书的命令 openssl pkcs12 -in jks/broker1.p12 -info

SSL仅加密 & 不认证

  • 在CA创建好并签发管理证书后,可以开始对kafka服务端和客户端进行配置进行实验
  • 注意kafka客户端会检查服务端证书中的SAN字段并校验,不通过会停止自己的访问
    • 如果 不需要 客户端对服务端证书进行校验的话,在签发证书的时候把SAN字段去掉就可以
    • 但会面临MITM攻击的风险
  • 服务端配置公共部分,与上一篇初探博文中的配置相同
      KAFKA_BROKER_ID: 1
      KAFKA_CREATE_TOPICS: "test:1:1"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: INSIDE://172.26.0.2:9092,OUTSIDE://172.26.0.2:9093
      KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:9093
      KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
  • 服务端配置特殊部分
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:SSL
      KAFKA_SSL_KEYSTORE_LOCATION: /etc/pki/jks/broker1.jks
      KAFKA_SSL_KEYSTORE_PASSWORD: 123456
      KAFKA_SSL_KEY_PASSWORD: 123456
      KAFKA_SSL_TRUSTSTORE_LOCATION: /etc/pki/jks/truststore.jks
      KAFKA_SSL_TRUSTSTORE_PASSWORD: 123456
      KAFKA_SSL_SECURE_RANDOM_IMPLEMENTATION: SHA1PRNG
      KAFKA_SSL_CLIENT_AUTH: none
  • 配置解释:

    • truststore.location与keystore.location是两个jks证书的位置
    • keystore.password与key.password的区别是
      • 前者是jks文件的密码,后者是jks文件中密钥的密码
      • importstore时指定这两个密码不同的话会报错Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -destkeypass value.
      • 因此使用keytool创建的jks文件这两个密码是必须相同的,也就省略了私钥密码
      • 所以在kafka的配置中这两个参数的value是一样的
    • secure.random是调用SSL时使用的随机数生成器,官方文档推荐SHA1PRNG
    • ssl.client.auth是服务端对客户端的证书要求
      • none:不要求
      • required:要求客户端必须提供证书
      • requested:客户端可选提供证书
  • 客户端配置

kafka_client_ssl.properties:

group.id=test-group
security.protocol=SSL
ssl.truststore.location=/etc/pki/jks/truststore.jks
ssl.truststore.password=123456
  • 测试命令
    • 消费者 ./kafka-console-consumer.sh --bootstrap-server 172.26.0.2:9093 --topic test --from-beginning --consumer.config /etc/jaas/kafka_client_ssl.properties
    • 生产者 ./kafka-console-producer.sh --bootstrap-server 172.26.0.2:9093 --topic test --producer.config /etc/jaas/kafka_client_ssl.properties
    • 这时候在docker网桥上tcpdump抓包已经看不到明文内容了

SSL加密 & SSL认证

对服务端SSL认证

  • 如前文所述,在签发证书时加上SAN字段即可

对客户端SSL认证

  • 服务端配置仅需改动KAFKA_SSL_CLIENT_AUTH为required
  • 客户端配置需改动为如下,添加了给客户端生成的jks
group.id=test-group
security.protocol=SSL
ssl.truststore.location=/etc/pki/jks/truststore.jks
ssl.truststore.password=123456
ssl.keystore.location=/etc/pki/jks/client1.jks
ssl.keystore.password=123456
ssl.key.password=123456
  • 测试命令相同
    • 若此时若客户端所访问的kafka服务的IP不在服务端的SAN中,如127.0.0.1,会报错java.security.cert.CertificateException: No subject alternative names matching IP address 127.0.0.1 found
    • 若此时客户端不提供客户端证书,则会报错org.apache.kafka.common.errors.SslAuthenticationException: SSL handshake failed

SSl加密 & SASL认证

对服务端SSL认证

  • 同上一小节

对客户端SASL认证

  • 服务端配置改为
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:SASL_SSL
      KAFKA_SSL_KEYSTORE_LOCATION: /etc/pki/jks/broker1.jks
      KAFKA_SSL_KEYSTORE_PASSWORD: 123456
      KAFKA_SSL_KEY_PASSWORD: 123456
      KAFKA_SSL_TRUSTSTORE_LOCATION: /etc/pki/jks/truststore.jks
      KAFKA_SSL_TRUSTSTORE_PASSWORD: 123456
      KAFKA_SSL_SECURE_RANDOM_IMPLEMENTATION: SHA1PRNG
      KAFKA_SSL_CLIENT_AUTH: none
      KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/jaas/kafka_server_jaas.conf"
      KAFKA_SASL_MECHANISM: PLAIN
      KAFKA_SASL_ENABLED_MECHANISMS: PLAIN
      KAFKA_SUPER_USERS: "User:admin;User:ANONYMOUS"
  • 主要修改了security的map,指定SASL_SSL,代表传输层SSL,认证使用SASL

  • 其次SASL配置与初探中的SASL配置相同,jaas配置文件也与上篇文章中相同

  • 客户端配置修改为

security.protocol=SASL_SSL
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="5699923";
group.id=test-group

ssl.truststore.location=/etc/pki/jks/truststore.jks
ssl.truststore.password=123456
  • 同样也是SASL配置和传输层配置SSL的结合
  • 测试命令相同
  • 若客户端提供的密码不对,会报错org.apache.kafka.common.errors.SaslAuthenticationException: Authentication failed: Invalid username or password
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342