From 5d049b7e5c162453984aa615405f1aa77502ddb5 Mon Sep 17 00:00:00 2001 From: dev0 Date: Mon, 18 Sep 2023 21:06:07 +1000 Subject: [PATCH] add boringtun --- Cargo.lock | 156 +++++++++++++++++++++++++++++- clash_lib/Cargo.toml | 3 + clash_lib/src/app/dns/resolver.rs | 2 +- clash_lib/src/proxy/mod.rs | 2 + clash_lib/src/proxy/wg/mod.rs | 94 ++++++++++++++++++ 5 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 clash_lib/src/proxy/wg/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1843ba0dd..e3ffeef44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "blake3" version = "1.4.1" @@ -491,6 +500,32 @@ dependencies = [ "fslock", ] +[[package]] +name = "boringtun" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "751787b019c674b9ac353f4eaa285e6711c21badb421cd8c199bf2c83b727f29" +dependencies = [ + "aead 0.5.2", + "base64 0.13.1", + "blake2", + "chacha20poly1305 0.10.1", + "hex", + "hmac", + "ip_network", + "ip_network_table", + "libc", + "nix", + "parking_lot", + "rand_core", + "ring", + "socket2 0.4.9", + "thiserror", + "tracing", + "untrusted 0.9.0", + "x25519-dalek", +] + [[package]] name = "brotli" version = "3.3.4" @@ -797,6 +832,7 @@ dependencies = [ "base64 0.21.2", "boring", "boring-sys", + "boringtun", "brotli", "byteorder", "bytes", @@ -1168,6 +1204,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "data-encoding" version = "2.4.0" @@ -1403,6 +1466,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + [[package]] name = "filetime" version = "0.2.21" @@ -2005,6 +2074,22 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c429fffa658f288669529fc26565f728489a2e39bc7b24a428aaaf51355182e" +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ip_network_table" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" +dependencies = [ + "ip_network", + "ip_network_table-deps-treebitmap", +] + [[package]] name = "ip_network_table-deps-treebitmap" version = "0.5.0" @@ -2409,6 +2494,18 @@ dependencies = [ "smallvec", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -2736,6 +2833,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + [[package]] name = "plotters" version = "0.3.5" @@ -3093,7 +3196,7 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -3127,6 +3230,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.4" @@ -3168,7 +3280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -3220,7 +3332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -3258,6 +3370,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "sendfd" version = "0.4.3" @@ -4368,6 +4486,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -4818,8 +4942,34 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7fae07da688e17059d5886712c933bb0520f15eff2e09cfa18e30968f4e63a" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + [[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] diff --git a/clash_lib/Cargo.toml b/clash_lib/Cargo.toml index 79eef4c6d..8be8cbe7e 100644 --- a/clash_lib/Cargo.toml +++ b/clash_lib/Cargo.toml @@ -58,8 +58,11 @@ filetime = "0.2" axum = { version = "0.6.20", features = ["ws"] } tower-http = { version = "0.4.0", features = ["fs", "trace", "cors"] } chrono = { version = "0.4.26", features = ["serde"] } + tun = { git = "https://github.com/Watfaq/rust-tun.git", rev = "5c0702b", features = ["async"] } netstack-lwip = { git = "https://github.com/Watfaq/netstack-lwip.git", rev = "8c8c0b0" } +boringtun = { version = "0.6.0", features = ["device"] } + serde = { version = "1.0", features=["derive"] } diff --git a/clash_lib/src/app/dns/resolver.rs b/clash_lib/src/app/dns/resolver.rs index 464b54c1d..66d14c148 100644 --- a/clash_lib/src/app/dns/resolver.rs +++ b/clash_lib/src/app/dns/resolver.rs @@ -195,7 +195,7 @@ impl Resolver { async move { c.exchange(message) .inspect_err(|x| { - warn!("DNS client {} resolve error: {}", c.id(), x.to_string()) + debug!("DNS client {} resolve error: {}", c.id(), x.to_string()) }) .await } diff --git a/clash_lib/src/proxy/mod.rs b/clash_lib/src/proxy/mod.rs index 0a8a0a72e..7e10e2d95 100644 --- a/clash_lib/src/proxy/mod.rs +++ b/clash_lib/src/proxy/mod.rs @@ -32,6 +32,7 @@ pub mod trojan; pub mod tun; pub mod utils; pub mod vmess; +//pub mod wg; pub mod converters; @@ -129,6 +130,7 @@ pub enum OutboundType { Shadowsocks, Vmess, Trojan, + WireGuard, #[serde(rename = "URLTest")] UrlTest, diff --git a/clash_lib/src/proxy/wg/mod.rs b/clash_lib/src/proxy/wg/mod.rs new file mode 100644 index 000000000..fc88d1bfc --- /dev/null +++ b/clash_lib/src/proxy/wg/mod.rs @@ -0,0 +1,94 @@ +use std::{ + io, + net::{Ipv4Addr, Ipv6Addr}, + sync::Arc, +}; + +use crate::{ + app::{dispatcher::BoxedChainedStream, dns::ThreadSafeDNSResolver}, + session::{Session, SocksAddr}, +}; + +use super::{ + AnyOutboundDatagram, AnyOutboundHandler, AnyStream, CommonOption, OutboundHandler, OutboundType, +}; + +use async_trait::async_trait; +pub use netstack_lwip as netstack; + +pub struct Opts { + pub name: String, + pub common_opts: CommonOption, + pub server: String, + pub port: u16, + pub ip: Ipv4Addr, + pub ipv6: Option, + pub private_key: String, + pub public_key: String, + pub preshared_key: Option, + pub remote_dns_resolve: bool, + pub dns: Option>, + pub mtu: Option, + pub udp: bool, +} + +pub struct Handler { + opts: Opts, + + device: boringtun::device::Device, +} + +impl Handler { + pub fn new(opts: Opts) -> AnyOutboundHandler { + let device_cfg = boringtun::device::DeviceConfig::default(); + let device = boringtun::device::Device::new("utun", device_cfg).unwrap(); + Arc::new(Self { opts, device }) + } +} + +#[async_trait] +impl OutboundHandler for Handler { + fn name(&self) -> &str { + &self.opts.name + } + + fn proto(&self) -> OutboundType { + OutboundType::WireGuard + } + + async fn remote_addr(&self) -> Option { + None + } + + async fn support_udp(&self) -> bool { + self.opts.udp + } + + /// connect to remote target via TCP + async fn connect_stream( + &self, + sess: &Session, + resolver: ThreadSafeDNSResolver, + ) -> io::Result { + todo!() + } + + /// wraps a stream with outbound handler + async fn proxy_stream( + &self, + s: AnyStream, + sess: &Session, + resolver: ThreadSafeDNSResolver, + ) -> io::Result { + todo!() + } + + /// connect to remote target via UDP + async fn connect_datagram( + &self, + sess: &Session, + resolver: ThreadSafeDNSResolver, + ) -> io::Result { + todo!() + } +}