SASL 认证机制:从 PLAIN 到 Kerberos 的实战选择
说到 Kafka 的认证,SASL 是个绕不开的话题。我最早接触它的时候,也被那一堆缩写搞得头大——PLAIN、SCRAM、GSSAPI,到底该用哪个?
其实 SASL 全称是 Simple Authentication and Security Layer,说白了就是一个认证框架。它不负责具体怎么验证身份,而是定义了一套接口,让不同的认证机制可以插进去用。Kafka 支持三种主流机制:PLAIN、SCRAM 和 GSSAPI(Kerberos)。
今天我就把这三种机制掰开揉碎了讲清楚。你想想看,选错了认证方式,后面运维起来有多痛苦?我踩过的坑,你就别踩了。
一句话总结:PLAIN 适合快速验证环境,SCRAM 是生产环境的首选,Kerberos 适合已经部署了 Kerberos 的大企业。
SASL/PLAIN:最简单的方案,但别用在生产环境
SASL/PLAIN 是三种机制里最直白的。客户端把用户名和密码直接发给 Broker,Broker 拿着配置文件里的信息做比对。嗯,就是明文传输,没有加密。
我记得刚入行那会儿,有个同事图省事,直接在线上环境配了 PLAIN。结果安全审计的时候被查出来,差点背了处分。后来我养成了一个习惯:PLAIN 只用来做功能验证,上线前必须换掉。
配置步骤
- 创建 JAAS 配置文件:在每台 Broker 上创建
kafka_server_jaas.conf - 配置 Broker:修改
server.properties启用 SASL_PLAINTEXT 监听器 - 配置客户端:生产者和消费者也需要 JAAS 配置
来看一个具体的 Broker 端 JAAS 配置:
KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin-secret"
user_admin="admin-secret"
user_producer="producer-secret"
user_consumer="consumer-secret";
};
注意:这里的密码是明文存储的。一旦配置文件泄露,所有账号就全完了。我曾经见过有人把 JAAS 文件提交到 Git 仓库里……嗯,那场面,不堪回首。
Broker 端 server.properties 的改动:
listeners=SASL_PLAINTEXT://0.0.0.0:9093
advertised.listeners=SASL_PLAINTEXT://broker1.example.com:9093
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=PLAIN
sasl.enabled.mechanisms=PLAIN
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
客户端配置就简单多了:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
username="producer" \
password="producer-secret";
我的建议:如果你非要在开发环境用 PLAIN,至少把监听器绑定到内网 IP,别暴露到公网。另外,密码别用 admin/admin123 这种,我见过太多人这么干了。
SASL/SCRAM:生产环境的正确选择
SCRAM 全称是 Salted Challenge Response Authentication Mechanism。名字很长,但核心思想很简单:密码不在网络上传输。
客户端和 Broker 之间通过一系列挑战-响应交互来验证身份。即使有人抓包,也拿不到密码原文。而且 SCRAM 支持动态增删用户,不用重启 Broker。
我个人习惯在生产环境首选 SCRAM。它比 PLAIN 安全得多,配置起来又比 Kerberos 简单。性价比最高。
SCRAM 的工作原理
我画个简单的流程帮你理解:
- 客户端发起认证请求,带上用户名
- Broker 返回一个随机挑战(包含 salt 和迭代次数)
- 客户端用密码和挑战计算响应值,发回 Broker
- Broker 用自己存储的凭证验证响应值
整个过程密码只在客户端内存里出现一次,网络传输的全是计算后的摘要。
配置步骤
第一步,在 ZooKeeper 里创建用户凭证:
# 创建管理员用户
kafka-configs.sh --zookeeper localhost:2181 \
--alter --add-config 'SCRAM-SHA-256=[password=admin-secret]' \
--entity-type users --entity-name admin
# 创建生产者用户
kafka-configs.sh --zookeeper localhost:2181 \
--alter --add-config 'SCRAM-SHA-512=[password=producer-secret]' \
--entity-type users --entity-name producer
关键点:SCRAM 凭证存储在 ZooKeeper 中,所以 ZooKeeper 本身也要做好安全防护。我见过有人 ZooKeeper 没配认证,结果 SCRAM 凭证被人直接删了……
第二步,Broker 端 JAAS 配置:
KafkaServer {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin-secret";
};
注意看,这里只需要配置 Broker 自身用于 Broker 间通信的凭证。用户的凭证已经在 ZooKeeper 里了。
第三步,server.properties 配置:
listeners=SASL_PLAINTEXT://0.0.0.0:9093
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-512
sasl.enabled.mechanisms=SCRAM-SHA-256,SCRAM-SHA-512
客户端配置:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
username="producer" \
password="producer-secret";
经验之谈:我建议用 SCRAM-SHA-512,别用 SCRAM-SHA-256。虽然 256 也够用,但 512 的哈希更长,暴力破解更难。而且性能开销差别几乎可以忽略不计。
动态管理用户
这是 SCRAM 最大的优势。不用重启 Broker,直接加用户:
# 新增用户
kafka-configs.sh --zookeeper localhost:2181 \
--alter --add-config 'SCRAM-SHA-512=[password=newuser-secret]' \
--entity-type users --entity-name newuser
# 删除用户
kafka-configs.sh --zookeeper localhost:2181 \
--alter --delete-config 'SCRAM-SHA-512' \
--entity-type users --entity-name olduser
# 查看用户
kafka-configs.sh --zookeeper localhost:2181 \
--describe --entity-type users --entity-name producer
SASL/GSSAPI(Kerberos):企业级的安全堡垒
Kerberos 是这三者里最复杂的,也是安全性最高的。它基于票据(Ticket)的认证方式,不需要在网络上传送密码。
我在一家金融公司做过项目,他们要求必须用 Kerberos。说实话,配置过程确实折腾,但一旦跑起来,运维反而省心——因为用户管理交给了 KDC,Kafka 这边只管验证票据就行。
Kerberos 的核心概念
| 组件 | 作用 |
|---|---|
| KDC | 密钥分发中心,负责发放票据 |
| Principal | 每个服务的唯一身份标识,格式:service/host@REALM |
| Keytab | 存储 Principal 密钥的文件,相当于密码的替代品 |
| Ticket | 临时凭证,有过期时间 |
配置步骤(精简版)
Kerberos 的配置步骤比较多,我挑核心的讲:
- 在 KDC 上创建 Principal:为每台 Broker 和每个客户端创建 Principal
- 导出 Keytab 文件:分发到对应的 Broker 和客户端机器
- 配置 Broker 端 JAAS:使用 keytab 登录
- 配置 krb5.conf:指定 KDC 地址和 Realm 信息
Broker 端 JAAS 配置示例:
KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/etc/security/keytabs/kafka.keytab"
principal="kafka/broker1.example.com@EXAMPLE.COM";
};
server.properties 配置:
listeners=SASL_PLAINTEXT://0.0.0.0:9093
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanisms=GSSAPI
sasl.kerberos.service.name=kafka
我曾经踩过的坑:Principal 的 service name 必须和 sasl.kerberos.service.name 一致。默认是 kafka,如果你改了,两边都要同步改。还有,所有 Broker 的时钟必须同步,Kerberos 对时间偏差很敏感,超过 5 分钟就会认证失败。
客户端配置:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
useKeyTab=true \
storeKey=true \
keyTab="/etc/security/keytabs/producer.keytab" \
principal="producer@EXAMPLE.COM";
三种机制的对比总结
| 特性 | SASL/PLAIN | SASL/SCRAM | SASL/GSSAPI |
|---|---|---|---|
| 密码传输 | 明文 | 不传输 | 不传输 |
| 密码存储 | 配置文件明文 | ZooKeeper 加盐哈希 | KDC 管理 |
| 动态增删用户 | 不支持,需重启 | 支持,无需重启 | 支持,通过 KDC |
| 配置复杂度 | 低 | 中 | 高 |
| 运维成本 | 低 | 中 | 高(需维护 KDC) |
| 适用场景 | 开发测试 | 生产环境首选 | 已有 Kerberos 的企业 |
我的最终建议:如果你在搭建新的 Kafka 集群,直接上 SCRAM-SHA-512。别犹豫。PLAIN 只用来做快速验证,Kerberos 除非公司已经部署了,否则别自己从头搭——那是个无底洞。