refact: tls fallback, rustls -> native-tls
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
153
src/proxy.rs
153
src/proxy.rs
@@ -411,9 +411,9 @@ impl Proxy {
|
|||||||
let url = format!("https://{}", self.intercept.get_host_and_port()?);
|
let url = format!("https://{}", self.intercept.get_host_and_port()?);
|
||||||
let tls_type = get_cached_tls_type(&url);
|
let tls_type = get_cached_tls_type(&url);
|
||||||
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(&url);
|
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(&url);
|
||||||
let stream = match tls_type.unwrap_or(TlsType::NativeTls) {
|
let stream = match tls_type.unwrap_or(TlsType::Rustls) {
|
||||||
TlsType::NativeTls => {
|
TlsType::Rustls => {
|
||||||
self.https_connect_nativetls_wrap_danger(
|
self.https_connect_rustls_wrap_danger(
|
||||||
&url,
|
&url,
|
||||||
local,
|
local,
|
||||||
proxy,
|
proxy,
|
||||||
@@ -425,8 +425,8 @@ impl Proxy {
|
|||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
TlsType::Rustls => {
|
TlsType::NativeTls => {
|
||||||
self.https_connect_rustls_wrap_danger(
|
self.https_connect_nativetls_wrap_danger(
|
||||||
&url,
|
&url,
|
||||||
local,
|
local,
|
||||||
proxy,
|
proxy,
|
||||||
@@ -477,77 +477,30 @@ impl Proxy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
|
||||||
async fn https_connect_nativetls_wrap_danger<'a>(
|
async fn https_connect_nativetls_wrap_danger<'a>(
|
||||||
&self,
|
&self,
|
||||||
url: &str,
|
url: &str,
|
||||||
local: SocketAddr,
|
local: SocketAddr,
|
||||||
proxy: SocketAddr,
|
proxy: SocketAddr,
|
||||||
stream: Option<tokio::net::TcpStream>,
|
|
||||||
target_addr: &TargetAddr<'a>,
|
target_addr: &TargetAddr<'a>,
|
||||||
is_tls_type_cached: bool,
|
|
||||||
danger_accept_invalid_cert: Option<bool>,
|
danger_accept_invalid_cert: Option<bool>,
|
||||||
origin_danger_accept_invalid_cert: Option<bool>,
|
|
||||||
) -> ResultType<DynTcpStream> {
|
) -> ResultType<DynTcpStream> {
|
||||||
let stream = stream.unwrap_or(self.new_stream(local, proxy).await?);
|
let stream = self.new_stream(local, proxy).await?;
|
||||||
match super::timeout(
|
let s = super::timeout(
|
||||||
self.ms_timeout,
|
self.ms_timeout,
|
||||||
self.https_connect_nativetls(
|
self.https_connect_nativetls(
|
||||||
stream,
|
stream,
|
||||||
target_addr,
|
&target_addr,
|
||||||
danger_accept_invalid_cert.unwrap_or(false),
|
danger_accept_invalid_cert.unwrap_or(false),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.await?
|
.await??;
|
||||||
{
|
upsert_tls_cache(
|
||||||
Ok(s) => {
|
url,
|
||||||
upsert_tls_cache(
|
TlsType::NativeTls,
|
||||||
&url,
|
danger_accept_invalid_cert.unwrap_or(false),
|
||||||
TlsType::NativeTls,
|
);
|
||||||
danger_accept_invalid_cert.unwrap_or(false),
|
Ok(DynTcpStream(Box::new(s)))
|
||||||
);
|
|
||||||
Ok(DynTcpStream(Box::new(s)))
|
|
||||||
}
|
|
||||||
Err(ProxyError::NativeTlsError(e)) => {
|
|
||||||
let s = if danger_accept_invalid_cert.is_none() {
|
|
||||||
log::warn!(
|
|
||||||
"Falling back to native-tls (accept invalid cert) for HTTPS proxy server."
|
|
||||||
);
|
|
||||||
self.https_connect_nativetls_wrap_danger(
|
|
||||||
&url,
|
|
||||||
local,
|
|
||||||
proxy,
|
|
||||||
None,
|
|
||||||
target_addr,
|
|
||||||
is_tls_type_cached,
|
|
||||||
Some(true),
|
|
||||||
origin_danger_accept_invalid_cert,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else if !is_tls_type_cached {
|
|
||||||
log::warn!("Falling back to rustls for HTTPS proxy server.");
|
|
||||||
self.https_connect_rustls_wrap_danger(
|
|
||||||
&url,
|
|
||||||
local,
|
|
||||||
proxy,
|
|
||||||
&target_addr,
|
|
||||||
origin_danger_accept_invalid_cert,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else {
|
|
||||||
log::error!(
|
|
||||||
"Failed to connect to HTTPS proxy server with native-tls: {:?}.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
bail!(e)
|
|
||||||
};
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Failed to connect to HTTPS proxy server: {:?}.", e);
|
|
||||||
bail!(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn https_connect_nativetls<'a, Input>(
|
pub async fn https_connect_nativetls<'a, Input>(
|
||||||
@@ -570,30 +523,86 @@ impl Proxy {
|
|||||||
self.http_connect(stream, target_addr).await
|
self.http_connect(stream, target_addr).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_recursion]
|
||||||
async fn https_connect_rustls_wrap_danger<'a>(
|
async fn https_connect_rustls_wrap_danger<'a>(
|
||||||
&self,
|
&self,
|
||||||
url: &str,
|
url: &str,
|
||||||
local: SocketAddr,
|
local: SocketAddr,
|
||||||
proxy: SocketAddr,
|
proxy: SocketAddr,
|
||||||
|
stream: Option<tokio::net::TcpStream>,
|
||||||
target_addr: &TargetAddr<'a>,
|
target_addr: &TargetAddr<'a>,
|
||||||
|
is_tls_type_cached: bool,
|
||||||
danger_accept_invalid_cert: Option<bool>,
|
danger_accept_invalid_cert: Option<bool>,
|
||||||
|
origin_danger_accept_invalid_cert: Option<bool>,
|
||||||
) -> ResultType<DynTcpStream> {
|
) -> ResultType<DynTcpStream> {
|
||||||
let stream = self.new_stream(local, proxy).await?;
|
let stream = stream.unwrap_or(self.new_stream(local, proxy).await?);
|
||||||
let s = super::timeout(
|
match super::timeout(
|
||||||
self.ms_timeout,
|
self.ms_timeout,
|
||||||
self.https_connect_rustls(
|
self.https_connect_rustls(
|
||||||
stream,
|
stream,
|
||||||
&target_addr,
|
target_addr,
|
||||||
danger_accept_invalid_cert.unwrap_or(false),
|
danger_accept_invalid_cert.unwrap_or(false),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.await??;
|
.await?
|
||||||
upsert_tls_cache(
|
{
|
||||||
url,
|
Ok(s) => {
|
||||||
TlsType::Rustls,
|
upsert_tls_cache(
|
||||||
danger_accept_invalid_cert.unwrap_or(false),
|
&url,
|
||||||
);
|
TlsType::Rustls,
|
||||||
Ok(DynTcpStream(Box::new(s)))
|
danger_accept_invalid_cert.unwrap_or(false),
|
||||||
|
);
|
||||||
|
Ok(DynTcpStream(Box::new(s)))
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// NOTE: Maybe it's better to check if the error is related to TLS here. (ProxyError::IoError(e), or ProxyError::NativeTlsError(e))
|
||||||
|
// But we can only get the error when the TLS protocol is TLSv1.1.
|
||||||
|
// The error message of the following is unclear:
|
||||||
|
// https://github.com/rustdesk/rustdesk-server-pro/issues/189#issuecomment-1895701480
|
||||||
|
// So we just try to fallback unconditionally here.
|
||||||
|
//
|
||||||
|
// If the protocol is TLS 1.1, the error is:
|
||||||
|
// 1. "IO Error: received fatal alert: ProtocolVersion"
|
||||||
|
// 2. "IO Error: An existing connection was forcibly closed by the remote host. (os error 10054)" on Windows sometimes.
|
||||||
|
//
|
||||||
|
// If the cert verification fails, the error is:
|
||||||
|
// "IO Error: invalid peer certificate: UnknownIssuer"
|
||||||
|
|
||||||
|
let s = if danger_accept_invalid_cert.is_none() {
|
||||||
|
log::warn!(
|
||||||
|
"Falling back to rustls-tls (accept invalid cert) for HTTPS proxy server."
|
||||||
|
);
|
||||||
|
self.https_connect_rustls_wrap_danger(
|
||||||
|
&url,
|
||||||
|
local,
|
||||||
|
proxy,
|
||||||
|
None,
|
||||||
|
target_addr,
|
||||||
|
is_tls_type_cached,
|
||||||
|
Some(true),
|
||||||
|
origin_danger_accept_invalid_cert,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
} else if !is_tls_type_cached {
|
||||||
|
log::warn!("Falling back to native-tls for HTTPS proxy server.");
|
||||||
|
self.https_connect_nativetls_wrap_danger(
|
||||||
|
&url,
|
||||||
|
local,
|
||||||
|
proxy,
|
||||||
|
&target_addr,
|
||||||
|
origin_danger_accept_invalid_cert,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
} else {
|
||||||
|
log::error!(
|
||||||
|
"Failed to connect to HTTPS proxy server with native-tls: {:?}.",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
bail!(e)
|
||||||
|
};
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn https_connect_rustls<'a, Input>(
|
pub async fn https_connect_rustls<'a, Input>(
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl WsFramedStream {
|
|||||||
|
|
||||||
let tls_type = get_cached_tls_type(url);
|
let tls_type = get_cached_tls_type(url);
|
||||||
let is_tls_type_cached = tls_type.is_some();
|
let is_tls_type_cached = tls_type.is_some();
|
||||||
let tls_type = tls_type.unwrap_or(TlsType::NativeTls);
|
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
|
||||||
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(&url);
|
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(&url);
|
||||||
Self::try_connect(
|
Self::try_connect(
|
||||||
url,
|
url,
|
||||||
@@ -113,9 +113,9 @@ impl WsFramedStream {
|
|||||||
Ok(ws_stream)
|
Ok(ws_stream)
|
||||||
}
|
}
|
||||||
Err(e) => match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
|
Err(e) => match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
|
||||||
(TlsType::NativeTls, _, None) => {
|
(TlsType::Rustls, _, None) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"WebSocket connection with native-tls failed, try accept invalid certs: {}, {:?}",
|
"WebSocket connection with rustls-tls failed, try accept invalid certs: {}, {:?}",
|
||||||
url,
|
url,
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
@@ -129,25 +129,25 @@ impl WsFramedStream {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
(TlsType::NativeTls, false, Some(_)) => {
|
(TlsType::Rustls, false, Some(_)) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"WebSocket connection with native-tls failed, try rustls: {}, {:?}",
|
"WebSocket connection with rustls-tls failed, try native-tls: {}, {:?}",
|
||||||
url,
|
url,
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
Self::try_connect(
|
Self::try_connect(
|
||||||
url,
|
url,
|
||||||
ms_timeout,
|
ms_timeout,
|
||||||
TlsType::Rustls,
|
TlsType::NativeTls,
|
||||||
is_tls_type_cached,
|
is_tls_type_cached,
|
||||||
original_danger_accept_invalid_certs,
|
original_danger_accept_invalid_certs,
|
||||||
original_danger_accept_invalid_certs,
|
original_danger_accept_invalid_certs,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
(TlsType::Rustls, _, None) => {
|
(TlsType::NativeTls, _, None) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"WebSocket connection with rustls failed, try accept invalid certs: {}, {:?}",
|
"WebSocket connection with native-tls failed, try accept invalid certs: {}, {:?}",
|
||||||
url,
|
url,
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user