bigywater.tech
ZooKeeper · 76

mTLS 双向认证

TLS 只让客户端确认服务端是谁;双向 TLS 还要服务端确认客户端是谁。这篇配置 ssl.clientAuth,验证没有证书、冒名证书、合法证书三种连接的结果,再用证书 DN 做 ACL。

need vs want
need 强制客户端证书;want 有没有都放行
x509: CN=client1
证书 DN 就是 ZooKeeper 里的身份
能连 ≠ 能访问
合法证书仍要被 ACL 授权

clientAuth=need

实测 · 本机执行输出
  TLS 客户端不带证书 → Unexpected throwable | io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: (certificate_required) Received fatal alert: certificate_required
  带 client1 证书(CA 签发)→ [zookeeper]
  带一张自签名、同样叫 CN=client1 的证书(不是我的 CA 签发)→ Unexpected throwable | io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: (certificate_required) Received fatal alert: certificate_required

证书就是身份

实测 · 本机执行输出
  client1 的 whoami → Auth scheme: User | ip: 127.0.0.1 | x509: CN=client1
  client2 的 whoami → Auth scheme: User | x509: CN=client2 | ip: 127.0.0.1

按证书授权

实测 · 本机执行输出
  client1 创建 /only-client1(ACL = x509:CN=client1:cdrwa)→ Created /only-client1
  client1 读 → secret
  client2 读 → Insufficient permission : /only-client1 | Exiting JVM with code 1
  getAcl → 'x509,'CN=client1 | : cdrwa

clientAuth=want

实测 · 本机执行输出
  不带证书 → [zookeeper]
  带 client1 证书 whoami → Auth scheme: User | ip: 127.0.0.1 | x509: CN=client1

分步演示

双向 TLS
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机;本机 openssl 生成的 CA、client1、client2 以及一张自签名冒名证书;客户端是官方 CLI(PKCS12 密钥库)
    • 没有验证:证书吊销、DN 里含逗号等特殊字符的 ACL 写法、ssl.authProvider 自定义、集群里节点间的双向认证(第 78 篇只验证了加密)
    京ICP备2026067502号-1京公网安备11010502063487号