Cluster route TLS: FQDN from route URL is resolved to IP before TLS dial, causing x509 IP SAN verification failure

Author: n0where3anCreated Jun 12, 2026Updated Sep 10, 2026
Labelsdefect

Observed behavior

When cluster routes are configured using FQDNs (e.g. nats://user:[email protected]:6222), the server establishes the TLS connection but fails certificate verification with:

TLS route handshake error: tls: failed to verify certificate: x509: cannot validate certificate for 172.20.10.236 because it doesn't contain any IP SANs The certificate for nats-0.example.com has CN=nats-0.example.com and passes openssl verify against the CA chain. However, nats-server appears to resolve the FQDN to its IP address (172.20.10.236) before the TLS dial and passes the IP — not the original hostname — as the TLS ServerName. As a result, Go's x509 library performs IP SAN verification instead of hostname verification, which fails because the certificate contains no IP SANs.

Expected behavior

The TLS ServerName used for certificate verification should be the hostname exactly as written in the route URL (nats-0.example.com), regardless of how the underlying TCP connection was established. This is consistent with how all standard TLS clients (curl, browsers, openssl s_client) behave — they never substitute the resolved IP for the original hostname in TLS verification

Server and client version

debian 12, nats-server 2.14.0

Host environment

nats-server 2.14.0, Linux/amd64 Certificates issued by internal PKI (StepCA), containing CN=hostname, no IP SANs Cluster routes configured with FQDNs, mutual TLS (verify: true), custom CA chain

Steps to reproduce

No response