ZooKeeper安全认证机制:SSL

本文探讨ZooKeeper的SSL安全机制。默认情形下,ZooKeeper的网络通信是没有加密的,但ZooKeeper提供了SSL特性,目前仅应用在Client与Server端之间的交互(Server与Server之间的交互尚不支持),且RPC通信协议基于Netty时(ZooKeeper内置的NIO实现中不支持)。

SSL简介

SSL全称为Secure Socket Layer,它是一种介于传输层和应用层的协议,它通过”握手协议”和“传输协议”来解决信息传输的安全问题,它可以被建立在任何可靠的传输层协议之上(例如TCP,但不能是UDP)。SSL协议主要提供如下三方面的能力:

  • 信息的加密传播
  • 校验机制,数据一旦被篡改,通信双方均会立刻发现
  • 身份证书,防止身份被冒充

SSL的基本设计思想:

  1. Client向Server端索要”公钥
  2. Client对获取的”公钥“进行校验
  3. 双方协商生成“会话密钥
  4. 双方基于”会话密钥“进行信息交换

前3步称之为”握手阶段”,”握手阶段”采用”非对称加密“算法。
第4步称之为”传输阶段”,基于”对称加密“算法,”对称加密”算法的性能是远高于”非对称加密”算法的,因此,更适用于大数据量的传输加密。

如何使用

Client端配置

ZooKeeper Client通过配置如下系统属性来启用基于Netty的RPC通信层:

zookeeper.clientCnxnSocket=”org.apache.zookeeper.ClientCnxnSocketNetty”

Client需要设置如下参数来启用安全通信:

zookeeper.client.secure=true

设置了zookeeper.client.secure属性为true以后,意味着Client与Server之间只能通过"secureClientPort"所指定的端口进行交互。
最后,需要配置KeyStore与TrustStore的相关系统属性:

zookeeper.ssl.keyStore.location=”/path/to/your/keystore”
zookeeper.ssl.keyStore.password=”keystore_password”
zookeeper.ssl.trustStore.location=”/path/to/your/truststore”
zookeeper.ssl.trustStore.password=”truststore_password”

Server端配置

ZooKeeper Server通过配置如下系统属性来启用Netty:

zookeeper.serverCnxnFactory=”org.apache.zookeeper.server.NettyServerCnxnFactory”

在”zoo.cfg”中配置”secureClientPort”端口值,该端口值与原来的”clientPort”端口值应该区别开:

secureClientPort=2281

最后也需要设置KeyStore与TrustStore的配置,与Client端配置类似。

配置示例

“bin/zkServer.sh”的配置示例如下:

export SERVER_JVMFLAGS=”
-Dzookeeper.serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
-Dzookeeper.ssl.keyStore.location=/root/zookeeper/ssl/testKeyStore.jks
-Dzookeeper.ssl.keyStore.password=testpass
-Dzookeeper.ssl.trustStore.location=/root/zookeeper/ssl/testTrustStore.jks
-Dzookeeper.ssl.trustStore.password=testpass”

在 “zoo.cfg”中增加:

secureClientPort=2281

“bin/zkCli.sh”的配置为:

export CLIENT_JVMFLAGS=”
-Dzookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty
-Dzookeeper.client.secure=true
-Dzookeeper.ssl.keyStore.location=/root/zookeeper/ssl/testKeyStore.jks
-Dzookeeper.ssl.keyStore.password=testpass
-Dzookeeper.ssl.trustStore.location=/root/zookeeper/ssl/testTrustStore.jks
-Dzookeeper.ssl.trustStore.password=testpass”

X509AuthenticationProvider

默认情况下,SSL认证是由X509AuthenticationProvider提供的,对应的schema为x509X509AuthenticationProvider基于javax.net.ssl.X509KeyManagerjavax.net.ssl.X509TrustManager提供Host证书认证机制。X509AuthenticationProvider仅仅当zookeeper.serverCnxnFactory配置为NettyServerCnxnFactory时才可使用,ZooKeeper内置的NIO实现类NIOServerCnxnFactory并不支持SSL。
关键的配置项如下所示:

配置项 配置解释
zookeeper.ssl.keyStore.location KeyStore的路径
zookeeper.ssl.trustStore.location TrustStore的路径
zookeeper.ssl.keyStore.password KeyStore的访问密码
zookeeper.ssl.trustStore.password TrustStore的访问密码

在KeyStore JKS文件中保存了Server的证书以及私钥信息,该证书需要由Client端信任,因此,该证书或CA(证书认证机构信息)也会被存储在Client端的TrustStore JKS文件中。同时,Server端的TrustStore JFS文件中存储了所信任的Client的证书/CA信息。
Client认证成功之后,会创建一个ZooKeeper Session,Client可以设置ACLs的schema为”x509″. “x509″使用Client认证成功后的X500 Principal作为ACL ID。 ACL信息中包含Client认证后的确切的X500 Principal名称。

关于X509与 X500:
X509: 一套数字证书体系标准
X500: 定义了一种区别命名规则,以命名树来确保用户名称的唯一性

digest认证类似,Server端可以配置一个X509的superUser,对应的Property Key为:

zookeeper.X509AuthenticationProvider.superUser

superUser可以绕过ACL配置从而拥有所有znodes的所有权限。

定制X509AuthenticationProvider

除了默认的X509AuthenticationProvider以外,ZooKeeper允许自定义扩展实现X509的安全信任机制,尤其是Certificate Key Infrastructures不使用JKS时。
自定义实现X509AuthenticationProvider应该遵循:

  • 继承自X509AuthenticationProvider
  • KeyManager需要继承自javax.net.ssl.X509ExtendedKeyManager
  • TrustManager需要继承自javax.net.ssl.X509ExtendedTrustManager
  • 覆写X509AuthenticationProvidergetKeyManagergetTrustManager方法

这样,自定义的实现才会在SSLEngine中发挥作用。
自定义的AuthenticationProvider需要配置一个对应的schema名称,并且通过系统属性"zookeeper.authProvider.[schema_name]"来配置新定义的AuthenticationProvider实现类,这样在ProviderRegistry初始化时会自动加载。接下来,还需要设置系统属性"zookeeper.ssl.authProvider=[schema_name]",这样,新定义的AuthenticationProvider才可以被应用在安全认证中。

实现细节

NettyServerCnxnFactory构造函数中初始化ChannelPipeline时调用初始化SSL的方法:

NettyServerCnxnFactory#initSSL方法的实现如下:

CnxnChannelHandler#channelConnected方法的定义如下:

当SslHandler中的handshake Future中的监听者被触发以后,由CertificateVerifier来对证书的合法性进行校验,而CertificateVerifier对证书进行校验的操作是由X509AuthenticationProvider或者自定义的扩展实现类来完成:

Reference

  1. Client-Server Mutual Authentication
  2. ZOOKEEPER-938
  3. ZOOKEEPER-2125
  4. ZooKeeper SSL User Guide
  5. SSL/TLS协议运行机制的概述

本文源自:NoSQL漫谈(nosqlnotes.com)
除非特别注明,本站文章均为原创,转载请注明出处和链接。

推荐阅读:

ZooKeeper安全认证机制:用户名密码认证

One comment

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注