From 823e1dfef3251e6ee4c150ad9c7beefc49e518e8 Mon Sep 17 00:00:00 2001 From: eauxxs Date: Fri, 24 Nov 2023 19:05:18 +0800 Subject: [PATCH 1/2] support socks5 proxy --- Cargo.toml | 3 ++ src/main.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90fa920..f208d78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,9 @@ log = "0.4" stun = "0.4" tokio = "1.27" pretty_env_logger = "0.5" +fast-socks5 = "0.9.1" +async-trait = "0.1.74" +webrtc-util = "0.7.0" [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index feaae8f..f8f9d3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +use async_trait::async_trait; +use fast_socks5::client::Socks5Datagram; +use fast_socks5::util::target_addr::TargetAddr; use log::info; use stun::addr::*; use stun::agent::*; @@ -7,8 +10,11 @@ use stun::xoraddr::*; use stun::Error; use clap::{arg, command, Arg, ArgAction}; +use std::net::SocketAddr; use std::sync::Arc; -use tokio::net::{lookup_host, UdpSocket}; +use tokio::net::lookup_host; +use tokio::net::TcpStream; +use tokio::net::UdpSocket; #[tokio::main] async fn main() -> Result<(), Error> { @@ -28,6 +34,13 @@ async fn main() -> Result<(), Error> { .help("Do not use IPv6 addresses when connecting to STUN server") .action(ArgAction::SetTrue), ) + .arg( + Arg::new("host:port") + .long("socks5") + .short('s') + .required(false) + .help("Use SOCKS5 udp proxy"), + ) .get_matches(); let (handler_tx, mut handler_rx) = tokio::sync::mpsc::unbounded_channel(); @@ -52,16 +65,26 @@ async fn main() -> Result<(), Error> { info!("Server address is: {}", addr); - let conn = UdpSocket::bind(if addr.is_ipv4() { - "0.0.0.0:0" - } else { - "[::]:0" - }) - .await?; + let mut client = if let Some(proxy) = matches.get_one::("socks5") { + println!("Using SOCKS5 proxy: {}", proxy); + let backing_socket = TcpStream::connect(proxy).await?; + let u = fast_socks5::client::Socks5Datagram::bind(backing_socket, "0.0.0.0:0") + .await + .map_err(|e| Error::Other(e.to_string()))?; - conn.connect(addr).await?; + let conn = Arc::new(Socks5Udp(u, TargetAddr::Ip(addr))); + ClientBuilder::new().with_conn(conn).build()? + } else { + let conn = UdpSocket::bind(if addr.is_ipv4() { + "0.0.0.0:0" + } else { + "[::]:0" + }) + .await?; - let mut client = ClientBuilder::new().with_conn(Arc::new(conn)).build()?; + conn.connect(addr).await?; + ClientBuilder::new().with_conn(Arc::new(conn)).build()? + }; let mut msg = Message::new(); msg.build(&[Box::::default(), Box::new(BINDING_REQUEST)])?; @@ -86,3 +109,50 @@ async fn main() -> Result<(), Error> { Ok(()) } + +struct Socks5Udp(Socks5Datagram, TargetAddr); +use webrtc_util::Result as WResult; +#[async_trait] +impl webrtc_util::Conn for Socks5Udp { + async fn connect(&self, _addr: SocketAddr) -> WResult<()> { + unimplemented!() + } + async fn recv(&self, buf: &mut [u8]) -> WResult { + let r = self.0.recv_from(buf).await; + match r { + Ok((n, _)) => WResult::Ok(n), + Err(e) => Err(webrtc_util::Error::Other(e.to_string())), + } + } + async fn recv_from(&self, _buf: &mut [u8]) -> WResult<(usize, SocketAddr)> { + unimplemented!() + } + async fn send(&self, buf: &[u8]) -> WResult { + let r = match self.1 { + TargetAddr::Ip(addr) => self.0.send_to(buf, addr).await, + TargetAddr::Domain(ref domain, port) => { + self.0.send_to(buf, (domain.as_ref(), port)).await + } + }; + match r { + Ok(n) => WResult::Ok(n), + Err(e) => Err(webrtc_util::Error::Other(e.to_string())), + } + } + async fn send_to(&self, buf: &[u8], target: SocketAddr) -> WResult { + let r = self.0.send_to(buf, target).await; + match r { + Ok(n) => WResult::Ok(n), + Err(e) => Err(webrtc_util::Error::Other(e.to_string())), + } + } + async fn close(&self) -> WResult<()> { + Ok(()) + } + fn local_addr(&self) -> WResult { + unimplemented!() + } + fn remote_addr(&self) -> Option { + unimplemented!() + } +} From 7b41ff1807f12d898903b75f29b122e1ffb5d99c Mon Sep 17 00:00:00 2001 From: eauxxs Date: Fri, 24 Nov 2023 21:01:51 +0800 Subject: [PATCH 2/2] fix clap --- src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index f8f9d3e..d7bb208 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,11 +35,11 @@ async fn main() -> Result<(), Error> { .action(ArgAction::SetTrue), ) .arg( - Arg::new("host:port") + Arg::new("socks5") .long("socks5") .short('s') .required(false) - .help("Use SOCKS5 udp proxy"), + .help("Use SOCKS5 udp proxy "), ) .get_matches(); @@ -66,7 +66,6 @@ async fn main() -> Result<(), Error> { info!("Server address is: {}", addr); let mut client = if let Some(proxy) = matches.get_one::("socks5") { - println!("Using SOCKS5 proxy: {}", proxy); let backing_socket = TcpStream::connect(proxy).await?; let u = fast_socks5::client::Socks5Datagram::bind(backing_socket, "0.0.0.0:0") .await