11.10.3 身份认证与加密通信配置

在ZooKeeper安全体系中,身份认证与加密通信是防止未授权访问与中间人攻击的核心环节。建议以“强认证 + 端到端加密 + 最小暴露面”为原则,统一规划生产环境的认证机制、密钥管理与通信链路的加固配置。

原理草图:SASL + TLS 认证与加密链路

文章图片

认证机制选择与策略
- 优先使用SASL/Kerberos实现强身份认证,适用于多节点集群与跨业务访问场景。
- 轻量场景可使用digest认证,但需配合强口令策略与ACL最小权限原则。
- 客户端与服务端认证方式必须统一,避免混用导致访问异常与安全漏洞。
- 禁止匿名访问,关闭不必要的四字命令与明文管理接口。

安装与准备(示例环境)
- OS: RockyLinux 8
- ZK: 3.8.x
- KDC: MIT Kerberos
- 证书: 自建CA

1)Kerberos 安装与主体创建(示例)

# 安装KDC与管理工具
dnf -y install krb5-server krb5-workstation

# 初始化Realm(示例:OPS.COM)
kdb5_util create -s -r OPS.COM

# 启动KDC
systemctl enable --now krb5kdc kadmin

# 创建ZooKeeper服务主体与客户端主体
kadmin.local <<EOF
addprinc -randkey zookeeper/zk1.ops.com@OPS.COM
addprinc -randkey zookeeper/zk2.ops.com@OPS.COM
addprinc -randkey zookeeper/zk3.ops.com@OPS.COM
addprinc zkclient@OPS.COM
# 导出keytab
ktadd -k /etc/security/keytabs/zk1.keytab zookeeper/zk1.ops.com@OPS.COM
ktadd -k /etc/security/keytabs/zk2.keytab zookeeper/zk2.ops.com@OPS.COM
ktadd -k /etc/security/keytabs/zk3.keytab zookeeper/zk3.ops.com@OPS.COM
ktadd -k /etc/security/keytabs/zkclient.keytab zkclient@OPS.COM
EOF

# 权限收敛
chmod 600 /etc/security/keytabs/*.keytab

2)ZooKeeper 服务器端 SASL 配置
- conf/jaas.conf(每台节点独立设置principal与keytab)

Server {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/etc/security/keytabs/zk1.keytab"
  storeKey=true
  useTicketCache=false
  principal="zookeeper/zk1.ops.com@OPS.COM";
};
  • conf/zoo.cfg
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl
# 强制安全端口
secureClientPort=2281
# 关闭明文端口
clientPort=0
  • 启动参数(确保加载JAAS)
export JVMFLAGS="-Djava.security.auth.login.config=/opt/zookeeper/conf/jaas.conf"
bin/zkServer.sh start

3)客户端 SASL 连接示例
- conf/jaas-client.conf

Client {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/etc/security/keytabs/zkclient.keytab"
  storeKey=true
  useTicketCache=false
  principal="zkclient@OPS.COM";
};
  • 连接命令
export JVMFLAGS="-Djava.security.auth.login.config=/opt/zookeeper/conf/jaas-client.conf"
bin/zkCli.sh -server zk1.ops.com:2281
# 预期输出:Welcome to ZooKeeper! 之后可执行 ls /

4)TLS/SSL 加密通信配置(客户端与quorum)
- 生成CA与证书(示例OpenSSL)

# CA
openssl genrsa -out /etc/pki/ca/ca.key 4096
openssl req -x509 -new -nodes -key /etc/pki/ca/ca.key -sha256 -days 3650 \
  -subj "/C=CN/O=OPS/OU=ZK/CN=OPS-CA" -out /etc/pki/ca/ca.crt

# 节点证书(以zk1为例)
openssl genrsa -out /etc/pki/zk1.key 2048
openssl req -new -key /etc/pki/zk1.key -subj "/C=CN/O=OPS/OU=ZK/CN=zk1.ops.com" \
  -out /etc/pki/zk1.csr
openssl x509 -req -in /etc/pki/zk1.csr -CA /etc/pki/ca/ca.crt -CAkey /etc/pki/ca/ca.key \
  -CAcreateserial -out /etc/pki/zk1.crt -days 825 -sha256

# 转为JKS
keytool -importcert -alias ops-ca -file /etc/pki/ca/ca.crt \
  -keystore /opt/zookeeper/conf/truststore.jks -storepass changeit -noprompt

openssl pkcs12 -export -in /etc/pki/zk1.crt -inkey /etc/pki/zk1.key \
  -out /tmp/zk1.p12 -name zk1 -password pass:changeit

keytool -importkeystore -deststorepass changeit -destkeystore /opt/zookeeper/conf/keystore.jks \
  -srckeystore /tmp/zk1.p12 -srcstoretype PKCS12 -srcstorepass changeit
chmod 600 /opt/zookeeper/conf/keystore.jks /opt/zookeeper/conf/truststore.jks
  • conf/zoo.cfg(TLS相关)
# 客户端TLS
secureClientPort=2281
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
ssl.keyStore.location=/opt/zookeeper/conf/keystore.jks
ssl.keyStore.password=changeit
ssl.trustStore.location=/opt/zookeeper/conf/truststore.jks
ssl.trustStore.password=changeit
ssl.enabledProtocols=TLSv1.2,TLSv1.3

# quorum TLS
sslQuorum=true
sslQuorum.clientAuth=need
ssl.quorum.keyStore.location=/opt/zookeeper/conf/keystore.jks
ssl.quorum.keyStore.password=changeit
ssl.quorum.trustStore.location=/opt/zookeeper/conf/truststore.jks
ssl.quorum.trustStore.password=changeit

5)验证与安全自测

# 验证服务端监听端口
ss -lntp | grep 2281

# TLS握手验证
echo ruok | openssl s_client -connect zk1.ops.com:2281 -CAfile /etc/pki/ca/ca.crt

# SASL验证(客户端登录后)
getAcl /
# 预期:看到sasl:zkclient的ACL

常见故障与排错(含命令)
- 现象:SASL authentication failed
- 排查:客户端是否加载JAAS、principal是否一致
bash grep -i sasl /opt/zookeeper/logs/zookeeper.out klist -k /etc/security/keytabs/zkclient.keytab
- 现象:Not in GSS InitiateKrbException: Clock skew
- 排查:时间不同步
bash chronyc sources -v date
- 现象:javax.net.ssl.SSLHandshakeException
- 排查:证书不受信任或主机名不匹配
bash keytool -list -keystore /opt/zookeeper/conf/truststore.jks openssl x509 -in /etc/pki/zk1.crt -noout -subject -issuer
- 现象:客户端无法连接secureClientPort
- 排查:端口未开放或clientPort未关闭
bash grep -E "secureClientPort|clientPort" /opt/zookeeper/conf/zoo.cfg firewall-cmd --list-ports

配置片段汇总(最小可用示例)

# zoo.cfg 关键项
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl
secureClientPort=2281
clientPort=0
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
ssl.keyStore.location=/opt/zookeeper/conf/keystore.jks
ssl.keyStore.password=changeit
ssl.trustStore.location=/opt/zookeeper/conf/truststore.jks
ssl.trustStore.password=changeit
sslQuorum=true
sslQuorum.clientAuth=need

练习题与操作实践
1. 使用digest认证为/app节点设置只读ACL,并验证匿名用户无法读取。
- 提示命令:
bash addauth digest user:pass setAcl /app digest:user:pass:cr get /app
2. 将现有集群从明文2181迁移到TLS 2281,完成滚动重启并验证客户端可连接。
3. 模拟证书过期,观察SSLHandshakeException日志并完成证书轮换。
4. 通过klistkadmin.local核对principal,解决一次SASL认证失败问题。

最佳实践摘要
- 禁止匿名访问与明文端口,统一启用SASL + TLS。
- Keytab/证书不随镜像分发,通过安全通道下发并严格权限控制。
- 强制TLS1.2+与禁用弱加密套件,密钥与证书定期轮换。
- ZooKeeper对外暴露需在内网/VPN内,配合防火墙与安全组限制源IP。