You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@zookeeper.apache.org by "Dávid Paksy (Jira)" <ji...@apache.org> on 2026/06/08 12:40:00 UTC

[jira] [Created] (ZOOKEEPER-5053) Support multiple TLS version in ZooKeeper client

Dávid Paksy created ZOOKEEPER-5053:
--------------------------------------

             Summary: Support multiple TLS version in ZooKeeper client
                 Key: ZOOKEEPER-5053
                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-5053
             Project: ZooKeeper
          Issue Type: Improvement
          Components: java client
    Affects Versions: 3.10.0
            Reporter: Dávid Paksy


When you have a ZooKeeper cluster in FIPS mode, and set the TLS protocol to TLSv1.3, when the client tries to connect to it, it will fail because TLS protocol mismatch.
{noformat}
2026-06-01 15:48:28,489 ERROR org.apache.zookeeper.server.NettyServerCnxnFactory: Unsuccessful handshake with session 0x0
2026-06-01 15:48:28,489 WARN org.apache.zookeeper.server.NettyServerCnxnFactory: Exception caught
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: org.bouncycastle.tls.TlsFatalAlert: protocol_version(70)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:515)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:805)
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:501)
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:399)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: javax.net.ssl.SSLException: org.bouncycastle.tls.TlsFatalAlert: protocol_version(70)
	at bctls/org.bouncycastle.jsse.provider.ProvSSLEngine.unwrap(ProvSSLEngine.java:502)
	at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679)
	at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:308)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1486)
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1377)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1428)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:545)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:484)
	... 15 more
Caused by: org.bouncycastle.tls.TlsFatalAlert: protocol_version(70)
	at bctls/org.bouncycastle.tls.AbstractTlsServer.getServerVersion(AbstractTlsServer.java:413)
	at bctls/org.bouncycastle.jsse.provider.ProvTlsServer.getServerVersion(ProvTlsServer.java:767)
	at bctls/org.bouncycastle.tls.TlsServerProtocol.generateServerHello(TlsServerProtocol.java:508)
	at bctls/org.bouncycastle.tls.TlsServerProtocol.handleHandshakeMessage(TlsServerProtocol.java:1058)
	at bctls/org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(TlsProtocol.java:715)
	at bctls/org.bouncycastle.tls.TlsProtocol.processRecord(TlsProtocol.java:591)
	at bctls/org.bouncycastle.tls.RecordStream.readFullRecord(RecordStream.java:209)
	at bctls/org.bouncycastle.tls.TlsProtocol.safeReadFullRecord(TlsProtocol.java:926)
	at bctls/org.bouncycastle.tls.TlsProtocol.offerInput(TlsProtocol.java:1368)
	at bctls/org.bouncycastle.jsse.provider.ProvSSLEngine.unwrap(ProvSSLEngine.java:486){noformat}
 

This is because in FIPS mode we default to TLSv1.2 but server uses TLSv1.3 and they cannot negotiate a common protocol.

If we'd like to have a SSLContext which supports multiple TLS versions on the client side, we should call SSLContext.getProtocol("TLS") instead of what we have right now:
{code:java}
        String defaultTlsProtocol = defaultTlsProtocol(config);
        String protocol = config.getProperty(sslProtocolProperty, defaultTlsProtocol);
        try {
            SSLContext sslContext = SSLContext.getInstance(protocol);
            sslContext.init(keyManagers, trustManagers, null);
            return new SSLContextAndOptions(this, config, sslContext);
        } catch (NoSuchAlgorithmException | KeyManagementException sslContextInitException) {
            throw new SSLContextException(sslContextInitException);
        } {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)