Cluster route TLS: FQDN from route URL is resolved to IP before TLS dial, causing x509 IP SAN verification failure
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
Source: nats-io/nats-server