From 7073ba5dcec537eff9c4e3b6c7ed35d6082482f7 Mon Sep 17 00:00:00 2001 From: Sandeep Kunusoth Date: Tue, 22 Sep 2026 01:48:29 -0500 Subject: [PATCH 1/6] Use per-endpoint DNS names for TLS SNI Signed-off-by: Sandeep Kunusoth --- .../Configuration/LoggingTunnel.cs | 6 +---- .../Configuration/TlsOptions.cs | 10 +++----- .../ConfigurationOptions.cs | 7 +++++- src/StackExchange.Redis/Format.cs | 23 +++++++++++++++++++ src/StackExchange.Redis/PhysicalConnection.cs | 6 +---- .../ClusterTlsIdentityTests.cs | 17 ++++++++++++++ 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/StackExchange.Redis/Configuration/LoggingTunnel.cs b/src/StackExchange.Redis/Configuration/LoggingTunnel.cs index a76231cd7..78b0b9af3 100644 --- a/src/StackExchange.Redis/Configuration/LoggingTunnel.cs +++ b/src/StackExchange.Redis/Configuration/LoggingTunnel.cs @@ -407,11 +407,7 @@ private async Task TlsHandshakeAsync(Stream stream, EndPoint endpoint) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { // mirrors TLS handshake from PhysicalConnection, but wouldn't help to share code here - var host = _options.SslHost; - if (host.IsNullOrWhiteSpace()) - { - host = Format.ToStringHostOnly(endpoint); - } + var host = Format.GetTlsHostName(endpoint, _options.SslHost); var ssl = new SslStream( innerStream: stream, diff --git a/src/StackExchange.Redis/Configuration/TlsOptions.cs b/src/StackExchange.Redis/Configuration/TlsOptions.cs index 2e0d9f533..f01378607 100644 --- a/src/StackExchange.Redis/Configuration/TlsOptions.cs +++ b/src/StackExchange.Redis/Configuration/TlsOptions.cs @@ -96,12 +96,8 @@ public LocalCertificateSelectionCallback? CertificateSelectionCallback #endif /// - /// The TLS host name to use for the given endpoint: the configured if there is - /// one, otherwise the host portion of the endpoint - which is what the library's own TLS path does. + /// The TLS host name to use for the given endpoint. A uses its own host + /// (required for SNI routing); an address endpoint uses when set, otherwise its address. /// - public string ResolveHost(EndPoint endpoint) - { - var host = SslHost; - return host.IsNullOrWhiteSpace() ? Format.ToStringHostOnly(endpoint) : host!; - } + public string ResolveHost(EndPoint endpoint) => Format.GetTlsHostName(endpoint, SslHost); } diff --git a/src/StackExchange.Redis/ConfigurationOptions.cs b/src/StackExchange.Redis/ConfigurationOptions.cs index 5b75fd4ed..fc3b99ad3 100644 --- a/src/StackExchange.Redis/ConfigurationOptions.cs +++ b/src/StackExchange.Redis/ConfigurationOptions.cs @@ -957,8 +957,13 @@ public bool Ssl } /// - /// The target-host to use when validating SSL certificate; setting a value here enables SSL mode. + /// The target host to use when validating an SSL certificate for connections that dial an + /// (or when no per-endpoint DNS name is available). Setting a value here enables SSL mode. /// + /// + /// Connections to a use that endpoint's host for SNI and certificate validation, + /// not this property. This allows hostname-routed clusters to use a distinct SNI name for each node. + /// public string? SslHost { get => sslHost ?? Defaults.GetSslHostFromEndpoints(EndPoints); diff --git a/src/StackExchange.Redis/Format.cs b/src/StackExchange.Redis/Format.cs index 70d8003aa..779254e9b 100644 --- a/src/StackExchange.Redis/Format.cs +++ b/src/StackExchange.Redis/Format.cs @@ -131,6 +131,29 @@ internal static string ToStringHostOnly(EndPoint endpoint) => _ => "", }; + /// + /// Gets the TLS SNI and certificate-validation host for a connection to . + /// + /// + /// A always uses its own host so hostname-routed clusters present the + /// correct SNI for each discovered node. An address endpoint still honors + /// so dial-by-IP deployments can validate a certificate name. + /// + internal static string GetTlsHostName(EndPoint endpoint, string? sslHost) + { + if (endpoint is DnsEndPoint dns && !dns.Host.IsNullOrWhiteSpace()) + { + return dns.Host; + } + + if (!sslHost.IsNullOrWhiteSpace()) + { + return sslHost; + } + + return ToStringHostOnly(endpoint); + } + internal static bool TryGetHostPort(EndPoint? endpoint, [NotNullWhen(true)] out string? host, [NotNullWhen(true)] out int? port) { if (endpoint is not null) diff --git a/src/StackExchange.Redis/PhysicalConnection.cs b/src/StackExchange.Redis/PhysicalConnection.cs index 6eb70a100..88a54d7e7 100644 --- a/src/StackExchange.Redis/PhysicalConnection.cs +++ b/src/StackExchange.Redis/PhysicalConnection.cs @@ -1226,11 +1226,7 @@ static Stream DemandSocketStream(Socket? socket) if (config.Ssl) { log?.LogInformationConfiguringTLS(); - var host = config.SslHost; - if (host.IsNullOrWhiteSpace()) - { - host = Format.ToStringHostOnly(bridge.ServerEndPoint.EndPoint); - } + var host = Format.GetTlsHostName(bridge.ServerEndPoint.EndPoint, config.SslHost); stream ??= DemandSocketStream(socket); var ssl = new SslStream( diff --git a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs index 21ce97598..77f6fb728 100644 --- a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs +++ b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs @@ -38,6 +38,7 @@ public async Task HostnamePreferredClusterValidatesAgainstAHostnameOnlyCertifica var config = server.GetClientConfig(defaultOnly: true); config.EndPoints.Clear(); config.EndPoints.Add(new DnsEndPoint(Hostname, port)); + config.SslHost = "apex.redis.example.com"; // the seed-derived name must not replace per-node SNI await using var conn = await ConnectionMultiplexer.ConnectAsync(config); var db = conn.GetDatabase(); @@ -109,4 +110,20 @@ public async Task SslHostOverridesTheDialledFormForValidation() } #endif } + + [Fact] + public void DnsEndPointOverridesSslHostForTlsTargetName() + { + // A single shared-VIP seed derives SslHost from its apex name, but every discovered DNS endpoint + // must present its own name so SNI routes the connection to the correct cluster node. + var shard = new DnsEndPoint("host-2.redis.example.com", 443); + Assert.Equal("host-2.redis.example.com", Format.GetTlsHostName(shard, "apex.redis.example.com")); + } + + [Fact] + public void IpEndPointUsesSslHostForTlsTargetName() + { + var address = new IPEndPoint(IPAddress.Loopback, 443); + Assert.Equal("certificate.redis.example.com", Format.GetTlsHostName(address, "certificate.redis.example.com")); + } } From e001032c01d447525b655ef9f5b41c9457084c1d Mon Sep 17 00:00:00 2001 From: Sandeep Kunusoth Date: Tue, 22 Sep 2026 02:03:12 -0500 Subject: [PATCH 2/6] fixed tests Signed-off-by: Sandeep Kunusoth --- .../ClusterTlsIdentityTests.cs | 17 +------ .../TlsHostNameUnitTests.cs | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs diff --git a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs index 77f6fb728..9fdc6eaa5 100644 --- a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs +++ b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs @@ -38,7 +38,7 @@ public async Task HostnamePreferredClusterValidatesAgainstAHostnameOnlyCertifica var config = server.GetClientConfig(defaultOnly: true); config.EndPoints.Clear(); config.EndPoints.Add(new DnsEndPoint(Hostname, port)); - config.SslHost = "apex.redis.example.com"; // the seed-derived name must not replace per-node SNI + config.SslHost = "host-2.redis.example.com"; // the configured name must not replace per-node SNI await using var conn = await ConnectionMultiplexer.ConnectAsync(config); var db = conn.GetDatabase(); @@ -111,19 +111,4 @@ public async Task SslHostOverridesTheDialledFormForValidation() #endif } - [Fact] - public void DnsEndPointOverridesSslHostForTlsTargetName() - { - // A single shared-VIP seed derives SslHost from its apex name, but every discovered DNS endpoint - // must present its own name so SNI routes the connection to the correct cluster node. - var shard = new DnsEndPoint("host-2.redis.example.com", 443); - Assert.Equal("host-2.redis.example.com", Format.GetTlsHostName(shard, "apex.redis.example.com")); - } - - [Fact] - public void IpEndPointUsesSslHostForTlsTargetName() - { - var address = new IPEndPoint(IPAddress.Loopback, 443); - Assert.Equal("certificate.redis.example.com", Format.GetTlsHostName(address, "certificate.redis.example.com")); - } } diff --git a/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs b/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs new file mode 100644 index 000000000..9442b3d10 --- /dev/null +++ b/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs @@ -0,0 +1,47 @@ +using System.Net; +using Xunit; + +namespace StackExchange.Redis.Tests; + +/// +/// TLS target-host selection for SNI and certificate validation. +/// +public class TlsHostNameUnitTests +{ + [Fact] + public void DnsEndPointUsesItsOwnHostEvenWhenSslHostIsSet() + { + var endpoint = new DnsEndPoint("host-2.redis.example.com", 443); + Assert.Equal("host-2.redis.example.com", Format.GetTlsHostName(endpoint, "host-1.redis.example.com")); + } + + [Fact] + public void IpEndPointPrefersConfiguredSslHost() + { + var endpoint = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 6379); + Assert.Equal("mycache.redis.example.com", Format.GetTlsHostName(endpoint, "mycache.redis.example.com")); + } + + [Fact] + public void IpEndPointFallsBackToAddressWhenSslHostMissing() + { + var endpoint = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 6379); + Assert.Equal("10.0.0.1", Format.GetTlsHostName(endpoint, null)); + Assert.Equal("10.0.0.1", Format.GetTlsHostName(endpoint, "")); + } + + [Fact] + public void TlsOptionsResolveHostMatchesFormatHelper() + { + var options = new ConfigurationOptions + { + EndPoints = { "host-1.redis.example.com:443" }, + Ssl = true, + SslHost = "host-1.redis.example.com", + }; + var tls = new Configuration.TlsOptions(options); + + Assert.Equal("host-2.redis.example.com", tls.ResolveHost(new DnsEndPoint("host-2.redis.example.com", 443))); + Assert.Equal("host-1.redis.example.com", tls.ResolveHost(new IPEndPoint(IPAddress.Parse("10.0.0.1"), 443))); + } +} From d71afabf31fc56d90a11d60ca02757148e9c1ecd Mon Sep 17 00:00:00 2001 From: Sandeep Kunusoth Date: Tue, 22 Sep 2026 02:05:16 -0500 Subject: [PATCH 3/6] removed space Signed-off-by: Sandeep Kunusoth --- tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs index 9fdc6eaa5..6821a6936 100644 --- a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs +++ b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs @@ -110,5 +110,4 @@ public async Task SslHostOverridesTheDialledFormForValidation() } #endif } - } From 0fdaba8dc440115b0e9592094b7ac2edfb88dc04 Mon Sep 17 00:00:00 2001 From: Sandeep Kunusoth Date: Tue, 22 Sep 2026 03:02:35 -0500 Subject: [PATCH 4/6] fixed comments Signed-off-by: Sandeep Kunusoth --- .../Configuration/LoggingTunnel.cs | 2 +- .../Configuration/TlsOptions.cs | 8 ++- .../ConfigurationOptions.cs | 20 +++++-- src/StackExchange.Redis/Format.cs | 13 ++-- src/StackExchange.Redis/PhysicalConnection.cs | 2 +- .../ClusterTlsIdentityTests.cs | 1 - tests/StackExchange.Redis.Tests/SSLTests.cs | 6 +- .../TlsHostNameUnitTests.cs | 59 ++++++++++++++++--- 8 files changed, 82 insertions(+), 29 deletions(-) diff --git a/src/StackExchange.Redis/Configuration/LoggingTunnel.cs b/src/StackExchange.Redis/Configuration/LoggingTunnel.cs index 78b0b9af3..3fb023c9f 100644 --- a/src/StackExchange.Redis/Configuration/LoggingTunnel.cs +++ b/src/StackExchange.Redis/Configuration/LoggingTunnel.cs @@ -407,7 +407,7 @@ private async Task TlsHandshakeAsync(Stream stream, EndPoint endpoint) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { // mirrors TLS handshake from PhysicalConnection, but wouldn't help to share code here - var host = Format.GetTlsHostName(endpoint, _options.SslHost); + var host = _options.ResolveTlsHostName(endpoint); var ssl = new SslStream( innerStream: stream, diff --git a/src/StackExchange.Redis/Configuration/TlsOptions.cs b/src/StackExchange.Redis/Configuration/TlsOptions.cs index f01378607..52798f694 100644 --- a/src/StackExchange.Redis/Configuration/TlsOptions.cs +++ b/src/StackExchange.Redis/Configuration/TlsOptions.cs @@ -96,8 +96,10 @@ public LocalCertificateSelectionCallback? CertificateSelectionCallback #endif /// - /// The TLS host name to use for the given endpoint. A uses its own host - /// (required for SNI routing); an address endpoint uses when set, otherwise its address. + /// The TLS host name to use for the given endpoint. An explicitly configured always + /// wins. Otherwise, a uses its own host, and an address endpoint uses the inferred + /// configuration host when available before falling back to its address. /// - public string ResolveHost(EndPoint endpoint) => Format.GetTlsHostName(endpoint, SslHost); + public string ResolveHost(EndPoint endpoint) + => _options?.ResolveTlsHostName(endpoint) ?? Format.ToStringHostOnly(endpoint); } diff --git a/src/StackExchange.Redis/ConfigurationOptions.cs b/src/StackExchange.Redis/ConfigurationOptions.cs index fc3b99ad3..75a23c630 100644 --- a/src/StackExchange.Redis/ConfigurationOptions.cs +++ b/src/StackExchange.Redis/ConfigurationOptions.cs @@ -957,19 +957,29 @@ public bool Ssl } /// - /// The target host to use when validating an SSL certificate for connections that dial an - /// (or when no per-endpoint DNS name is available). Setting a value here enables SSL mode. + /// The target host to use for SNI and certificate validation; setting a value here enables SSL mode. /// /// - /// Connections to a use that endpoint's host for SNI and certificate validation, - /// not this property. This allows hostname-routed clusters to use a distinct SNI name for each node. + /// When explicitly configured, this overrides the host for every endpoint. When unset, connections to a + /// use that endpoint's host, allowing hostname-routed clusters to use a distinct + /// SNI name for each node. /// public string? SslHost { - get => sslHost ?? Defaults.GetSslHostFromEndpoints(EndPoints); + get => sslHost; set => sslHost = value; } + internal string ResolveTlsHostName(EndPoint endpoint) + { + var host = sslHost; + if (host.IsNullOrWhiteSpace() && endpoint is not DnsEndPoint) + { + host = Defaults.GetSslHostFromEndpoints(EndPoints); + } + return Format.GetTlsHostName(endpoint, host); + } + /// /// Configures which SSL/TLS protocols should be allowed. If not set, defaults are chosen by the .NET framework. /// diff --git a/src/StackExchange.Redis/Format.cs b/src/StackExchange.Redis/Format.cs index 779254e9b..a57bea0cd 100644 --- a/src/StackExchange.Redis/Format.cs +++ b/src/StackExchange.Redis/Format.cs @@ -135,20 +135,19 @@ internal static string ToStringHostOnly(EndPoint endpoint) => /// Gets the TLS SNI and certificate-validation host for a connection to . /// /// - /// A always uses its own host so hostname-routed clusters present the - /// correct SNI for each discovered node. An address endpoint still honors - /// so dial-by-IP deployments can validate a certificate name. + /// An explicitly configured wins. Otherwise, a + /// uses its own host and any other endpoint uses its address. /// internal static string GetTlsHostName(EndPoint endpoint, string? sslHost) { - if (endpoint is DnsEndPoint dns && !dns.Host.IsNullOrWhiteSpace()) + if (!sslHost.IsNullOrWhiteSpace()) { - return dns.Host; + return sslHost; } - if (!sslHost.IsNullOrWhiteSpace()) + if (endpoint is DnsEndPoint dns && !dns.Host.IsNullOrWhiteSpace()) { - return sslHost; + return dns.Host; } return ToStringHostOnly(endpoint); diff --git a/src/StackExchange.Redis/PhysicalConnection.cs b/src/StackExchange.Redis/PhysicalConnection.cs index 88a54d7e7..cbedd4225 100644 --- a/src/StackExchange.Redis/PhysicalConnection.cs +++ b/src/StackExchange.Redis/PhysicalConnection.cs @@ -1226,7 +1226,7 @@ static Stream DemandSocketStream(Socket? socket) if (config.Ssl) { log?.LogInformationConfiguringTLS(); - var host = Format.GetTlsHostName(bridge.ServerEndPoint.EndPoint, config.SslHost); + var host = config.ResolveTlsHostName(bridge.ServerEndPoint.EndPoint); stream ??= DemandSocketStream(socket); var ssl = new SslStream( diff --git a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs index 6821a6936..21ce97598 100644 --- a/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs +++ b/tests/StackExchange.Redis.Tests/ClusterTlsIdentityTests.cs @@ -38,7 +38,6 @@ public async Task HostnamePreferredClusterValidatesAgainstAHostnameOnlyCertifica var config = server.GetClientConfig(defaultOnly: true); config.EndPoints.Clear(); config.EndPoints.Add(new DnsEndPoint(Hostname, port)); - config.SslHost = "host-2.redis.example.com"; // the configured name must not replace per-node SNI await using var conn = await ConnectionMultiplexer.ConnectAsync(config); var db = conn.GetDatabase(); diff --git a/tests/StackExchange.Redis.Tests/SSLTests.cs b/tests/StackExchange.Redis.Tests/SSLTests.cs index 731701755..2230af9c6 100644 --- a/tests/StackExchange.Redis.Tests/SSLTests.cs +++ b/tests/StackExchange.Redis.Tests/SSLTests.cs @@ -364,7 +364,7 @@ public async Task RedisLabsEnvironmentVariableClientCertificate(bool setEnv) } [Fact] - public void SSLHostInferredFromEndpoints() + public void SSLHostIsOnlyExplicitlyConfigured() { var options = new ConfigurationOptions { @@ -376,7 +376,9 @@ public void SSLHostInferredFromEndpoints() }, Ssl = true, }; - Assert.Equal("mycache.rediscache.windows.net", options.SslHost); + Assert.Null(options.SslHost); + options.SslHost = "override.rediscache.windows.net"; + Assert.Equal("override.rediscache.windows.net", options.SslHost); options = new ConfigurationOptions() { EndPoints = { { "121.23.23.45", 15000 } }, diff --git a/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs b/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs index 9442b3d10..e2ac6742a 100644 --- a/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs +++ b/tests/StackExchange.Redis.Tests/TlsHostNameUnitTests.cs @@ -9,35 +9,76 @@ namespace StackExchange.Redis.Tests; public class TlsHostNameUnitTests { [Fact] - public void DnsEndPointUsesItsOwnHostEvenWhenSslHostIsSet() + public void ExplicitSslHostOverridesDnsEndPoint() { var endpoint = new DnsEndPoint("host-2.redis.example.com", 443); - Assert.Equal("host-2.redis.example.com", Format.GetTlsHostName(endpoint, "host-1.redis.example.com")); + var options = new ConfigurationOptions { SslHost = "host-1.redis.example.com" }; + Assert.Equal("host-1.redis.example.com", options.ResolveTlsHostName(endpoint)); } [Fact] - public void IpEndPointPrefersConfiguredSslHost() + public void DnsEndPointUsesItsOwnHostInsteadOfInferredHost() + { + var options = new ConfigurationOptions + { + EndPoints = { "host-1.redis.example.com:443" }, + }; + + Assert.Null(options.SslHost); + Assert.Equal("host-2.redis.example.com", options.ResolveTlsHostName(new DnsEndPoint("host-2.redis.example.com", 443))); + } + + [Fact] + public void IpEndPointPrefersExplicitSslHost() { var endpoint = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 6379); - Assert.Equal("mycache.redis.example.com", Format.GetTlsHostName(endpoint, "mycache.redis.example.com")); + var options = new ConfigurationOptions + { + EndPoints = { "host-1.redis.example.com:443" }, + SslHost = "mycache.redis.example.com", + }; + Assert.Equal("mycache.redis.example.com", options.ResolveTlsHostName(endpoint)); + } + + [Fact] + public void IpEndPointUsesInferredHost() + { + var options = new ConfigurationOptions + { + EndPoints = { "host-1.redis.example.com:443" }, + }; + Assert.Equal("host-1.redis.example.com", options.ResolveTlsHostName(new IPEndPoint(IPAddress.Parse("10.0.0.1"), 6379))); } [Fact] - public void IpEndPointFallsBackToAddressWhenSslHostMissing() + public void IpEndPointFallsBackToAddressWhenHostsAreMissing() { var endpoint = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 6379); - Assert.Equal("10.0.0.1", Format.GetTlsHostName(endpoint, null)); - Assert.Equal("10.0.0.1", Format.GetTlsHostName(endpoint, "")); + Assert.Equal("10.0.0.1", new ConfigurationOptions().ResolveTlsHostName(endpoint)); + } + + [Fact] + public void TlsOptionsResolveHostHonorsExplicitOverride() + { + var options = new ConfigurationOptions + { + EndPoints = { "host-1.redis.example.com:443" }, + Ssl = true, + SslHost = "override.redis.example.com", + }; + var tls = new Configuration.TlsOptions(options); + + Assert.Equal("override.redis.example.com", tls.ResolveHost(new DnsEndPoint("host-2.redis.example.com", 443))); + Assert.Equal("override.redis.example.com", tls.ResolveHost(new IPEndPoint(IPAddress.Parse("10.0.0.1"), 443))); } [Fact] - public void TlsOptionsResolveHostMatchesFormatHelper() + public void TlsOptionsResolveHostUsesEndpointBeforeInferredHost() { var options = new ConfigurationOptions { EndPoints = { "host-1.redis.example.com:443" }, Ssl = true, - SslHost = "host-1.redis.example.com", }; var tls = new Configuration.TlsOptions(options); From 9f7fd9b27047fe0961ba7a84e62595693bdb9d53 Mon Sep 17 00:00:00 2001 From: Sandeep Kunusoth Date: Tue, 22 Sep 2026 03:16:57 -0500 Subject: [PATCH 5/6] Retrigger CI Signed-off-by: Sandeep Kunusoth From 01ee74d61b1b72a036d06061db45c744c7455767 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 22 Sep 2026 10:05:48 +0100 Subject: [PATCH 6/6] Clarify GetSslHostFromEndpoints applicability in doc comment Only consulted for non-DnsEndPoint connections now that SslHost resolution no longer infers a host for endpoints that already carry their own. --- .../Configuration/DefaultOptionsProvider.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/StackExchange.Redis/Configuration/DefaultOptionsProvider.cs b/src/StackExchange.Redis/Configuration/DefaultOptionsProvider.cs index 055c3d23d..f3866f37c 100644 --- a/src/StackExchange.Redis/Configuration/DefaultOptionsProvider.cs +++ b/src/StackExchange.Redis/Configuration/DefaultOptionsProvider.cs @@ -486,8 +486,14 @@ protected virtual string GetDefaultClientName() => public virtual bool GetDefaultSsl(EndPointCollection endPoints) => false; /// - /// Gets the SSL Host to check for when connecting to endpoints (customizable in case of internal certificate shenanigans. + /// Gets the SSL host to infer when is not explicitly set, for + /// endpoints that don't already carry their own host name (customizable in case of internal certificate shenanigans). /// + /// + /// Only consulted for non- connections - a always uses its + /// own instead, so in practice this applies to IP endpoints, such as ones + /// discovered via cluster topology. + /// /// The configured endpoints to determine SSL host from (e.g. from the port). /// The common host, if any, detected from the endpoint collection. public virtual string? GetSslHostFromEndpoints(EndPointCollection endPoints)