From 8653b8c7a98b80b9f2e23e1328a1d4f1b4973faf Mon Sep 17 00:00:00 2001 From: alterdekim Date: Thu, 22 Aug 2024 22:05:31 +0300 Subject: [PATCH] Changes to be committed: modified: src/client.rs new file: src/config.rs modified: src/main.rs new file: src/obfs.rs modified: src/server.rs deleted: src/tcp_client.rs deleted: src/tcp_server.rs new file: src/udp.rs deleted: src/veil.rs --- src/client.rs | 3 +- src/config.rs | 113 +++++++++++++++++++++++++++++ src/main.rs | 177 ++-------------------------------------------- src/obfs.rs | 0 src/server.rs | 4 +- src/tcp_client.rs | 126 --------------------------------- src/tcp_server.rs | 91 ------------------------ src/udp.rs | 42 +++++++++++ src/veil.rs | 48 ------------- 9 files changed, 167 insertions(+), 437 deletions(-) create mode 100644 src/config.rs create mode 100644 src/obfs.rs delete mode 100644 src/tcp_client.rs delete mode 100644 src/tcp_server.rs create mode 100644 src/udp.rs delete mode 100644 src/veil.rs diff --git a/src/client.rs b/src/client.rs index d543d04..a6e9ca2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -15,7 +15,8 @@ use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Key, Nonce}; -use crate::{UDPVpnHandshake, UDPVpnPacket, VpnPacket, ClientConfiguration, UDPSerializable}; +use crate::config::ClientConfiguration; +use crate::udp::{UDPVpnPacket, UDPVpnHandshake, UDPSerializable}; fn configure_routes() { let ip_output = Command::new("ip") diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..5074ca9 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,113 @@ +use std::{fs, io::{self, Error, Read}, net::{IpAddr, Ipv4Addr, SocketAddr}, str, sync::Arc, thread, time}; +use serde_derive::Serialize; +use serde_derive::Deserialize; +use std::str::FromStr; +use x25519_dalek::{StaticSecret, PublicKey}; +use rand::{rngs::StdRng, SeedableRng}; + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct ServerInterface { + pub bind_address: String, + pub internal_address: String, + pub private_key: String, + pub public_key: String, + pub broadcast_mode: bool, + pub keepalive: u8 +} + +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] +pub struct ServerPeer { + pub public_key: String, + pub ip: Ipv4Addr +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub enum ObfsProtocol { + DNSMask, + ICMPMask, + XOR +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct ObfsConfig { + protocol: ObfsProtocol +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct ServerConfiguration { + pub interface: ServerInterface, + pub peers: Vec, + pub obfs: ObfsConfig, + pub dns: DNSConfig +} + +impl ServerConfiguration { + pub fn default(bind_address: &str, internal_address: &str, broadcast_mode: bool, keepalive: u8, obfs_type: ObfsProtocol) -> Self { + let mut csprng = StdRng::from_entropy(); + let secret = StaticSecret::new(&mut csprng); + ServerConfiguration { interface: ServerInterface { + bind_address: String::from_str(bind_address).unwrap(), + internal_address: String::from_str(internal_address).unwrap(), + private_key: base64::encode(secret.as_bytes()), + public_key: base64::encode(PublicKey::from(&secret).as_bytes()), + broadcast_mode, + keepalive + }, + peers: Vec::new(), + obfs: ObfsConfig { protocol: obfs_type }, + dns: DNSConfig { enabled: false, net_name: String::from_str("fridah.vpn").unwrap(), entries: Vec::new() } + } + } +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct DNSConfig { + enabled: bool, + net_name: String, + entries: Vec +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct DNSEntry { + ip: Ipv4Addr, + subdomain: String +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct ClientInterface { + pub private_key: String, + pub public_key: String, + pub address: String +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct EndpointInterface { + pub public_key: String, + pub endpoint: String, + pub keepalive: u8 +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct ClientConfiguration { + pub client: ClientInterface, + pub server: EndpointInterface +} + +impl ClientConfiguration { + pub fn default(endpoint: &str, keepalive: u8, public_key: &str, internal_address: &str) -> Self { + let mut csprng = StdRng::from_entropy(); + let secret = StaticSecret::new(&mut csprng); + ClientConfiguration { + client: ClientInterface { + private_key: base64::encode(secret.as_bytes()), + public_key: base64::encode(PublicKey::from(&secret).as_bytes()), + address: String::from_str(internal_address).unwrap() + }, + server: EndpointInterface { + public_key: String::from_str(public_key).unwrap(), + endpoint: String::from_str(endpoint).unwrap(), + keepalive + } + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ccb2d58..040eb52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,177 +9,14 @@ use serde_derive::Deserialize; use std::str::FromStr; use x25519_dalek::{StaticSecret, PublicKey}; use rand::{rngs::StdRng, SeedableRng}; +use crate::config::{ ServerConfiguration, ClientConfiguration, ObfsConfig, ObfsProtocol, ServerPeer }; + -//mod tcp_client; -//mod tcp_server; mod server; mod client; +mod udp; +mod config; -struct VpnPacket { - data: Vec -} - -impl VpnPacket { - fn serialize(&self) -> Vec { - let len: [u8; 8] = (self.data.len() as u64).to_be_bytes(); - len.iter().cloned().chain(self.data.iter().cloned()).collect() - } - - fn deserialize_length(d: [u8; 8]) -> u64 { - u64::from_be_bytes(d) - } - - fn deserialize(d: Vec) -> Result { - Ok(VpnPacket{ data: d }) - } -} - -struct UDPVpnPacket { - nonce: Vec, // [u8; 12] - data: Vec -} - -impl UDPSerializable for UDPVpnPacket { - fn serialize(&self) -> Vec { - let h: &[u8] = &[1]; - [h, &self.nonce, &self.data[..]].concat() - } -} - -impl UDPVpnPacket { - fn deserialize(data: &Vec) -> Self { - UDPVpnPacket { nonce: data[1..=12].to_vec(), data: data[13..].to_vec() } - } -} - -struct UDPVpnHandshake { - public_key: Vec, - request_ip: Ipv4Addr // [u8; 4] -} - -impl UDPSerializable for UDPVpnHandshake { - fn serialize(&self) -> Vec { - let h: &[u8] = &[0]; - [h, &self.public_key[..], &self.request_ip.octets()].concat() - } -} - -impl UDPVpnHandshake { - fn deserialize(data: &Vec) -> Self { - UDPVpnHandshake { public_key: data[1..=32].to_vec(), request_ip: Ipv4Addr::new(data[33], data[34], data[35], data[36]) } - } -} - -trait UDPSerializable { - fn serialize(&self) -> Vec; -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct ServerInterface { - bind_address: String, - internal_address: String, - private_key: String, - public_key: String, - broadcast_mode: bool, - keepalive: u8 -} - -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct ServerPeer { - public_key: String, - ip: Ipv4Addr -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -enum ObfsProtocol { - DNSMask, - ICMPMask, - VEIL -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct ObfsConfig { - protocol: ObfsProtocol -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -pub struct ServerConfiguration { - interface: ServerInterface, - peers: Vec, - obfs: ObfsConfig, - dns: DNSConfig -} - -impl ServerConfiguration { - fn default(bind_address: &str, internal_address: &str, broadcast_mode: bool, keepalive: u8, obfs_type: ObfsProtocol) -> Self { - let mut csprng = StdRng::from_entropy(); - let secret = StaticSecret::new(&mut csprng); - ServerConfiguration { interface: ServerInterface { - bind_address: String::from_str(bind_address).unwrap(), - internal_address: String::from_str(internal_address).unwrap(), - private_key: base64::encode(secret.as_bytes()), - public_key: base64::encode(PublicKey::from(&secret).as_bytes()), - broadcast_mode, - keepalive - }, - peers: Vec::new(), - obfs: ObfsConfig { protocol: obfs_type }, - dns: DNSConfig { enabled: false, net_name: String::from_str("fridah.vpn").unwrap(), entries: Vec::new() } - } - } -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct DNSConfig { - enabled: bool, - net_name: String, - entries: Vec -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct DNSEntry { - ip: Ipv4Addr, - subdomain: String -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct ClientInterface { - private_key: String, - public_key: String, - address: String -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct EndpointInterface { - public_key: String, - endpoint: String, - keepalive: u8 -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -pub struct ClientConfiguration { - client: ClientInterface, - server: EndpointInterface -} - -impl ClientConfiguration { - fn default(endpoint: &str, keepalive: u8, public_key: &str, internal_address: &str) -> Self { - let mut csprng = StdRng::from_entropy(); - let secret = StaticSecret::new(&mut csprng); - ClientConfiguration { - client: ClientInterface { - private_key: base64::encode(secret.as_bytes()), - public_key: base64::encode(PublicKey::from(&secret).as_bytes()), - address: String::from_str(internal_address).unwrap() - }, - server: EndpointInterface { - public_key: String::from_str(public_key).unwrap(), - endpoint: String::from_str(endpoint).unwrap(), - keepalive - } - } - } -} fn generate_server_config(matches: &ArgMatches, config_path: &str) { let bind_address = matches.value_of("bind-address").expect("No bind address specified"); @@ -189,7 +26,7 @@ fn generate_server_config(matches: &ArgMatches, config_path: &str) { let obfs_type = match matches.value_of("obfs-type").expect("Obfs type should be specified") { "dns" => ObfsProtocol::DNSMask, "icmp" => ObfsProtocol::ICMPMask, - _ => ObfsProtocol::VEIL + _ => ObfsProtocol::XOR }; fs::write(config_path, serde_yaml::to_string(&ServerConfiguration::default(bind_address, internal_address, broadcast_mode, keepalive, obfs_type)).unwrap()); @@ -246,7 +83,7 @@ async fn main() { .filter(None, LevelFilter::Info) .init(); - let matches = App::new("Frida VPN") + let matches = App::new("Frida") .version("0.1.2") .author("alterwain") .about("VPN software") @@ -298,7 +135,7 @@ async fn main() { .takes_value(true)) .arg(Arg::with_name("obfs-type") .long("obfs-type") - .possible_values(&["dns", "icmp", "veil"]) + .possible_values(&["dns", "icmp", "xor"]) .takes_value(true) .value_name("OBFS") .help("Obfuscation protocol (config)")) diff --git a/src/obfs.rs b/src/obfs.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/server.rs b/src/server.rs index 4c7a1ec..1563ab9 100644 --- a/src/server.rs +++ b/src/server.rs @@ -14,7 +14,9 @@ use std::process::Command; use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Key, Nonce }; -use crate::{ ServerConfiguration, ServerPeer, UDPSerializable, UDPVpnHandshake, UDPVpnPacket }; +use crate::config::{ ServerConfiguration, ServerPeer}; + +use crate::udp::{UDPSerializable, UDPVpnHandshake, UDPVpnPacket}; pub async fn server_mode(server_config: ServerConfiguration) { info!("Starting server..."); diff --git a/src/tcp_client.rs b/src/tcp_client.rs deleted file mode 100644 index 1a54597..0000000 --- a/src/tcp_client.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crossbeam_channel::{unbounded, Receiver}; -use tokio::{io::AsyncWriteExt, net::{TcpListener, TcpSocket, TcpStream}, sync::{mpsc, Mutex}}; -use tokio::task::JoinSet; -use packet::{builder::Builder, icmp, ip, Packet}; -use std::io::{Read, Write}; -use tun2::BoxError; -use log::{error, info, LevelFilter}; -use std::sync::Arc; -use std::net::SocketAddr; -use std::collections::HashMap; -use std::process::Command; -use tokio::io::AsyncReadExt; - -use crate::VpnPacket; - -fn configure_routes() { - let ip_output = Command::new("ip") - .arg("addr") - .arg("add") - .arg("10.8.0.2/24") - .arg("dev") - .arg("tun0") - .output() - .expect("Failed to execute IP command"); - - if !ip_output.status.success() { - eprintln!("Failed to set IP: {}", String::from_utf8_lossy(&ip_output.stderr)); - return; - } - - let link_output = Command::new("ip") - .arg("link") - .arg("set") - .arg("up") - .arg("dev") - .arg("tun0") - .output() - .expect("Failed to execute IP LINK command"); - - if !link_output.status.success() { - eprintln!("Failed to set link up: {}", String::from_utf8_lossy(&link_output.stderr)); - return; - } - - let route_output = Command::new("ip") - .arg("route") - .arg("add") - .arg("0.0.0.0/0") - .arg("via") - .arg("10.8.0.1") - .arg("dev") - .arg("tun0") - .output() - .expect("Failed to execute IP ROUTE command"); - - if !route_output.status.success() { - eprintln!("Failed to set route: {}", String::from_utf8_lossy(&route_output.stderr)); - } -} - -pub async fn client_mode(remote_addr: String) { - info!("Starting client..."); - - let mut config = tun2::Configuration::default(); - config.address("10.8.0.2"); - config.netmask("128.0.0.0"); - config.destination("0.0.0.0"); - config.name("tun0"); - config.up(); - - #[cfg(target_os = "linux")] - config.platform_config(|config| { - config.packet_information(true); - }); - - let dev = tun2::create(&config).unwrap(); - let (mut dev_reader, mut dev_writer) = dev.split(); - - #[cfg(target_os = "linux")] - configure_routes(); - - let socket = TcpStream::connect(&remote_addr).await.unwrap(); - let (mut sock_reader, mut sock_writer) = socket.into_split(); - - let (tx, rx) = unbounded::>(); - let (dx, mx) = unbounded::>(); - - tokio::spawn(async move { - while let Ok(bytes) = rx.recv() { - dev_writer.write_all(&bytes).unwrap(); - } - }); - - tokio::spawn(async move { - let mut buf = vec![0; 8192]; - while let Ok(n) = dev_reader.read(&mut buf) { - dx.send(buf[..n].to_vec()).unwrap(); - } - }); - - tokio::spawn(async move { - let mut buf = vec![0; 4096]; - loop { - if let Ok(l) = sock_reader.read_u64().await { - buf = vec![0; l as usize]; - if let Ok(n) = sock_reader.read_exact(&mut buf).await { - info!("Catch from socket {:?} | {:?}", l, l as usize); - match VpnPacket::deserialize((&buf[..n]).to_vec()) { - Ok(vpn_packet) => tx.send(vpn_packet.data).unwrap(), - Err(error) => error!("Deserialization error {:?}", error), - }; - //if vpn_packet.start != &HEADER || vpn_packet.end != &TAIL { error!("Bad packet"); continue; } - } - } - } - }); - - loop { - if let Ok(bytes) = mx.recv() { - let vpn_packet = VpnPacket{ data: bytes }; - let serialized_data = vpn_packet.serialize(); - //info!("Writing to sock: {:?}", serialized_data); - sock_writer.write_all(&serialized_data).await.unwrap(); - } - } -} \ No newline at end of file diff --git a/src/tcp_server.rs b/src/tcp_server.rs deleted file mode 100644 index f9f0dd4..0000000 --- a/src/tcp_server.rs +++ /dev/null @@ -1,91 +0,0 @@ -use crossbeam_channel::{unbounded, Receiver}; -use tokio::{io::AsyncWriteExt, net::{TcpListener, TcpSocket, TcpStream}, sync::{mpsc, Mutex}}; -use tokio::task::JoinSet; -use packet::{builder::Builder, icmp, ip, AsPacket, Packet}; -use std::io::{Read, Write}; -use tun2::BoxError; -use log::{error, info, LevelFilter}; -use std::sync::Arc; -use std::net::SocketAddr; -use std::collections::HashMap; -use tokio::io::AsyncReadExt; -use std::process::Command; - -use crate::VpnPacket; - -pub async fn server_mode(bind_addr: String) { - info!("Starting server..."); - - let mut config = tun2::Configuration::default(); - config.address("10.8.0.1"); - config.netmask("255.255.255.0"); - config.tun_name("tun0"); - config.up(); - - #[cfg(target_os = "linux")] - config.platform_config(|config| { - config.packet_information(true); - }); - - let dev = tun2::create(&config).unwrap(); - let (mut dev_reader, mut dev_writer) = dev.split(); - - let (tx, rx) = unbounded::>(); - let (dx, mx) = unbounded::>(); - - tokio::spawn(async move { - while let Ok(mut bytes) = rx.recv() { - info!("Got packet"); - //info!("Source ip: {:?}", &bytes[12..=15]); - //bytes[12] = 192; - //bytes[13] = 168; - //bytes[14] = 0; - //bytes[15] = 5; - dev_writer.write_all(&bytes).unwrap(); - } - }); - - tokio::spawn(async move { - let mut buf = vec![0; 4096]; - while let Ok(n) = dev_reader.read(&mut buf) { - dx.send(buf[..n].to_vec()).unwrap(); - } - }); - - let listener = TcpListener::bind(&bind_addr).await.unwrap(); - - loop { - let (mut socket, _) = listener.accept().await.unwrap(); - let (mut sock_reader, mut sock_writer) = socket.into_split(); - let thread_tx = tx.clone(); - let thread_mx = mx.clone(); - - tokio::spawn(async move { - loop { - if let Ok(bytes) = thread_mx.recv() { - let vpn_packet = VpnPacket{ data: bytes }; - let serialized_data = vpn_packet.serialize(); - sock_writer.write_all(&serialized_data).await.unwrap(); - //info!("Wrote to sock: {:?}", serialized_data); - } - } - }); - - tokio::spawn(async move { - let mut buf = vec![0; 8192]; - loop { - if let Ok(l) = sock_reader.read_u64().await { - buf = vec![0; l as usize]; - if let Ok(n) = sock_reader.read_exact(&mut buf).await { - //info!("Catched from sock: {:?}", &buf[..n]); - match VpnPacket::deserialize((&buf[..n]).to_vec()) { - Ok(vpn_packet) => thread_tx.send(vpn_packet.data).unwrap(), - Err(error) => error!("Deserializing error {:?}", error), - }; - //if vpn_packet.start != &HEADER || vpn_packet.end != &TAIL { error!("Bad packet"); continue; } - } - } - } - }); - } -} \ No newline at end of file diff --git a/src/udp.rs b/src/udp.rs new file mode 100644 index 0000000..663817d --- /dev/null +++ b/src/udp.rs @@ -0,0 +1,42 @@ + +use std::net::Ipv4Addr; + +pub struct UDPVpnPacket { + pub nonce: Vec, // [u8; 12] + pub data: Vec +} + +impl UDPSerializable for UDPVpnPacket { + fn serialize(&self) -> Vec { + let h: &[u8] = &[1]; + [h, &self.nonce, &self.data[..]].concat() + } +} + +impl UDPVpnPacket { + pub fn deserialize(data: &Vec) -> Self { + UDPVpnPacket { nonce: data[1..=12].to_vec(), data: data[13..].to_vec() } + } +} + +pub struct UDPVpnHandshake { + pub public_key: Vec, + pub request_ip: Ipv4Addr // [u8; 4] +} + +impl UDPSerializable for UDPVpnHandshake { + fn serialize(&self) -> Vec { + let h: &[u8] = &[0]; + [h, &self.public_key[..], &self.request_ip.octets()].concat() + } +} + +impl UDPVpnHandshake { + pub fn deserialize(data: &Vec) -> Self { + UDPVpnHandshake { public_key: data[1..=32].to_vec(), request_ip: Ipv4Addr::new(data[33], data[34], data[35], data[36]) } + } +} + +pub trait UDPSerializable { + fn serialize(&self) -> Vec; +} \ No newline at end of file diff --git a/src/veil.rs b/src/veil.rs deleted file mode 100644 index bd90706..0000000 --- a/src/veil.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Veil -// Make it hidden. - -/*fn main() { - let mut small_rng = SmallRng::from_entropy(); - let b = Veil::init(&mut small_rng); - println!("Hello, world! Noise val: {}", b.noise(10.0)); -}*/ - -use core::f32::consts::E; -use core::f32::consts::PI; -use rand::{Rng, SeedableRng}; -use rand::rngs::SmallRng; -use rand::RngCore; - -pub struct Veil { - factor_e: f32, - factor_pi: f32, - factor_f: f32, - scale_e: f32, - scale_pi: f32, - scale_f: f32, - factor_t: f32 -} - -impl Veil { - fn default() -> Veil { - Veil{ factor_e: -1.2, factor_pi: 1.9, factor_f: -3.2, factor_t: 0.3, scale_e: -1.7, scale_f: -1.3, scale_pi: 0.7 } - } - - fn init(small_rng: &mut SmallRng) -> Veil { - Veil { factor_e: gen_rnd(small_rng), - factor_pi: gen_rnd(small_rng), - factor_f: gen_rnd(small_rng), - scale_e: gen_rnd(small_rng), - scale_pi: gen_rnd(small_rng), - scale_f: gen_rnd(small_rng), - factor_t: gen_rnd(small_rng) } - } - - fn noise(&self, x: f32) -> f32 { - self.factor_t * (self.factor_f * (self.scale_f * x).sin() + self.factor_e*(self.scale_e * E * x).sin() + self.factor_pi * (self.scale_pi * PI * x).sin()) - } -} - -fn gen_rnd(small_rng: &mut SmallRng) -> f32 { - (small_rng.gen_range(-8..=8) as f32) / 2.0 -}