diff --git a/Cargo.lock b/Cargo.lock index 3cc807b..a4dc2ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,6 +547,7 @@ dependencies = [ "generic-array", "hex", "log", + "network-interface", "packet", "rand", "serde", @@ -1047,6 +1048,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "network-interface" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433419f898328beca4f2c6c73a1b52540658d92b0a99f0269330457e0fd998d5" +dependencies = [ + "cc", + "libc", + "thiserror", + "winapi", +] + [[package]] name = "nix" version = "0.29.0" diff --git a/Cargo.toml b/Cargo.toml index de5212e..32e3ab5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,4 +32,5 @@ serde_yaml = "0.9.34" x25519-dalek = { version = "2.0.1", features = ["getrandom", "static_secrets"] } base64 = "0.22.1" chrono = "0.4.38" -console-subscriber = "0.4.0" \ No newline at end of file +console-subscriber = "0.4.0" +network-interface = "2.0.0" \ No newline at end of file diff --git a/README.md b/README.md index db3dcf5..c729f90 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Frida ![GitHub last commit](https://img.shields.io/github/last-commit/alterdekim/Frida) -![GitHub Release Date](https://img.shields.io/github/release-date/alterdekim/Frida) -![Jenkins Build](https://img.shields.io/jenkins/build) +![Jenkins Build](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.awain.net%2Fjob%2FFrida%2F) ![docs.rs](https://img.shields.io/docsrs/:crate) +![GitHub Repo stars](https://img.shields.io/github/stars/alterdekim/Frida) A lightweight VPN software, focused on scalability, traffic obfuscation and simplicity. @@ -20,7 +20,7 @@ On Linux, you can run this in a terminal (sudo required): curl --proto '=https' --tlsv1.2 -sSf https://get-frida.awain.net | sh ``` -Also you can download latest version from the releases page. +Also you can download latest version from the jenkins. ## Android / IOS @@ -32,3 +32,7 @@ There is an app for both Android and IOS devices. ### IOS links - Github: ... + +## Todo + - implement obfuscation protocols + - make an Android build \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 403537d..4bd8fe4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -6,12 +6,53 @@ use log::{error, info, warn}; use std::sync::Arc; use std::net::Ipv4Addr; use x25519_dalek::{PublicKey, StaticSecret}; +use std::process::Command; use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Nonce}; use crate::config::ClientConfiguration; use crate::udp::{UDPVpnPacket, UDPVpnHandshake, UDPSerializable}; +use network_interface::NetworkInterface; +use network_interface::NetworkInterfaceConfig; + +fn configure_routes(endpoint_ip: &str) { + let interfaces = NetworkInterface::show().unwrap(); + + let net_inter = interfaces.iter() + .filter(|i| !i.addr.iter().any(|b| b.ip().to_string() == "127.0.0.1" || b.ip().to_string() == "::1") ) + .min_by(|x, y| x.index.cmp(&y.index)) + .unwrap(); + + info!("Main network interface: {:?}", &net_inter.name); + + let mut ip_output = Command::new("ip") + .arg("-4") + .arg("route") + .arg("add") + .arg("0.0.0.0/0") + .arg("dev") + .arg("tun0") + .output() + .expect("Failed to execute ip route command."); + + if !ip_output.status.success() { + error!("Failed to forward packets: {:?}", String::from_utf8_lossy(&ip_output.stderr)); + } + + ip_output = Command::new("ip") + .arg("route") + .arg("add") + .arg(endpoint_ip.to_owned()+"/32") + .arg("dev") + .arg(&net_inter.name) + .output() + .expect("Failed to execute ip route command."); + + if !ip_output.status.success() { + error!("Failed to forward packets: {:?}", String::from_utf8_lossy(&ip_output.stderr)); + } +} pub async fn client_mode(client_config: ClientConfiguration) { info!("Starting client..."); @@ -51,6 +92,9 @@ pub async fn client_mode(client_config: ClientConfiguration) { } }); + #[cfg(target_os = "linux")] + configure_routes(client_config.server.endpoint.split(":")[0]); + let priv_key = BASE64_STANDARD.decode(client_config.client.private_key).unwrap(); let cipher_shared_clone = cipher_shared.clone(); diff --git a/src/server.rs b/src/server.rs index d0ee4be..84d1830 100644 --- a/src/server.rs +++ b/src/server.rs @@ -8,12 +8,78 @@ use log::{error, info}; use std::sync::Arc; use std::net::{ SocketAddr, Ipv4Addr, IpAddr }; use std::collections::HashMap; +use std::process::Command; use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Nonce }; +use network_interface::NetworkInterface; +use network_interface::NetworkInterfaceConfig; use crate::config::{ ServerConfiguration, ServerPeer}; use crate::udp::{UDPKeepAlive, UDPSerializable, UDPVpnHandshake, UDPVpnPacket}; +fn configure_routes() { + let interfaces = NetworkInterface::show().unwrap(); + + let net_inter = interfaces.iter() + .filter(|i| !i.addr.iter().any(|b| b.ip().to_string() == "127.0.0.1" || b.ip().to_string() == "::1") ) + .min_by(|x, y| x.index.cmp(&y.index)) + .unwrap(); + + info!("Main network interface: {:?}", net_inter.name); + + let mut ip_output = Command::new("iptables") + .arg("-A") + .arg("FORWARD") + .arg("-i") + .arg("tun0") + .arg("-o") + .arg(&net_inter.name) + .arg("-j") + .arg("ACCEPT") + .output() + .expect("Failed to execute iptables command."); + + if !ip_output.status.success() { + error!("Failed to forward packets: {:?}", String::from_utf8_lossy(&ip_output.stderr)); + } + + ip_output = Command::new("iptables") + .arg("-A") + .arg("FORWARD") + .arg("-i") + .arg(&net_inter.name) + .arg("-o") + .arg("tun0") + .arg("-m") + .arg("state") + .arg("--state") + .arg("ESTABLISHED,RELATED") + .arg("-j") + .arg("ACCEPT") + .output() + .expect("Failed to execute iptables command."); + + if !ip_output.status.success() { + error!("Failed to forward packets: {:?}", String::from_utf8_lossy(&ip_output.stderr)); + } + + ip_output = Command::new("iptables") + .arg("-t") + .arg("nat") + .arg("-A") + .arg("POSTROUTING") + .arg("-o") + .arg(&net_inter.name) + .arg("-j") + .arg("MASQUERADE") + .output() + .expect("Failed to execute iptables command."); + + if !ip_output.status.success() { + error!("Failed to forward packets: {:?}", String::from_utf8_lossy(&ip_output.stderr)); + } +} + pub async fn server_mode(server_config: ServerConfiguration) { info!("Starting server..."); @@ -36,6 +102,9 @@ pub async fn server_mode(server_config: ServerConfiguration) { let (send2hnd, mut recv2hnd) = mpsc::unbounded_channel::<(Vec, SocketAddr)>(); // unbounded::<(Vec, SocketAddr)>(); + #[cfg(target_os = "linux")] + configure_routes(); + let tun_writer_task = tokio::spawn(async move { loop { if let Some(bytes) = recv2tun.recv().await {