diff --git a/src/conn/mod.rs b/src/conn/mod.rs index 252fbce7..577dd836 100644 --- a/src/conn/mod.rs +++ b/src/conn/mod.rs @@ -550,7 +550,10 @@ impl Conn { self.write_struct(&ssl_request).await?; let conn = self; let ssl_opts = conn.opts().ssl_opts().cloned().expect("unreachable"); - let domain = conn.opts().ip_or_hostname().into(); + let domain = ssl_opts + .tls_hostname_override() + .unwrap_or_else(|| conn.opts().ip_or_hostname()) + .into(); conn.stream_mut()?.make_secure(domain, ssl_opts).await?; Ok(()) } else { diff --git a/src/io/tls/rustls_io.rs b/src/io/tls/rustls_io.rs index ceccc539..5edce5c9 100644 --- a/src/io/tls/rustls_io.rs +++ b/src/io/tls/rustls_io.rs @@ -136,8 +136,7 @@ impl ServerCertVerifier for DangerousVerifier { ) { Ok(assertion) => Ok(assertion), Err(ref e) - if e.to_string().contains("NotValidForName") - && self.skip_domain_validation => + if e.to_string().contains("NotValidForName") && self.skip_domain_validation => { Ok(rustls::client::ServerCertVerified::assertion()) } diff --git a/src/opts/mod.rs b/src/opts/mod.rs index 2ecb0e3a..b50aa4b0 100644 --- a/src/opts/mod.rs +++ b/src/opts/mod.rs @@ -144,6 +144,7 @@ pub struct SslOpts { root_cert_path: Option>, skip_domain_validation: bool, accept_invalid_certs: bool, + tls_hostname_override: Option>, } impl SslOpts { @@ -178,6 +179,18 @@ impl SslOpts { self } + /// If set, will override the hostname used to verify the server's certificate. + /// + /// This is useful when connecting to a server via a tunnel, where the server hostname + /// name is different from the hostname used to connect to the tunnel. + pub fn with_tls_hostname_override>>( + mut self, + domain: Option, + ) -> Self { + self.tls_hostname_override = domain.map(Into::into); + self + } + #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] pub fn client_identity(&self) -> Option<&ClientIdentity> { self.client_identity.as_ref() @@ -194,6 +207,10 @@ impl SslOpts { pub fn accept_invalid_certs(&self) -> bool { self.accept_invalid_certs } + + pub fn tls_hostname_override(&self) -> Option<&str> { + self.tls_hostname_override.as_ref().map(AsRef::as_ref) + } } /// Connection pool options.