feat: Disable SNI for STARTTLS (#7499)

Many clients don't send it currently, so it is unlikely that servers depend on it:
https://mastodon.social/@cks/114690055923939576.

For "implicit TLS", do not turn it off yet, it will serve as a fallback in case of rare server that
needs it. If the server only supports STARTTLS and requires SNI then it is really weird, likely
should not happen.
This commit is contained in:
iequidoo
2025-12-02 16:24:53 -03:00
committed by iequidoo
parent 8bce137e06
commit 676132457f
6 changed files with 43 additions and 6 deletions

View File

@@ -207,6 +207,7 @@ impl Client {
hostname: &str,
strict_tls: bool,
) -> Result<Self> {
let use_sni = true;
let tcp_stream = connect_tcp_inner(addr).await?;
let account_id = context.get_id();
let events = context.events.clone();
@@ -215,6 +216,7 @@ impl Client {
strict_tls,
hostname,
addr.port(),
use_sni,
alpn(addr.port()),
logging_stream,
&context.tls_session_store,
@@ -251,6 +253,7 @@ impl Client {
host: &str,
strict_tls: bool,
) -> Result<Self> {
let use_sni = false;
let tcp_stream = connect_tcp_inner(addr).await?;
let account_id = context.get_id();
@@ -275,6 +278,7 @@ impl Client {
strict_tls,
host,
addr.port(),
use_sni,
"",
tcp_stream,
&context.tls_session_store,
@@ -294,6 +298,7 @@ impl Client {
strict_tls: bool,
proxy_config: ProxyConfig,
) -> Result<Self> {
let use_sni = true;
let proxy_stream = proxy_config
.connect(context, domain, port, strict_tls)
.await?;
@@ -301,6 +306,7 @@ impl Client {
strict_tls,
domain,
port,
use_sni,
alpn(port),
proxy_stream,
&context.tls_session_store,
@@ -340,6 +346,7 @@ impl Client {
proxy_config: ProxyConfig,
strict_tls: bool,
) -> Result<Self> {
let use_sni = false;
let proxy_stream = proxy_config
.connect(context, hostname, port, strict_tls)
.await?;
@@ -362,6 +369,7 @@ impl Client {
strict_tls,
hostname,
port,
use_sni,
"",
proxy_stream,
&context.tls_session_store,

View File

@@ -131,11 +131,13 @@ pub(crate) async fn connect_tls_inner(
alpn: &str,
tls_session_store: &TlsSessionStore,
) -> Result<impl SessionStream + 'static> {
let use_sni = true;
let tcp_stream = connect_tcp_inner(addr).await?;
let tls_stream = wrap_tls(
strict_tls,
host,
addr.port(),
use_sni,
alpn,
tcp_stream,
tls_session_store,

View File

@@ -74,19 +74,33 @@ where
}
"https" => {
let port = parsed_url.port_u16().unwrap_or(443);
let load_cache = true;
let (use_sni, load_cache) = (true, true);
if let Some(proxy_config) = proxy_config_opt {
let proxy_stream = proxy_config
.connect(context, host, port, load_cache)
.await?;
let tls_stream =
wrap_rustls(host, port, "", proxy_stream, &context.tls_session_store).await?;
let tls_stream = wrap_rustls(
host,
port,
use_sni,
"",
proxy_stream,
&context.tls_session_store,
)
.await?;
Box::new(tls_stream)
} else {
let tcp_stream = crate::net::connect_tcp(context, host, port, load_cache).await?;
let tls_stream =
wrap_rustls(host, port, "", tcp_stream, &context.tls_session_store).await?;
let tls_stream = wrap_rustls(
host,
port,
use_sni,
"",
tcp_stream,
&context.tls_session_store,
)
.await?;
Box::new(tls_stream)
}
}

View File

@@ -429,9 +429,11 @@ impl ProxyConfig {
load_cache,
)
.await?;
let use_sni = true;
let tls_stream = wrap_rustls(
&https_config.host,
https_config.port,
use_sni,
"",
tcp_stream,
&context.tls_session_store,

View File

@@ -13,12 +13,14 @@ pub async fn wrap_tls<'a>(
strict_tls: bool,
hostname: &str,
port: u16,
use_sni: bool,
alpn: &str,
stream: impl SessionStream + 'static,
tls_session_store: &TlsSessionStore,
) -> Result<impl SessionStream + 'a> {
if strict_tls {
let tls_stream = wrap_rustls(hostname, port, alpn, stream, tls_session_store).await?;
let tls_stream =
wrap_rustls(hostname, port, use_sni, alpn, stream, tls_session_store).await?;
let boxed_stream: Box<dyn SessionStream> = Box::new(tls_stream);
Ok(boxed_stream)
} else {
@@ -32,6 +34,7 @@ pub async fn wrap_tls<'a>(
};
let tls = async_native_tls::TlsConnector::new()
.min_protocol_version(Some(async_native_tls::Protocol::Tlsv12))
.use_sni(use_sni)
.request_alpns(&alpns)
.danger_accept_invalid_hostnames(true)
.danger_accept_invalid_certs(true);
@@ -90,6 +93,7 @@ impl TlsSessionStore {
pub async fn wrap_rustls<'a>(
hostname: &str,
port: u16,
use_sni: bool,
alpn: &str,
stream: impl SessionStream + 'a,
tls_session_store: &TlsSessionStore,
@@ -117,6 +121,7 @@ pub async fn wrap_rustls<'a>(
let resumption = tokio_rustls::rustls::client::Resumption::store(resumption_store)
.tls12_resumption(tokio_rustls::rustls::client::Tls12Resumption::Disabled);
config.resumption = resumption;
config.enable_sni = use_sni;
let tls = tokio_rustls::TlsConnector::from(Arc::new(config));
let name = rustls_pki_types::ServerName::try_from(hostname)?.to_owned();

View File

@@ -228,6 +228,7 @@ async fn connect_secure_proxy(
strict_tls: bool,
proxy_config: ProxyConfig,
) -> Result<Box<dyn SessionBufStream>> {
let use_sni = true;
let proxy_stream = proxy_config
.connect(context, hostname, port, strict_tls)
.await?;
@@ -235,6 +236,7 @@ async fn connect_secure_proxy(
strict_tls,
hostname,
port,
use_sni,
alpn(port),
proxy_stream,
&context.tls_session_store,
@@ -253,6 +255,7 @@ async fn connect_starttls_proxy(
strict_tls: bool,
proxy_config: ProxyConfig,
) -> Result<Box<dyn SessionBufStream>> {
let use_sni = false;
let proxy_stream = proxy_config
.connect(context, hostname, port, strict_tls)
.await?;
@@ -266,6 +269,7 @@ async fn connect_starttls_proxy(
strict_tls,
hostname,
port,
use_sni,
"",
tcp_stream,
&context.tls_session_store,
@@ -316,6 +320,7 @@ async fn connect_starttls(
strict_tls: bool,
tls_session_store: &TlsSessionStore,
) -> Result<Box<dyn SessionBufStream>> {
let use_sni = false;
let tcp_stream = connect_tcp_inner(addr).await?;
// Run STARTTLS command and convert the client back into a stream.
@@ -327,6 +332,7 @@ async fn connect_starttls(
strict_tls,
host,
addr.port(),
use_sni,
"",
tcp_stream,
tls_session_store,