diff --git a/Cargo.lock b/Cargo.lock index 1f7551c8..5cf88703 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1518,6 +1518,7 @@ dependencies = [ "timedmap", "tokio", "tokio-rustls", + "tokio-socks", "tokio-stream", "tokio-util", "tokio-websockets", @@ -6276,6 +6277,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" diff --git a/easytier/Cargo.toml b/easytier/Cargo.toml index fd06e6ef..4f484d38 100644 --- a/easytier/Cargo.toml +++ b/easytier/Cargo.toml @@ -203,6 +203,7 @@ rstest = "0.18.2" [target.'cfg(target_os = "linux")'.dev-dependencies] defguard_wireguard_rs = "0.4.2" +tokio-socks = "0.5.2" [features] diff --git a/easytier/src/gateway/socks5.rs b/easytier/src/gateway/socks5.rs index c32c545e..ce4c7dce 100644 --- a/easytier/src/gateway/socks5.rs +++ b/easytier/src/gateway/socks5.rs @@ -302,7 +302,10 @@ impl Socks5Server { proxy_url.port().unwrap() ); - let listener = TcpListener::bind(bind_addr.parse::().unwrap()).await?; + let listener = { + let _g = self.global_ctx.net_ns.guard(); + TcpListener::bind(bind_addr.parse::().unwrap()).await? + }; self.peer_manager .add_packet_process_pipeline(Box::new(self.clone())) diff --git a/easytier/src/tests/three_node.rs b/easytier/src/tests/three_node.rs index e796239d..46d24b19 100644 --- a/easytier/src/tests/three_node.rs +++ b/easytier/src/tests/three_node.rs @@ -56,6 +56,7 @@ pub fn get_inst_config(inst_name: &str, ns: Option<&str>, ipv4: &str) -> TomlCon "ws://0.0.0.0:11011".parse().unwrap(), "wss://0.0.0.0:11012".parse().unwrap(), ]); + config.set_socks5_portal(Some("socks5://0.0.0.0:12345".parse().unwrap())); config } @@ -630,3 +631,51 @@ pub async fn wireguard_vpn_portal() { ) .await; } + +#[cfg(feature = "wireguard")] +#[tokio::test] +#[serial_test::serial] +pub async fn socks5_vpn_portal() { + use rand::Rng as _; + use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::{TcpListener, TcpStream}, + }; + use tokio_socks::tcp::socks5::Socks5Stream; + + let _insts = init_three_node("tcp").await; + + let mut buf = vec![0u8; 1024]; + rand::thread_rng().fill(&mut buf[..]); + + let buf_clone = buf.clone(); + let task = tokio::spawn(async move { + let net_ns = NetNS::new(Some("net_c".into())); + let _g = net_ns.guard(); + + let socket = TcpListener::bind("10.144.144.3:22222").await.unwrap(); + let (mut st, addr) = socket.accept().await.unwrap(); + assert_eq!(addr.ip().to_string(), "10.144.144.1".to_string()); + + let rbuf = &mut [0u8; 1024]; + st.read_exact(rbuf).await.unwrap(); + assert_eq!(rbuf, buf_clone.as_slice()); + }); + + let net_ns = NetNS::new(Some("net_a".into())); + let _g = net_ns.guard(); + + println!("connect to socks5 portal"); + let stream = TcpStream::connect("127.0.0.1:12345").await.unwrap(); + println!("connect to socks5 portal done"); + + stream.set_nodelay(true).unwrap(); + let mut conn = Socks5Stream::connect_with_socket(stream, "10.144.144.3:22222") + .await + .unwrap(); + + conn.write_all(&buf).await.unwrap(); + drop(conn); + + tokio::join!(task).0.unwrap(); +}