stream-client lib unexpectedly strip away domain before subject alternative DNS name matching check

94 views
Skip to first unread message

David Åkerman

unread,
Apr 30, 2025, 9:49:20 AMApr 30
to rabbitmq-users
Hi,

I try to add RabbitMQ stream support to a Gerrit plugin. In that plugin I use  the Java lib stream-client version 0.22.0 to create and connect to streams.
The problem is that the plugin fail to make a TLS connection to the rabbitMQ server/s because the subject alternative DNS name matching check fails.
It fails because in some way the check is done with <hostname> instead of the FQDN (<hostname><domain>).
Why is the domain stripped away? Have I missed some configuration or is this a bug?

The code I have used to create the stream environment:
EnvironmentBuilder builder = Environment.builder();
builder.uri(uri);
builder.username(username);
builder.password(password);
environment = builder.build();

Where uri is rabbitmq-stream+tls://<hostname><domain>:5551/<virtualhost>

The stacktrace I get:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching <hostname> found.
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:500)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
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.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
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:1583)
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching <hostname> found.
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:383)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1318)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1195)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1138)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:393)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:476)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1273)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1260)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1205)
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1691)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1537)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1378)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1427)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
... 17 more
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching <hostname> found.
at java.base/sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:207)
at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:103)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:466)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:432)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:291)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1296)
... 31 more

Best regards,
David



Arnaud Cogoluègnes

unread,
May 5, 2025, 8:31:58 AMMay 5
to rabbitmq-users
You should set up Netty's SslContext, see the documentation [1].

David Åkerman

unread,
Aug 4, 2025, 12:31:16 PMAug 4
to rabbitmq-users
On Monday, May 5, 2025 at 2:31:58 PM UTC+2 Arnaud Cogoluègnes wrote:
You should set up Netty's SslContext, see the documentation [1].


Thanks for the tip! Unfortunately, that did not fix the problem.
The problem seems to rely on the fact that the stream-client lib verify the node names(cluster_formation.classic_config.nodes) against the certificates and if you have not configured your Rabbitmq cluster to use node names with the full FQDN the verification fail. For me it seems like an oversight that the stream lib does not support Rabbitmq clusters with node names without the full FQDN. If I understood correctly there is no general discouragement of using node names without the full FQDN and changing node names in an actively used cluster is not painless.
Could it be that support for non-FQDN node names was something that was missed during the implementation or is there a design decision on why it is this way?

Arnaud Cogoluègnes

unread,
Aug 5, 2025, 2:31:04 AMAug 5
to rabbitmq-users
The client library verifies the hostname against the certificate the developer provides. You can configure the client library not to verify the broker identity and just use TLS for the encryption if you want to (this is not what I would recommend though).

Note the client library will use 2 "sets" of hostnames (short or FQDN): the one(s) you set when configuring the Environment and the ones that the broker nodes return as metadata hints (e.g. to connect a producer to the node that hosts the leader of the target stream, see [1] for more information). You have direct control over the hostname(s) you provide to the Environment but the broker may not be using what you expect for the metadata hints, at least with the default behavior.

Run the following command on one of the cluster nodes (assuming all the nodes would behave the same):

rabbitmqctl eval 'rabbit_stream:tls_host().'

The returned value is what the broker will return as a metadata hint, so the client library will use this value to connect to the node and the TLS hostname check will fail if the value does not match what is in the certificate.

You can configure the value each node returns with the stream.advertised_host [2] and stream.advertised_tls_host [3] configuration entries. The configured value should match what the certificate contains and the client library should also be able to connect to the host.

You can then re-run the command above to make sure the configuration has been applied (use "rabbitmqctl eval 'rabbit_stream:host().'" for plain, non-TLS connections if you are using them).

I'll update the TLS section of the documentation to mention "advertised" settings. Thanks for the follow-up.

David Åkerman

unread,
Aug 25, 2025, 3:45:41 AM (14 days ago) Aug 25
to rabbitmq-users
Setting stream.advertised_tls_host did the trick.

Thank you!
Reply all
Reply to author
Forward
0 new messages