diff --git a/Cargo.lock b/Cargo.lock index cfacc98..531a259 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1589,6 +1589,7 @@ dependencies = [ "env_logger", "frida_client", "frida_core", + "frida_server", "log", "serde", "serde_derive", @@ -1676,6 +1677,16 @@ dependencies = [ [[package]] name = "frida_server" version = "0.2.0" +dependencies = [ + "aes-gcm", + "base64 0.22.1", + "env_logger", + "frida_core", + "log", + "tokio", + "tokio-util", + "x25519-dalek", +] [[package]] name = "futures" diff --git a/frida_cli/Cargo.toml b/frida_cli/Cargo.toml index 3a84d31..fe0c83e 100644 --- a/frida_cli/Cargo.toml +++ b/frida_cli/Cargo.toml @@ -19,4 +19,5 @@ serde_yaml = "0.9.34" tokio = { version = "1", features = ["full", "signal", "tracing"] } tokio-util = "0.7.12" frida_core = { path = "../frida_core" } -frida_client = { path = "../frida_client" } \ No newline at end of file +frida_client = { path = "../frida_client" } +frida_server = { path = "../frida_server" } \ No newline at end of file diff --git a/frida_cli/src/main.rs b/frida_cli/src/main.rs index 356971d..b9d2633 100644 --- a/frida_cli/src/main.rs +++ b/frida_cli/src/main.rs @@ -56,7 +56,7 @@ fn generate_peer_config(matches: &ArgMatches, config_path: &str, cfg_raw: &Strin async fn init_server(cfg_raw: &str, s_interface: Option<&str>) { let config: ServerConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad server config file structure"); - //server::server_mode(config, s_interface).await; + frida_server::server::server_mode(config, s_interface).await; } async fn init_client(cfg_raw: &str) { diff --git a/frida_server/Cargo.toml b/frida_server/Cargo.toml index 634b3ad..80d64e2 100644 --- a/frida_server/Cargo.toml +++ b/frida_server/Cargo.toml @@ -7,6 +7,16 @@ authors = ["alterwain"] keywords = ["tun", "network", "tunnel", "vpn"] categories = ["network-programming", "asynchronous"] readme = "../README.md" -workspace = "../" + +[lib] +crate-type = ["staticlib", "cdylib", "lib"] [dependencies] +frida_core = { path = "../frida_core", package = "frida_core" } +aes-gcm = "0.10.3" +x25519-dalek = { version = "2.0.1", features = ["getrandom", "static_secrets"] } +base64 = "0.22.1" +tokio = { version = "1", features = ["full", "signal", "tracing"] } +tokio-util = "0.7.12" +env_logger = "0.9" +log = "0.4.20" \ No newline at end of file diff --git a/frida_server/src/lib.rs b/frida_server/src/lib.rs new file mode 100644 index 0000000..74f47ad --- /dev/null +++ b/frida_server/src/lib.rs @@ -0,0 +1 @@ +pub mod server; diff --git a/frida_server/src/main.rs b/frida_server/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/frida_server/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/frida_server/src/server.rs b/frida_server/src/server.rs index af346e8..a35f577 100644 --- a/frida_server/src/server.rs +++ b/frida_server/src/server.rs @@ -1,4 +1,3 @@ -use futures::{SinkExt, StreamExt}; use tokio::sync::mpsc; use tokio::{net::UdpSocket, sync::Mutex, time}; use x25519_dalek::{PublicKey, StaticSecret}; @@ -9,13 +8,13 @@ use std::net::{ SocketAddr, Ipv4Addr, IpAddr }; use std::collections::HashMap; use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Nonce }; -use tun::{Configuration, create_as_async}; #[cfg(target_os = "linux")] use network_interface::{NetworkInterface, NetworkInterfaceConfig}; -use crate::config::{ ServerConfiguration, ServerPeer}; -use crate::udp::{UDPKeepAlive, UDPSerializable, UDPVpnHandshake, UDPVpnPacket}; +use frida_core::config::{ ServerConfiguration, ServerPeer}; +use frida_core::udp::{UDPKeepAlive, UDPSerializable, UDPVpnHandshake, UDPVpnPacket}; +use frida_core::{DeviceReader, DeviceWriter, create, device::AbstractDevice}; #[cfg(target_os = "linux")] fn configure_routes(s_interface: Option<&str>) { @@ -85,15 +84,13 @@ fn configure_routes(s_interface: Option<&str>) { pub async fn server_mode(server_config: ServerConfiguration, s_interface: Option<&str>) { info!("Starting server..."); - - let mut config = Configuration::default(); - config.address(&server_config.interface.internal_address) - .netmask("255.255.255.0") - .tun_name("tun0") - .up(); - let dev = create_as_async(&config).unwrap(); - let (mut dev_writer, mut dev_reader) = dev.into_framed().split(); + let mut config = AbstractDevice::default(); + config.address(server_config.interface.internal_address.parse().unwrap()) + .netmask(Ipv4Addr::new(255, 255, 255, 0)) // 255.255.255.0 + .tun_name("tun0"); + + let (mut dev_reader, mut dev_writer) = create(config); let sock = UdpSocket::bind(&server_config.interface.bind_address).await.unwrap(); let sock_rec = Arc::new(sock); @@ -112,7 +109,7 @@ pub async fn server_mode(server_config: ServerConfiguration, s_interface: Option loop { if let Some(bytes) = recv2tun.recv().await { info!("Sent to tun!"); - let _ = dev_writer.send(bytes).await; + let _ = dev_writer.write(&bytes).await; } } }); @@ -146,28 +143,31 @@ pub async fn server_mode(server_config: ServerConfiguration, s_interface: Option let addrs_cl = addresses.clone(); let send2hnd_sr = send2hnd.clone(); let tun_reader_task = tokio::spawn(async move { - while let Some(Ok(buf)) = dev_reader.next().await { - if buf.len() <= 19 { continue; } - - let ip = IpAddr::V4(Ipv4Addr::new(buf[16], buf[17], buf[18], buf[19])); - let mp = addrs_cl.lock().await; - if let Some(peer) = mp.get(&ip) { - let aes = Aes256Gcm::new(&peer.shared_secret.into()); - let nonce = Aes256Gcm::generate_nonce(&mut OsRng); - - let ciphered_data = aes.encrypt(&nonce, &buf[..]); - - if let Ok(ciphered_d) = ciphered_data { - let vpn_packet = UDPVpnPacket{ data: ciphered_d, nonce: nonce.to_vec()}; - let _ = send2hnd_sr.send((vpn_packet.serialize(), peer.addr)); + let mut buf = vec![0u8; 4096]; + loop { + if let Ok(n) = dev_reader.read(&mut buf).await { + if n <= 19 { continue; } + + let ip = IpAddr::V4(Ipv4Addr::new(buf[16], buf[17], buf[18], buf[19])); + let mp = addrs_cl.lock().await; + if let Some(peer) = mp.get(&ip) { + let aes = Aes256Gcm::new(&peer.shared_secret.into()); + let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + + let ciphered_data = aes.encrypt(&nonce, &buf[..n]); + + if let Ok(ciphered_d) = ciphered_data { + let vpn_packet = UDPVpnPacket{ data: ciphered_d, nonce: nonce.to_vec()}; + let _ = send2hnd_sr.send((vpn_packet.serialize(), peer.addr)); + } else { + error!("Traffic encryption failed."); + } } else { - error!("Traffic encryption failed."); + // TODO: check in config is broadcast mode enabled (if not, do not send this to everyone) + //mp.values().for_each(| peer | { sock_snd.send_to(&buf[..n], peer.addr); }); } - } else { - // TODO: check in config is broadcast mode enabled (if not, do not send this to everyone) - //mp.values().for_each(| peer | { sock_snd.send_to(&buf[..n], peer.addr); }); + drop(mp); } - drop(mp); } });