From 114cc5132b7985bc8df9be29b135fac749cf08d0 Mon Sep 17 00:00:00 2001 From: Bluemangoo Date: Wed, 4 Nov 2026 19:12:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=8B=E7=BC=A9=E4=BA=86rust=E7=9A=84?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core_vpn/Cargo.lock | 389 +------------------------------------------ core_vpn/Cargo.toml | 10 +- core_vpn/src/mitm.rs | 54 +++--- 3 files changed, 35 insertions(+), 418 deletions(-) diff --git a/core_vpn/Cargo.lock b/core_vpn/Cargo.lock index b752f76..907d906 100644 --- a/core_vpn/Cargo.lock +++ b/core_vpn/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.119", - "synstructure 0.13.2", + "synstructure", ] [[package]] @@ -105,29 +105,6 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" -[[package]] -name = "aws-lc-rs" -version = "1.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", - "pkg-config", -] - [[package]] name = "base64" version = "0.23.1" @@ -181,8 +158,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -209,15 +184,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - [[package]] name = "combine" version = "4.6.9" @@ -284,8 +250,6 @@ dependencies = [ "tokio-rustls", "tokio-util", "tun-rs", - "url", - "webpki-roots", ] [[package]] @@ -340,12 +304,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "encoding_rs" version = "0.8.42" @@ -360,16 +318,6 @@ dependencies = [ "simdutf8", ] -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - [[package]] name = "etherparse" version = "0.20.3" @@ -426,21 +374,6 @@ dependencies = [ "spin", ] -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures-channel" version = "0.3.34" @@ -608,110 +541,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "icu_collections" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe090a42a0d3140fed8c63263ed1fecc02422cb2f4bfe55cd8de2de1b8e105dd" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d29b57c17c6528d0dc4c2141cfa2d08200465acb537a3909c8b9b8a4a984c0" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404a3b8c486f205c87fe7f23ab6894d84a4ad76d6e4671ae1981ba7def87c599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f0088bfb7441f7a37fa0c9e20cb1e9cba1cac6b9ce8cd2a6dc44294f8e8cbc" - -[[package]] -name = "icu_properties" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ea83d991c56158f7cf898bf86436c1dfe7c07ee82fe88951f2695c9f37a379f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98f29af82d02b163fe50161388350e743bb3107cc8e8c2f7314cb505faddfcf" - -[[package]] -name = "icu_provider" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413099315636c588ee8f011190b329b971a09a8fae9d157e01dcae8379468514" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - [[package]] name = "ipnet" version = "2.12.2" @@ -788,16 +617,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "jobserver" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" -dependencies = [ - "getrandom 0.4.3", - "libc", -] - [[package]] name = "js-sys" version = "0.3.106" @@ -830,12 +649,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "litemap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" - [[package]] name = "lock_api" version = "0.4.14" @@ -1058,29 +871,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link 0.2.1", -] - [[package]] name = "paste" version = "1.0.15" @@ -1120,21 +910,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "pkg-config" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" - -[[package]] -name = "potential_utf" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" -dependencies = [ - "zerovec", -] - [[package]] name = "powerfmt" version = "0.2.1" @@ -1211,15 +986,6 @@ dependencies = [ "yasna", ] -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.13.1" @@ -1301,9 +1067,8 @@ version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ - "aws-lc-rs", - "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1346,7 +1111,6 @@ version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1460,16 +1224,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - [[package]] name = "simd_cesu8" version = "1.2.0" @@ -1511,12 +1265,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "subtle" version = "2.6.1" @@ -1556,17 +1304,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "synstructure" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - [[package]] name = "system-configuration-sys" version = "0.6.0" @@ -1627,16 +1364,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc840c238154d58f9e86b2792261edfde565a17696e1cda1a449de27979801a" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tokio" version = "1.54.1" @@ -1646,9 +1373,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.61.2", @@ -1756,24 +1481,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "version_check" version = "0.9.5" @@ -1859,15 +1566,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "webpki-roots" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f280bbb2b287bc8e7de7e3852945a0ff50d1bbcb5ed42b6c7a568c546df171" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "widestring" version = "1.2.1" @@ -2098,12 +1796,6 @@ version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "writeable" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" - [[package]] name = "x509-parser" version = "0.18.1" @@ -2132,29 +1824,6 @@ dependencies = [ "time", ] -[[package]] -name = "yoke" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", - "synstructure 0.14.0", -] - [[package]] name = "zerocopy" version = "0.8.63" @@ -2175,66 +1844,12 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "zerofrom" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", - "synstructure 0.14.0", -] - [[package]] name = "zeroize" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" -[[package]] -name = "zerotrie" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58a2799cfe9a1670c7ea8edbd52ef8edb93cb37a7f83bf31ba9e35d9dae6a40" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3743ddbf47738d929cd1ae2e199d40d0162979dfe31aef8ae646d2bf00bf97a" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - [[package]] name = "zmij" version = "1.0.23" diff --git a/core_vpn/Cargo.toml b/core_vpn/Cargo.toml index 58c5560..41dda66 100644 --- a/core_vpn/Cargo.toml +++ b/core_vpn/Cargo.toml @@ -9,17 +9,16 @@ crate-type = ["cdylib"] [dependencies] ipstack = "1.0.1" tun-rs = { version = "2.8.13", features = ["async_tokio"] } -tokio = { version = "1.47.5", features = ["full"] } -tokio-rustls = "0.26" +tokio = { version = "1.47.5", features = ["rt-multi-thread", "net", "time", "macros", "sync", "fs"] } rustls-pemfile = "2" jni = "0.22.4" -rcgen = { version = "0.14", features = ["x509-parser"] } +rcgen = { version = "0.14", features = ["x509-parser", "ring"] } anyhow = "1" bytes = "1" tokio-util = "0.7.20" -rustls = "0.23.46" +rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] } rustls-native-certs = "0.8.5" -webpki-roots = "1" regex = "1.13.1" hyper = { version = "1.0", features = ["server", "client", "http1"] } hyper-util = { version = "0.1", features = ["tokio", "server", "client"] } @@ -28,7 +27,6 @@ http = "1.5.0" qstring = "0.7.2" serde = { version = "1", features = ["derive"] } serde_json = "1" -url = "2" base64 = "0.23.1" [build-dependencies] diff --git a/core_vpn/src/mitm.rs b/core_vpn/src/mitm.rs index a39fe9c..fdc8504 100644 --- a/core_vpn/src/mitm.rs +++ b/core_vpn/src/mitm.rs @@ -14,6 +14,7 @@ use std::net::SocketAddr; use std::os::fd::RawFd; use std::sync::{Arc, Mutex as StdMutex, OnceLock}; use std::time::Duration; +use anyhow::{anyhow, bail}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio::net::UdpSocket; use tokio::task::JoinSet; @@ -53,9 +54,6 @@ fn root_store() -> Arc { load_system_ca_dirs(&mut root_store); - if root_store.is_empty() { - root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); - } Arc::new(root_store) }) .clone() @@ -429,29 +427,35 @@ impl ProxyConfig { if raw.is_empty() { return Ok(None); } - let url = url::Url::parse(raw) - .map_err(|e| anyhow::anyhow!("代理地址不是合法 URL: {raw} ({e})"))?; - let tls = match url.scheme() { + let uri: Uri = raw + .parse() + .map_err(|e| anyhow!("代理地址不是合法 URL: {raw} ({e})"))?; + + let scheme = uri.scheme_str().unwrap_or(""); + let tls = match scheme { "http" => false, "https" => true, - other => anyhow::bail!("代理只支持 http/https,当前是 {other}://"), + other => bail!("代理只支持 http/https,当前是 {other}://"), }; - let host = url - .host_str() - .filter(|h| !h.is_empty()) - .ok_or_else(|| anyhow::anyhow!("代理地址缺少 host: {raw}"))? + + let host = uri + .host() + .filter(|h: &&str| !h.is_empty()) + .ok_or_else(|| anyhow!("代理地址缺少 host: {raw}"))? .to_string(); - let port = url - .port_or_known_default() - .ok_or_else(|| anyhow::anyhow!("代理地址缺少端口: {raw}"))?; - let auth = if url.username().is_empty() { - None - } else { - let pass = url.password().unwrap_or(""); - Some(base64_encode( - format!("{}:{}", url.username(), pass).as_bytes(), - )) - }; + + let port = uri.port_u16().unwrap_or(if tls { 443 } else { 80 }); + + // 提取 userInfo: [username]:[password] + let auth = uri.authority().and_then(|auth| { + let userinfo = auth.as_str().split('@').next()?; + // 只有确实存在 userinfo 时(即有 '@' 符号)才提取认证信息 + if auth.as_str().contains('@') && !userinfo.is_empty() { + Some(base64_encode(userinfo.as_bytes())) + } else { + None + } + }); Ok(Some(Self { tls, host, @@ -539,14 +543,14 @@ async fn connect_via_proxy( loop { let n = io.read(&mut byte).await?; if n == 0 { - anyhow::bail!("代理在 CONNECT 阶段直接断开"); + bail!("代理在 CONNECT 阶段直接断开"); } head.push(byte[0]); if head.ends_with(b"\r\n\r\n") { break; } if head.len() > 16 * 1024 { - anyhow::bail!("代理 CONNECT 响应头过长"); + bail!("代理 CONNECT 响应头过长"); } } let head_str = String::from_utf8_lossy(&head); @@ -557,7 +561,7 @@ async fn connect_via_proxy( .map(|code| code == "200") .unwrap_or(false); if !ok { - anyhow::bail!("代理 CONNECT 失败: {status_line}"); + bail!("代理 CONNECT 失败: {status_line}"); } Ok(io) }