Skip to content

Distinguish explicit and inferred TLS host names useful when cluster shards exposed using TLS/SNI - #3250

Merged
mgravell merged 6 commits into
StackExchange:mainfrom
sandeepkunusoth:fix_cluster_sni_2826
Sep 22, 2026
Merged

mgravell merged 6 commits into
StackExchange:mainfrom
sandeepkunusoth:fix_cluster_sni_2826

Conversation

@sandeepkunusoth

@sandeepkunusoth sandeepkunusoth commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Fixes TLS SNI selection for hostname-routed clusters from a single DNS endpoint.

For clusters behind a shared load balancer that routes by SNI, every discovered node consequently reused the initial endpoint’s SNI name and could be routed to the wrong backend.

this change distinguishes an explicitly configured SslHost from an inferred fallback and applies this precedence:

  1. An explicitly configured SslHost always wins.
  2. Otherwise, a DnsEndPoint uses its own Host.
  3. Otherwise, the default provider’s GetSslHostFromEndpoints(EndPoints) value is used.
  4. If none is available, the endpoint address is used.

This preserves existing behavior for callers that deliberately configure SslHost, while allowing each discovered DNS cluster endpoint to present its own SNI name.

The resolution logic is centralized and applied consistently to:

  • The standard physical connection TLS path
  • LoggingTunnel
  • TlsOptions.ResolveHost

ConfigurationOptions.SslHost now reports only an explicitly configured value rather than an inferred one.

Related to #2826, specifically:
#2826 (comment)

Testing

Added and updated coverage for:

  • Explicit SslHost overriding a DNS endpoint
  • A DNS endpoint taking precedence over an inferred hostname
  • An IP endpoint using an explicit SslHost
  • An IP endpoint using the inferred fallback
  • An IP endpoint falling back to its address
  • Matching behavior through TlsOptions.ResolveHost
  • TLS cluster connections using hostname-only certificates

Testing

Validated against a hostname-routed Valkey cluster using a single seed hostname, shared VIP, and per-node SNI routing.

Checklist

  • I fully and freely contribute this code in accordance with the project license (and am legally able to do so)
  • I take responsibility for this contribution's quality and correctness, including any portions produced with AI assistance (see CONTRIBUTING.md).

Signed-off-by: Sandeep Kunusoth <sandeepkunsoth000@gmail.com>
Signed-off-by: Sandeep Kunusoth <sandeepkunsoth000@gmail.com>
Signed-off-by: Sandeep Kunusoth <sandeepkunsoth000@gmail.com>
@sandeepkunusoth sandeepkunusoth changed the title Use per-endpoint DNS names for TLS SNI Use per-endpoint DNS names for cluster shards exposed using TLS SNI Sep 22, 2026
@sandeepkunusoth sandeepkunusoth changed the title Use per-endpoint DNS names for cluster shards exposed using TLS SNI Use per-endpoint DNS names for TLS SNI, cluster shards exposed using SNI Sep 22, 2026
@mgravell

Copy link
Copy Markdown
Collaborator

I'm concerned that as written this is a break to many scenarios - it stops using the sslhost as an override in some DNS scenarios that work today.

Question: are you actually specifying the sslhost in your scenario?

@mgravell

Copy link
Copy Markdown
Collaborator

I wonder if the real fix here is for the library to never infer sslhost on your behalf, so it only applies if the caller means it, I.e. change this:

get => sslHost ?? Defaults.GetSslHostFromEndpoints(EndPoints);

So:

  • SslHost always wins if specified
  • otherwise, for DNS endpoint: use .Host
  • otherwise, use Defaults.GetSslHostFromEndpoints(EndPoints)

@sandeepkunusoth

sandeepkunusoth commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for quick reply.

I'm concerned that as written this is a break to many scenarios - it stops using the sslhost as an override in some DNS scenarios that work today.

Question: are you actually specifying the sslhost in your scenario?

No, in our case we are not explicitly setting SslHost. It is being inferred from the single seed endpoint via:
get => sslHost ?? Defaults.GetSslHostFromEndpoints(EndPoints);
That inferred value is then effectively treated like an explicit override for the DNS endpoints discovered from CLUSTER SLOTS, which is what causes the wrong SNI to be reused across shards.

I wonder if the real fix here is for the library to never infer sslhost on your behalf, so it only applies if the caller means it, I.e. change this:

I agree your suggested direction is safer and preserves the existing override behavior:

explicit SslHost always wins
otherwise, for a DnsEndPoint, use DnsEndPoint.Host
otherwise, fall back to Defaults.GetSslHostFromEndpoints(EndPoints)

That should solve our single-dns cluster case without changing behavior for callers that intentionally set SslHost.

I can update the PR in that direction and adjust the tests accordingly.

Signed-off-by: Sandeep Kunusoth <sandeepkunsoth000@gmail.com>
Signed-off-by: Sandeep Kunusoth <sandeepkunsoth000@gmail.com>
@mgravell

Copy link
Copy Markdown
Collaborator

Retrigger CI

I was about to do that from this side ;p Yes, there's some annoying flakes, but if you let me deal with that: I can do it more granularly

Changes look good, thanks

@sandeepkunusoth

Copy link
Copy Markdown
Contributor Author

Retrigger CI

I was about to do that from this side ;p Yes, there's some annoying flakes, but if you let me deal with that: I can do it more granularly

Changes look good, thanks

please feel freee to update anything if u want.

@sandeepkunusoth sandeepkunusoth changed the title Use per-endpoint DNS names for TLS SNI, cluster shards exposed using SNI Distinguish explicit and inferred TLS host names useful when cluster shards exposed using TLS/SNI Sep 22, 2026
Only consulted for non-DnsEndPoint connections now that SslHost
resolution no longer infers a host for endpoints that already carry
their own.
@mgravell
mgravell merged commit 0a92ae4 into StackExchange:main Sep 22, 2026
3 checks passed
@sandeepkunusoth

Copy link
Copy Markdown
Contributor Author

Hi @mgravell, thanks for merging this! Could you let me know approximately when the next version containing this fix is expected to be released?

Also, is there a way to use a build/tag from main in a .NET project in the meantime, so we can start using and testing the fix before the official release?

@mgravell

Copy link
Copy Markdown
Collaborator

I don't object to doing a build for it, which would be 3.3.1 - however, GitHub is failing to load /releases for me, which makes that hard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants