diff --git a/Cargo.lock b/Cargo.lock index e88cfae..9b0c452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,6 +217,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cipher" version = "0.2.5" @@ -295,7 +301,17 @@ version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" dependencies = [ - "nix", + "nix 0.28.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "ctrlc2" +version = "3.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b9bdf0b3623a4c37b654b319624bae363b94c4e27c22db8d48a61c6d74234f" +dependencies = [ + "nix 0.28.0", "windows-sys 0.52.0", ] @@ -459,6 +475,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hwaddr" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e414433a9e4338f4e87fa29d0670c883a5e73e7955c45f4a49130c0aa992c85b" +dependencies = [ + "phf", +] + [[package]] name = "inout" version = "0.1.3" @@ -474,6 +499,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "libc" version = "0.2.155" @@ -541,7 +572,19 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", "libc", ] @@ -560,6 +603,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "packet" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c136c7ad0619ed4f88894aecf66ad86c80683e7b5d707996e6a3a7e0e3916944" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "hwaddr", + "thiserror", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -583,6 +638,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -721,16 +794,19 @@ dependencies = [ "block-padding", "clap", "ctrlc", + "ctrlc2", "env_logger", "futures", "generic-array", "log", + "packet", "rand", "serde", "serde_derive", "socket2 0.4.10", "tokio", "tun", + "tun2", ] [[package]] @@ -768,6 +844,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -914,7 +996,25 @@ dependencies = [ "libc", "log", "thiserror", - "wintun", + "wintun 0.3.2", +] + +[[package]] +name = "tun2" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ff242bea1c5ceb9b6aa4918cf340a6c157e1328a2389c5353cf91049d8cf17" +dependencies = [ + "bytes", + "cfg-if", + "ipnet", + "libc", + "libloading", + "log", + "nix 0.29.0", + "thiserror", + "windows-sys 0.52.0", + "wintun 0.5.0", ] [[package]] @@ -1165,6 +1265,19 @@ dependencies = [ "windows", ] +[[package]] +name = "wintun" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b196f9328341b035820c54beebca487823e2e20a5977f284f2af2a0ee8f04400" +dependencies = [ + "c2rust-bitfields", + "libloading", + "log", + "thiserror", + "windows-sys 0.52.0", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index fa13216..4e0f6ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,6 @@ socket2 = "0.4" env_logger = "0.9" log = "0.4.20" futures = "0.3.30" +tun2 = "2.0.5" +packet = "0.1.4" +ctrlc2 = "3.5" \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 57967fd..4fae47a 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,12 +1,15 @@ -use tokio::{net::UdpSocket, sync::{mpsc, Mutex}}; -use std::{borrow::{Borrow, BorrowMut}, future::IntoFuture, io::{self, Read, Write}, net::SocketAddr, sync::Arc, thread, time}; use std::process::Command; use clap::{App, Arg}; use env_logger::Builder; +use tokio::{net::UdpSocket, sync::{mpsc, Mutex}}; +use tokio::task::JoinSet; +use std::io::{self, Read, Write}; +use std::sync::mpsc::Receiver; +use tun2::BoxError; use log::{error, info, LevelFilter}; -use tun::platform::Device; -use serde_derive::Serialize; -use serde_derive::Deserialize; +use std::sync::Arc; +use std::net::SocketAddr; +use std::collections::HashMap; fn configure_routes() { let ip_output = Command::new("ip") @@ -56,7 +59,7 @@ fn configure_routes() { pub async fn client_mode(remote_addr: &str) -> io::Result<()> { info!("Starting client..."); - let mut config = tun::Configuration::default(); + let mut config = tun2::Configuration::default(); config.address("10.8.0.2"); config.netmask("128.0.0.0"); config.destination("0.0.0.0"); @@ -68,65 +71,57 @@ pub async fn client_mode(remote_addr: &str) -> io::Result<()> { config.packet_information(true); }); - let tun_device = Arc::new(Mutex::new(tun::create(&config).unwrap())); + let dev = tun2::create(&config)?; + let (mut reader, mut writer) = dev.split(); #[cfg(target_os = "linux")] configure_routes(); - let sock = Arc::new(Mutex::new(UdpSocket::bind("0.0.0.0:59611").await?)); + let sock = UdpSocket::bind("0.0.0.0:59611").await?; + let r = Arc::new(sock); + let s = r.clone(); + let (tx, mut rx) = mpsc::channel::>(1_000); - let sock_main = sock.clone(); - let sock_main_instance = sock_main.lock().await; - sock_main_instance.connect(remote_addr).await?; + let mut set = JoinSet::new(); - let tun_device_clone = tun_device.clone(); - let sock_clone = sock.clone(); - tokio::spawn(async move { - let mut buf = [0; 1024]; - let mut tun = tun_device_clone.lock().await; - let sock = sock_clone.lock().await; + set.spawn(async move { + let mut buf = [0; 4096]; loop { - let len = match sock.recv(&mut buf).await { - Err(error) => { - error!("Problem with reading from socket: {error:?}"); - 0 - }, - Ok(l) => l, - }; - - if len <= 0 { continue; } - - info!("{:?} bytes received from socket", len); - - let len = match tun.write(&buf) { - Ok(l) => l, - Err(error) => { - error!("Problem with writing to tun: {error:?}"); - 0 + match reader.read(&mut buf) { + Ok(size) => { + let pkt = &buf[..size]; + use std::io::{Error, ErrorKind::Other}; + tx.send(pkt.to_vec()).await.unwrap(); + info!("Wrote to sock"); } - }; - - info!("{:?} bytes sent to tun", len); + Err(error) => error!("Error with reading from tun") + } + () } }); - let tun_device_clone_second = tun_device.clone(); - let mut buf = [0; 1024]; - let mut tun = tun_device_clone_second.lock().await; - loop { - let len = match tun.read(&mut buf) { - Ok(l) => l, - Err(error) => { - error!("Problem with reading from tun: {error:?}"); - 0 - }, - }; - - if len <= 0 { continue; } + set.spawn(async move { + while let Some(bytes) = rx.recv().await { + let len = s.send(&bytes).await.unwrap(); + println!("{:?} bytes sent", len); + } + }); - info!("{:?} bytes received from tun", len); - - let len = sock_main_instance.send(&buf).await?; - info!("{:?} bytes sent to socket", len); - } + set.spawn(async move { + let mut buf = [0; 1024]; + loop { + match r.recv_from(&mut buf).await { + Ok((len, addr)) => { + println!("{:?} bytes received from {:?}", len, addr); + writer.write_all(&buf[..len]); + info!("Wrote to tun"); + } + Err(error) => error!("Error with reading from sock") + }; + } + }); + + while let Some(res) = set.join_next().await {} + + Ok(()) } \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index d9919d5..6071c63 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,20 +1,19 @@ use tokio::{net::UdpSocket, sync::{mpsc, Mutex}}; use tokio::task::JoinSet; -use std::{borrow::{Borrow, BorrowMut}, future::IntoFuture, io::{self, Read, Write}, net::{SocketAddr, Ipv4Addr, IpAddr}, sync::{Arc}, thread, time}; -use std::process::Command; -use clap::{App, Arg}; -use env_logger::Builder; +use packet::{builder::Builder, icmp, ip, Packet}; +use std::io::{Read, Write}; +use std::sync::mpsc::Receiver; +use tun2::BoxError; use log::{error, info, LevelFilter}; -use tun::platform::Device; -use serde_derive::Serialize; -use serde_derive::Deserialize; -//use packet::{builder::Builder, icmp, ip, Packet}; +use std::sync::Arc; +use std::net::SocketAddr; use std::collections::HashMap; -pub async fn server_mode() { + +pub async fn server_mode() -> Result<(), BoxError> { info!("Starting server..."); - let mut config = tun::Configuration::default(); + let mut config = tun2::Configuration::default(); config.address("10.8.0.1"); config.name("tun0"); config.up(); @@ -24,78 +23,56 @@ pub async fn server_mode() { config.packet_information(true); }); - let tun_receiver = Arc::new(Mutex::new(tun::create(&config).unwrap())); - let tun_sender = tun_receiver.clone(); + let dev = tun2::create(&config)?; + let (mut reader, mut writer) = dev.split(); - let clients_inserter = Arc::new(Mutex::new(HashMap::new())); + let clients_inserter = Arc::new(Mutex::new(HashMap::<&str, UdpSocket>::new())); let clients_getter = clients_inserter.clone(); let receiver_sock = Arc::new(match UdpSocket::bind("192.168.0.5:8879".parse::().unwrap()).await { Ok(s) => s, Err(_error) => panic!("Cannot bind to address") }); - let sender_sock = receiver_sock.clone(); - - let (tx, mut rx) = mpsc::channel::<(Vec, SocketAddr)>(1_000); - let (mx, mut dx) = mpsc::channel::<(Vec, SocketAddr)>(1_000); let mut set = JoinSet::new(); - // tun 2 socket set.spawn(async move { - while let Some((bytes, addr)) = rx.recv().await { - let len = sender_sock.send_to(&bytes, &addr).await.unwrap(); - info!("{:?} bytes sent to socket", len); - } - }); - - // socket 2 tun - set.spawn(async move { - while let Some((bytes, addr)) = dx.recv().await { - let mut m = clients_inserter.lock().await; - m.insert("10.0.8.2", addr); - let mut ltun = tun_sender.lock().await; - let len = match ltun.write(&bytes) { - Ok(l) => l, - Err(error) => { - error!("Failed to write to tun!"); - 0 - } - }; - info!("{:?} bytes sent to tun", len); - } - }); - - // socket 2 tun - set.spawn(async move { - let mut buf = [0; 1024]; - while let Ok((len, addr)) = receiver_sock.recv_from(&mut buf).await { - info!("{:?} bytes received from {:?}", len, addr); - mx.send((buf[..len].to_vec(), addr)).await.unwrap(); - } - }); - - - // tun 2 socket - set.spawn(async move { - let mut buf = [0; 1024]; - let mut ltun: tokio::sync::MutexGuard = tun_receiver.lock().await; + let mut buf = [0; 4096]; loop { - let len = match ltun.read(&mut buf) { - Ok(l) => l, - Err(error) => { - error!("Problem with reading from tun: {error:?}"); - 0 - } - }; - info!("{:?} bytes received from tun", len); + let size = reader.read(&mut buf)?; + let pkt = &buf[..size]; + use std::io::{Error, ErrorKind::Other}; + //tx.send(pkt.to_vec()).map_err(|e| Error::new(Other, e))?; let m = clients_getter.lock().await; match m.get(&"10.0.8.2") { - Some(&addr) => tx.send((buf[..len].to_vec(), addr)).await.unwrap(), - None => error!("There's no client!") + Some(&ref sock) => { sock.send(&pkt).await.unwrap(); info!("Wrote to sock") }, + None => { error!("There's no client!") } + }; + drop(m); + () + } + #[allow(unreachable_code)] + Ok::<(), std::io::Error>(()) + }); + + set.spawn(async move { + let mut buf = [0; 1024]; + loop { + if let Ok((len, addr)) = receiver_sock.recv_from(&mut buf).await { + let mut m = clients_inserter.lock().await; + if !m.contains_key(&"10.0.8.2") { + let cl = UdpSocket::bind("0.0.0.0:59611").await?; + cl.connect(addr).await?; + m.insert("10.0.8.2", cl); + } + drop(m); + writer.write_all(&buf[..len])?; + info!("Wrote to tun"); } } }); while let Some(res) = set.join_next().await {} + + Ok(()) } \ No newline at end of file