Skip to content

Commit

Permalink
use rustls on windows (#245)
Browse files Browse the repository at this point in the history
* use rustls on windows

* fix

* rm
  • Loading branch information
ibigbug authored Jan 1, 2024
1 parent 866cefb commit 10ee171
Show file tree
Hide file tree
Showing 174 changed files with 190 additions and 291,561 deletions.
45 changes: 45 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions clash_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ base64 = "0.21"
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }
boring = "4.2.0"
boring-sys = "4.2.0"
hyper-boring = "4.2.0"
tokio-boring = "4.2.0"

ip_network_table-deps-treebitmap = "0.5.0"
once_cell = "1.18.0"
Expand Down Expand Up @@ -114,5 +112,13 @@ tokio-test = "0.4.3"
axum-macros = "0.4.0"


[target.'cfg(target_os = "macos")'.dependencies]
[target.'cfg(macos)'.dependencies]
security-framework = "2.8.0"

[target.'cfg(windows)'.dependencies]
tokio-rustls = "0.24"
hyper-rustls = { version = "0.24", features = ["http1", "http2"] }

[target.'cfg(not(windows))'.dependencies]
hyper-boring = "4.2.0"
tokio-boring = "4.2.0"
4 changes: 2 additions & 2 deletions clash_lib/src/app/remote_content_manager/healthcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use tokio::time::Instant;
use tracing::debug;

use crate::{pm_debug, proxy::AnyOutboundHandler};
use crate::proxy::AnyOutboundHandler;

use super::ProxyManager;

Expand Down Expand Up @@ -65,7 +65,7 @@ impl HealthCheck {
loop {
tokio::select! {
_ = ticker.tick() => {
pm_debug!("healthcheck ticking: {}, lazy: {}", url, lazy);
debug!("healthcheck ticking: {}, lazy: {}", url, lazy);
let now = tokio::time::Instant::now();
let last_check = inner.read().await.last_check;
if !lazy || now.duration_since(last_check).as_secs() >= interval {
Expand Down
85 changes: 43 additions & 42 deletions clash_lib/src/app/remote_content_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,16 @@ use std::{
time::Duration,
};

use boring::ssl::{SslConnector, SslMethod};

use chrono::{DateTime, Utc};

use futures::{stream::FuturesUnordered, StreamExt};
use hyper::Request;
use hyper_boring::HttpsConnector;
use serde::Serialize;
use tokio::sync::RwLock;
use tracing::{debug, instrument};
use tracing::{debug, instrument, trace};

use crate::{
common::{
errors::{map_io_error, new_io_error},
timed_future::TimedFuture,
},
common::{errors::new_io_error, timed_future::TimedFuture},
proxy::AnyOutboundHandler,
};

Expand All @@ -34,20 +28,6 @@ pub mod healthcheck;
mod http_client;
pub mod providers;

#[macro_export]
macro_rules! pm_debug {
($($arg:tt)*) => ({
debug!(target: "proxy_manager", $($arg)*);
});
}

#[macro_export]
macro_rules! pm_warn {
($($arg:tt)*) => ({
warn!(target: "proxy_manager", $($arg)*);
});
}

#[derive(Clone, Serialize)]
pub struct DelayHistory {
time: DateTime<Utc>,
Expand All @@ -68,7 +48,10 @@ pub struct ProxyManager {
proxy_state: Arc<RwLock<HashMap<String, ProxyState>>>,
dns_resolver: ThreadSafeDNSResolver,

connector_map: Arc<RwLock<HashMap<String, HttpsConnector<LocalConnector>>>>,
#[cfg(windows)]
connector_map: Arc<RwLock<HashMap<String, hyper_rustls::HttpsConnector<LocalConnector>>>>,
#[cfg(not(windows))]
connector_map: Arc<RwLock<HashMap<String, hyper_boring::HttpsConnector<LocalConnector>>>>,
}

impl ProxyManager {
Expand Down Expand Up @@ -147,12 +130,6 @@ impl ProxyManager {
url: &str,
timeout: Option<Duration>,
) -> std::io::Result<(u16, u16)> {
pm_debug!(
"testing {} with url {}, timeout {:?}",
proxy.name(),
url,
timeout
);
let name = proxy.name().to_owned();
let name_clone = name.clone();
let default_timeout = Duration::from_secs(5);
Expand All @@ -162,17 +139,43 @@ impl ProxyManager {
let name = name_clone;
let connector = LocalConnector(proxy.clone(), dns_resolver);

let mut ssl = SslConnector::builder(SslMethod::tls()).map_err(map_io_error)?;
ssl.set_alpn_protos(b"\x02h2\x08http/1.1")
.map_err(map_io_error)?;
#[cfg(windows)]
let connector = {
use crate::common::tls::GLOBAL_ROOT_STORE;

let mut g = self.connector_map.write().await;
let connector = g
.entry(name.clone())
.or_insert(HttpsConnector::with_connector(connector, ssl).map_err(map_io_error)?);
let mut tls_config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(GLOBAL_ROOT_STORE.clone())
.with_no_client_auth();

let connector = connector.clone();
drop(g);
tls_config.key_log = Arc::new(rustls::KeyLogFile::new());

let connector = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(tls_config)
.https_or_http()
.enable_all_versions()
.wrap_connector(connector);

let mut g = self.connector_map.write().await;
let connector = g.entry(name.clone()).or_insert(connector);
connector.clone()
};
#[cfg(not(windows))]
let connector = {
use crate::common::errors::map_io_error;
use boring::ssl::{SslConnector, SslMethod};

let mut ssl = SslConnector::builder(SslMethod::tls()).map_err(map_io_error)?;
ssl.set_alpn_protos(b"\x02h2\x08http/1.1")
.map_err(map_io_error)?;

let connector = hyper_boring::HttpsConnector::with_connector(connector, ssl)
.map_err(map_io_error)?;

let mut g = self.connector_map.write().await;
let connector = g.entry(name.clone()).or_insert(connector);
connector.clone()
};

let client = hyper::Client::builder().build::<_, hyper::Body>(connector);

Expand All @@ -189,7 +192,7 @@ impl ProxyManager {
Ok((res, delay)) => match res {
Ok(res) => {
let delay = delay.as_millis().try_into().expect("delay is too large");
pm_debug!(
trace!(
"urltest for proxy {} with url {} returned response {} in {}ms",
&name,
url,
Expand All @@ -199,7 +202,7 @@ impl ProxyManager {
Ok(delay)
}
Err(e) => {
pm_debug!("urltest for proxy {} with url {} failed: {}", &name, url, e);
debug!("urltest for proxy {} with url {} failed: {}", &name, url, e);
Err(new_io_error(format!("{}: {}", url, e).as_str()))
}
},
Expand Down Expand Up @@ -245,8 +248,6 @@ impl ProxyManager {
state.delay_history.pop_front();
}

pm_debug!("{} alive: {}, delay: {:?}", name, result.is_ok(), result);

result
}
}
Expand Down
41 changes: 33 additions & 8 deletions clash_lib/src/common/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,19 @@ use std::{
task::{Context, Poll},
};

use boring::ssl::{SslConnector, SslMethod};
use futures::Future;

use hyper::{
client::connect::{Connected, Connection},
Uri,
};
use hyper_boring::HttpsConnector;
use tower::Service;

use crate::{
app::dns::ThreadSafeDNSResolver,
proxy::{utils::new_tcp_stream, AnyStream},
};

use super::errors::map_io_error;

#[derive(Clone)]
/// A LocalConnector that is generalised to connect to any url
pub struct LocalConnector(pub ThreadSafeDNSResolver);
Expand Down Expand Up @@ -68,17 +64,46 @@ impl Connection for AnyStream {
}
}

pub type HttpClient = hyper::Client<HttpsConnector<LocalConnector>>;
#[cfg(not(windows))]
pub type HttpClient = hyper::Client<hyper_boring::HttpsConnector<LocalConnector>>;
#[cfg(windows)]
pub type HttpClient = hyper::Client<hyper_rustls::HttpsConnector<LocalConnector>>;

#[cfg(not(windows))]
pub fn new_http_client(dns_resolver: ThreadSafeDNSResolver) -> std::io::Result<HttpClient> {
use super::errors::map_io_error;
use boring::ssl::{SslConnector, SslMethod};

let connector = LocalConnector(dns_resolver);

let mut ssl = SslConnector::builder(SslMethod::tls()).map_err(map_io_error)?;
ssl.set_alpn_protos(b"\x02h2\x08http/1.1")
.map_err(map_io_error)?;
#[cfg(target_os = "windows")]
ssl.set_verify(boring::ssl::SslVerifyMode::NONE); // TODO: verify certificate

let connector = HttpsConnector::with_connector(connector, ssl).map_err(map_io_error)?;
let connector =
hyper_boring::HttpsConnector::with_connector(connector, ssl).map_err(map_io_error)?;
Ok(hyper::Client::builder().build::<_, hyper::Body>(connector))
}

#[cfg(windows)]
pub fn new_http_client(dns_resolver: ThreadSafeDNSResolver) -> std::io::Result<HttpClient> {
use std::sync::Arc;

use super::tls::GLOBAL_ROOT_STORE;

let connector = LocalConnector(dns_resolver);

let mut tls_config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(GLOBAL_ROOT_STORE.clone())
.with_no_client_auth();
tls_config.key_log = Arc::new(rustls::KeyLogFile::new());

let connector = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(tls_config)
.https_or_http()
.enable_all_versions()
.wrap_connector(connector);

Ok(hyper::Client::builder().build::<_, hyper::Body>(connector))
}
Loading

0 comments on commit 10ee171

Please sign in to comment.