refact: tls, native-tls fallback rustls-tls (#13263)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
+271
-16
@@ -1,23 +1,49 @@
|
||||
use hbb_common::config::Config;
|
||||
use hbb_common::log::info;
|
||||
use hbb_common::proxy::{Proxy, ProxyScheme};
|
||||
use reqwest::blocking::Client as SyncClient;
|
||||
use reqwest::Client as AsyncClient;
|
||||
use hbb_common::{
|
||||
async_recursion::async_recursion,
|
||||
config::{Config, Socks5Server},
|
||||
log::{self, info},
|
||||
proxy::{Proxy, ProxyScheme},
|
||||
tls::{
|
||||
get_cached_tls_accept_invalid_cert, get_cached_tls_type, is_plain, upsert_tls_cache,
|
||||
TlsType,
|
||||
},
|
||||
};
|
||||
use reqwest::{blocking::Client as SyncClient, Client as AsyncClient};
|
||||
|
||||
macro_rules! configure_http_client {
|
||||
($builder:expr, $Client: ty) => {{
|
||||
($builder:expr, $tls_type:expr, $danger_accept_invalid_cert:expr, $Client: ty) => {{
|
||||
// https://github.com/rustdesk/rustdesk/issues/11569
|
||||
// https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.no_proxy
|
||||
let mut builder = $builder.no_proxy();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
match hbb_common::verifier::client_config() {
|
||||
Ok(client_config) => {
|
||||
builder = builder.use_preconfigured_tls(client_config);
|
||||
|
||||
match $tls_type {
|
||||
TlsType::Plain => {}
|
||||
TlsType::NativeTls => {
|
||||
builder = builder.use_native_tls();
|
||||
if $danger_accept_invalid_cert {
|
||||
builder = builder.danger_accept_invalid_certs(true);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
hbb_common::log::error!("Failed to get client config: {}", e);
|
||||
TlsType::Rustls => {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
match hbb_common::verifier::client_config($danger_accept_invalid_cert) {
|
||||
Ok(client_config) => {
|
||||
builder = builder.use_preconfigured_tls(client_config);
|
||||
}
|
||||
Err(e) => {
|
||||
hbb_common::log::error!("Failed to get client config: {}", e);
|
||||
}
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
builder = builder.use_rustls_tls();
|
||||
if $danger_accept_invalid_cert {
|
||||
builder = builder.danger_accept_invalid_certs(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let client = if let Some(conf) = Config::get_socks() {
|
||||
let proxy_result = Proxy::from_conf(&conf, None);
|
||||
|
||||
@@ -70,12 +96,241 @@ macro_rules! configure_http_client {
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn create_http_client() -> SyncClient {
|
||||
pub fn create_http_client(tls_type: TlsType, danger_accept_invalid_cert: bool) -> SyncClient {
|
||||
let builder = SyncClient::builder();
|
||||
configure_http_client!(builder, SyncClient)
|
||||
configure_http_client!(builder, tls_type, danger_accept_invalid_cert, SyncClient)
|
||||
}
|
||||
|
||||
pub fn create_http_client_async() -> AsyncClient {
|
||||
pub fn create_http_client_async(
|
||||
tls_type: TlsType,
|
||||
danger_accept_invalid_cert: bool,
|
||||
) -> AsyncClient {
|
||||
let builder = AsyncClient::builder();
|
||||
configure_http_client!(builder, AsyncClient)
|
||||
configure_http_client!(builder, tls_type, danger_accept_invalid_cert, AsyncClient)
|
||||
}
|
||||
|
||||
pub fn get_url_for_tls<'a>(url: &'a str, proxy_conf: &'a Option<Socks5Server>) -> &'a str {
|
||||
if is_plain(url) {
|
||||
if let Some(conf) = proxy_conf {
|
||||
if conf.proxy.starts_with("https://") {
|
||||
return &conf.proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
url
|
||||
}
|
||||
|
||||
pub fn create_http_client_with_url(url: &str) -> SyncClient {
|
||||
let proxy_conf = Config::get_socks();
|
||||
let tls_url = get_url_for_tls(url, &proxy_conf);
|
||||
let tls_type = get_cached_tls_type(tls_url);
|
||||
let is_tls_type_cached = tls_type.is_some();
|
||||
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
|
||||
let tls_danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
|
||||
create_http_client_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
tls_danger_accept_invalid_cert,
|
||||
tls_danger_accept_invalid_cert,
|
||||
)
|
||||
}
|
||||
|
||||
fn create_http_client_with_url_(
|
||||
url: &str,
|
||||
tls_url: &str,
|
||||
tls_type: TlsType,
|
||||
is_tls_type_cached: bool,
|
||||
danger_accept_invalid_cert: Option<bool>,
|
||||
original_danger_accept_invalid_cert: Option<bool>,
|
||||
) -> SyncClient {
|
||||
let mut client = create_http_client(tls_type, danger_accept_invalid_cert.unwrap_or(false));
|
||||
if is_tls_type_cached && original_danger_accept_invalid_cert.is_some() {
|
||||
return client;
|
||||
}
|
||||
if let Err(e) = client.head(url).send() {
|
||||
if e.is_request() {
|
||||
match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
|
||||
(TlsType::Rustls, _, None) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with rustls-tls: {:?}, trying accept invalid cert",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
Some(true),
|
||||
original_danger_accept_invalid_cert,
|
||||
);
|
||||
}
|
||||
(TlsType::Rustls, false, Some(_)) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with rustls-tls: {:?}, trying native-tls",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
TlsType::NativeTls,
|
||||
is_tls_type_cached,
|
||||
original_danger_accept_invalid_cert,
|
||||
original_danger_accept_invalid_cert,
|
||||
);
|
||||
}
|
||||
(TlsType::NativeTls, _, None) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with native-tls: {:?}, trying accept invalid cert",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
Some(true),
|
||||
original_danger_accept_invalid_cert,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
log::error!(
|
||||
"Failed to connect to server {} with {:?}, err: {:?}.",
|
||||
tls_url,
|
||||
tls_type,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with {:?}, err: {}.",
|
||||
tls_url,
|
||||
tls_type,
|
||||
e
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log::info!(
|
||||
"Successfully connected to server {} with {:?}",
|
||||
tls_url,
|
||||
tls_type
|
||||
);
|
||||
upsert_tls_cache(
|
||||
tls_url,
|
||||
tls_type,
|
||||
danger_accept_invalid_cert.unwrap_or(false),
|
||||
);
|
||||
}
|
||||
client
|
||||
}
|
||||
|
||||
pub async fn create_http_client_async_with_url(url: &str) -> AsyncClient {
|
||||
let proxy_conf = Config::get_socks();
|
||||
let tls_url = get_url_for_tls(url, &proxy_conf);
|
||||
let tls_type = get_cached_tls_type(tls_url);
|
||||
let is_tls_type_cached = tls_type.is_some();
|
||||
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
|
||||
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
|
||||
create_http_client_async_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
danger_accept_invalid_cert,
|
||||
danger_accept_invalid_cert,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[async_recursion]
|
||||
async fn create_http_client_async_with_url_(
|
||||
url: &str,
|
||||
tls_url: &str,
|
||||
tls_type: TlsType,
|
||||
is_tls_type_cached: bool,
|
||||
danger_accept_invalid_cert: Option<bool>,
|
||||
original_danger_accept_invalid_cert: Option<bool>,
|
||||
) -> AsyncClient {
|
||||
let mut client =
|
||||
create_http_client_async(tls_type, danger_accept_invalid_cert.unwrap_or(false));
|
||||
if is_tls_type_cached && original_danger_accept_invalid_cert.is_some() {
|
||||
return client;
|
||||
}
|
||||
if let Err(e) = client.head(url).send().await {
|
||||
match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
|
||||
(TlsType::Rustls, _, None) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with rustls-tls: {:?}, trying accept invalid cert",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_async_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
Some(true),
|
||||
original_danger_accept_invalid_cert,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
(TlsType::Rustls, false, Some(_)) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with rustls-tls: {:?}, trying native-tls",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_async_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
TlsType::NativeTls,
|
||||
is_tls_type_cached,
|
||||
original_danger_accept_invalid_cert,
|
||||
original_danger_accept_invalid_cert,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
(TlsType::NativeTls, _, None) => {
|
||||
log::warn!(
|
||||
"Failed to connect to server {} with native-tls: {:?}, trying accept invalid cert",
|
||||
tls_url,
|
||||
e
|
||||
);
|
||||
client = create_http_client_async_with_url_(
|
||||
url,
|
||||
tls_url,
|
||||
tls_type,
|
||||
is_tls_type_cached,
|
||||
Some(true),
|
||||
original_danger_accept_invalid_cert,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
_ => {
|
||||
log::error!(
|
||||
"Failed to connect to server {} with {:?}, err: {:?}.",
|
||||
tls_url,
|
||||
tls_type,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::info!(
|
||||
"Successfully connected to server {} with {:?}",
|
||||
tls_url,
|
||||
tls_type
|
||||
);
|
||||
upsert_tls_cache(
|
||||
tls_url,
|
||||
tls_type,
|
||||
danger_accept_invalid_cert.unwrap_or(false),
|
||||
);
|
||||
}
|
||||
client
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user