From e55cf11a591b18f6d5ef45300fff714fde738820 Mon Sep 17 00:00:00 2001 From: dev0 Date: Sun, 27 Aug 2023 22:11:30 +1000 Subject: [PATCH] pending ws + vmess --- clash/tests/data/config/rules.yaml | 1 + clash_lib/src/proxy/vmess/mod.rs | 13 +- .../src/proxy/vmess/vmess_impl/tls/macos.rs | 59 -------- .../src/proxy/vmess/vmess_impl/tls/mod.rs | 12 -- .../src/proxy/vmess/vmess_impl/tls/stream.rs | 141 ------------------ .../src/proxy/vmess/vmess_impl/tls/unix.rs | 16 -- .../src/proxy/vmess/vmess_impl/tls/windows.rs | 26 ---- 7 files changed, 6 insertions(+), 262 deletions(-) delete mode 100644 clash_lib/src/proxy/vmess/vmess_impl/tls/macos.rs delete mode 100644 clash_lib/src/proxy/vmess/vmess_impl/tls/mod.rs delete mode 100644 clash_lib/src/proxy/vmess/vmess_impl/tls/stream.rs delete mode 100644 clash_lib/src/proxy/vmess/vmess_impl/tls/unix.rs delete mode 100644 clash_lib/src/proxy/vmess/vmess_impl/tls/windows.rs diff --git a/clash/tests/data/config/rules.yaml b/clash/tests/data/config/rules.yaml index 2cda134e..63041412 100644 --- a/clash/tests/data/config/rules.yaml +++ b/clash/tests/data/config/rules.yaml @@ -127,6 +127,7 @@ proxies: cipher: auto udp: true skip-cert-verify: true + network: ws ws-opts: path: /api/v3/download.getFile headers: diff --git a/clash_lib/src/proxy/vmess/mod.rs b/clash_lib/src/proxy/vmess/mod.rs index 1afb4a93..5666d336 100644 --- a/clash_lib/src/proxy/vmess/mod.rs +++ b/clash_lib/src/proxy/vmess/mod.rs @@ -77,7 +77,6 @@ impl Handler { &'a self, s: AnyStream, sess: &'a Session, - resolver: ThreadSafeDNSResolver, udp: bool, ) -> io::Result { let mut stream = s; @@ -182,7 +181,7 @@ impl OutboundHandler for Handler { resolver: ThreadSafeDNSResolver, ) -> io::Result { let stream = new_tcp_stream( - resolver.clone(), + resolver, self.opts.server.as_str(), self.opts.port, self.opts.common_opts.iface.as_ref(), @@ -198,7 +197,7 @@ impl OutboundHandler for Handler { }) .await?; - self.inner_proxy_stream(stream, sess, resolver, false).await + self.inner_proxy_stream(stream, sess, false).await } /// wraps a stream with outbound handler @@ -206,9 +205,9 @@ impl OutboundHandler for Handler { &self, s: AnyStream, sess: &Session, - resolver: ThreadSafeDNSResolver, + _: ThreadSafeDNSResolver, ) -> io::Result { - self.inner_proxy_stream(s, sess, resolver, false).await + self.inner_proxy_stream(s, sess, false).await } async fn connect_datagram( @@ -241,9 +240,7 @@ impl OutboundHandler for Handler { format!("failed to resolve {}", sess.destination.host()).as_str(), ))?; - let stream = self - .inner_proxy_stream(stream, sess, resolver, true) - .await?; + let stream = self.inner_proxy_stream(stream, sess, true).await?; Ok(Box::new(OutboundDatagramVmess::new( stream, diff --git a/clash_lib/src/proxy/vmess/vmess_impl/tls/macos.rs b/clash_lib/src/proxy/vmess/vmess_impl/tls/macos.rs deleted file mode 100644 index f2647d7f..00000000 --- a/clash_lib/src/proxy/vmess/vmess_impl/tls/macos.rs +++ /dev/null @@ -1,59 +0,0 @@ -use boring::x509::X509; -use security_framework::trust_settings::{Domain, TrustSettings, TrustSettingsForCertificate}; -use std::io; - -use std::collections::HashMap; -use std::io::{Error, ErrorKind}; - -use crate::common::errors::map_io_error; - -// Adapted from https://github.com/rustls/rustls-native-certs -pub fn load_native_certs() -> io::Result> { - // The various domains are designed to interact like this: - // - // "Per-user Trust Settings override locally administered - // Trust Settings, which in turn override the System Trust - // Settings." - // - // So we collect the certificates in this order; as a map of - // their DER encoding to what we'll do with them. We don't - // overwrite existing elements, which mean User settings - // trump Admin trump System, as desired. - - let mut all_certs = HashMap::new(); - - for domain in &[Domain::User, Domain::Admin, Domain::System] { - let ts = TrustSettings::new(*domain); - let iter = ts.iter().map_err(map_io_error)?; - - for cert in iter { - let der = cert.to_der(); - - // If there are no specific trust settings, the default - // is to trust the certificate as a root cert. Weird API but OK. - // The docs say: - // - // "Note that an empty Trust Settings array means "always trust this cert, - // with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot". - let trusted = ts - .tls_trust_settings_for_certificate(&cert) - .map_err(|err| Error::new(ErrorKind::Other, err))? - .unwrap_or(TrustSettingsForCertificate::TrustRoot); - - all_certs.entry(der).or_insert(trusted); - } - } - - let mut certs = Vec::new(); - - // Now we have all the certificates and an idea of whether - // to use them. - for (der, trusted) in all_certs.drain() { - use TrustSettingsForCertificate::*; - if let TrustRoot | TrustAsRoot = trusted { - certs.push(X509::from_der(&der).map_err(map_io_error)?); - } - } - - Ok(certs) -} diff --git a/clash_lib/src/proxy/vmess/vmess_impl/tls/mod.rs b/clash_lib/src/proxy/vmess/vmess_impl/tls/mod.rs deleted file mode 100644 index fbea1348..00000000 --- a/clash_lib/src/proxy/vmess/vmess_impl/tls/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/// from https://github.com/Qv2ray/v2ray-rust/tree/dev/src/proxy/tls - -#[cfg(target_os = "macos")] -mod macos; -mod stream; -#[cfg(all(unix, not(target_os = "macos")))] -mod unix; -#[cfg(windows)] -mod windows; -// todo: provide Mozilla's root certs as optional - -pub use stream::TlsStreamBuilder; diff --git a/clash_lib/src/proxy/vmess/vmess_impl/tls/stream.rs b/clash_lib/src/proxy/vmess/vmess_impl/tls/stream.rs deleted file mode 100644 index 063faf81..00000000 --- a/clash_lib/src/proxy/vmess/vmess_impl/tls/stream.rs +++ /dev/null @@ -1,141 +0,0 @@ -use boring::ssl::{SslConnector, SslSignatureAlgorithm}; -use boring::ssl::{SslMethod, SslVersion}; -use foreign_types_shared::ForeignTypeRef; -use std::io; - -use tokio_boring::connect; - -use crate::common::errors::new_io_error; -use crate::proxy::AnyStream; - -#[cfg(target_os = "macos")] -use super::macos as platform; -#[cfg(all(unix, not(target_os = "macos")))] -use super::unix as platform; -#[cfg(windows)] -use super::windows as platform; - -#[derive(Clone)] -pub struct TlsStreamBuilder { - connector: SslConnector, - sni: String, - verify_hostname: bool, - verify_sni: bool, -} - -impl TlsStreamBuilder { - pub fn new_from_config( - sni: String, - cert_file: &Option, - verify_hostname: bool, - verify_sni: bool, - ) -> Self { - let mut configuration = SslConnector::builder(SslMethod::tls()).unwrap(); - { - let certs = platform::load_native_certs().unwrap(); - let mut count = 0; - for cert in certs.into_iter() { - let err = configuration.cert_store_mut().add_cert(cert); - if err.is_ok() { - count += 1; - } - } - } - if let Some(cert_file) = cert_file { - configuration.set_ca_file(cert_file).unwrap(); - } - configuration - .set_alpn_protos(b"\x02h2\x08http/1.1") - .unwrap(); - configuration - .set_cipher_list("ALL:!aPSK:!ECDSA+SHA1:!3DES") - .unwrap(); - configuration - .set_verify_algorithm_prefs(&[ - SslSignatureAlgorithm::ECDSA_SECP256R1_SHA256, - SslSignatureAlgorithm::RSA_PSS_RSAE_SHA256, - SslSignatureAlgorithm::RSA_PKCS1_SHA256, - SslSignatureAlgorithm::ECDSA_SECP384R1_SHA384, - SslSignatureAlgorithm::RSA_PSS_RSAE_SHA384, - SslSignatureAlgorithm::RSA_PKCS1_SHA384, - SslSignatureAlgorithm::RSA_PSS_RSAE_SHA512, - SslSignatureAlgorithm::RSA_PKCS1_SHA512, - ]) - .unwrap(); - configuration - .set_min_proto_version(Some(SslVersion::TLS1_2)) - .unwrap(); - configuration.enable_signed_cert_timestamps(); - configuration.enable_ocsp_stapling(); - configuration.set_grease_enabled(true); - unsafe { - boring_sys::SSL_CTX_add_cert_compression_alg( - configuration.as_ptr(), - boring_sys::TLSEXT_cert_compression_brotli as u16, - None, - Some(decompress_ssl_cert), - ); - } - Self { - connector: configuration.build(), - sni, - verify_hostname, - verify_sni, - } - } - - pub async fn proxy_stream(&self, stream: AnyStream) -> io::Result { - let mut configuration = self.connector.configure().unwrap(); - configuration.set_use_server_name_indication(self.verify_sni); - configuration.set_verify_hostname(self.verify_hostname); - unsafe { - boring_sys::SSL_add_application_settings( - configuration.as_ptr(), - b"h2".as_ptr(), - 2, - b"\x00\x03".as_ptr(), - 2, - ); - } - let stream = connect(configuration, self.sni.as_str(), stream).await; - match stream { - Ok(stream) => Ok(Box::new(stream)), - Err(e) => { - let res = e.to_string(); - Err(new_io_error(&res)) - } - } - } -} - -extern "C" fn decompress_ssl_cert( - _ssl: *mut boring_sys::SSL, - out: *mut *mut boring_sys::CRYPTO_BUFFER, - mut uncompressed_len: usize, - in_: *const u8, - in_len: usize, -) -> libc::c_int { - unsafe { - let mut buf: *mut u8 = std::ptr::null_mut(); - let x: *mut *mut u8 = &mut buf; - let allocated_buffer = boring_sys::CRYPTO_BUFFER_alloc(x, uncompressed_len); - if buf.is_null() { - return 0; - } - let uncompressed_len_ptr: *mut usize = &mut uncompressed_len; - if brotli::ffi::decompressor::CBrotliDecoderDecompress( - in_len, - in_, - uncompressed_len_ptr, - buf, - ) as i32 - == 1 - { - *out = allocated_buffer; - 1 - } else { - boring_sys::CRYPTO_BUFFER_free(allocated_buffer); - 0 - } - } -} diff --git a/clash_lib/src/proxy/vmess/vmess_impl/tls/unix.rs b/clash_lib/src/proxy/vmess/vmess_impl/tls/unix.rs deleted file mode 100644 index 16419b49..00000000 --- a/clash_lib/src/proxy/vmess/vmess_impl/tls/unix.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::common::new_error; -use boring::x509::X509; -use std::io; - -// Adapted from https://github.com/rustls/rustls-native-certs -pub fn load_native_certs() -> io::Result> { - let likely_locations = openssl_probe::probe(); - - match likely_locations.cert_file { - Some(cert_file) => { - let pem = std::fs::read(cert_file)?; - X509::stack_from_pem(pem.as_ref()).map_err(new_error) - } - None => Ok(Vec::new()), - } -} diff --git a/clash_lib/src/proxy/vmess/vmess_impl/tls/windows.rs b/clash_lib/src/proxy/vmess/vmess_impl/tls/windows.rs deleted file mode 100644 index df8ef232..00000000 --- a/clash_lib/src/proxy/vmess/vmess_impl/tls/windows.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::common::new_error; -use boring::x509::X509; -use std::io; - -static PKIX_SERVER_AUTH: &str = "1.3.6.1.5.5.7.3.1"; - -fn usable_for_rustls(uses: schannel::cert_context::ValidUses) -> bool { - match uses { - schannel::cert_context::ValidUses::All => true, - schannel::cert_context::ValidUses::Oids(strs) => strs.iter().any(|x| x == PKIX_SERVER_AUTH), - } -} - -// Adapted from https://github.com/rustls/rustls-native-certs -pub fn load_native_certs() -> io::Result> { - let mut certs = Vec::new(); - - let current_user_store = schannel::cert_store::CertStore::open_current_user("Root")?; - - for cert in current_user_store.certs() { - if usable_for_rustls(cert.valid_uses().unwrap()) && cert.is_time_valid().unwrap() { - certs.push(X509::from_der(cert.to_der()).map_err(new_error)?); - } - } - Ok(certs) -}