Changes to be committed:

modified:   README.md
	modified:   src/client.rs
	modified:   src/main.rs
	modified:   src/server.rs
This commit is contained in:
Michael Wain 2024-09-07 01:49:52 +03:00
parent 1a5ba24d30
commit 7bbae124fc
4 changed files with 59 additions and 28 deletions

View File

@ -8,9 +8,38 @@
A lightweight VPN software, focused on scalability, traffic obfuscation and simplicity. A lightweight VPN software, focused on scalability, traffic obfuscation and simplicity.
## Documentation ## CLI Arguments
Check the [repository wiki]() to access the documentation, tutorials. ### Usage
```bash
./frida_vpn [FLAGS] [OPTIONS] <mode> --config <FILE>
```
### Options
| Name | Value type | Description |
| ------------- |:-------------:| -----:|
| bind-address | IP:PORT | The ip:port that would be used to bind server (config) |
| config | FILE_PATH | The path to VPN configuration file |
| endpoint | IP:PORT | The ip:port that would be used by client to connect (config) |
| interface | NAME | Explicitly set network interface name for routing |
| internal-address | IP | The address of VPN server in it's subnet (config) |
| keepalive | SECONDS_UINT | Keepalive packets interval (config) [default: 0] |
| obfs-type | OBFS | Obfuscation protocol (config) [possible values: dns, veil, xor] |
| peer-cfg | FILE_PATH | The path to VPN peer configuration file |
### Flags
| Name (short) | Name (long) | Description |
| ------------- |:-------------:| -----:|
| | broadcast-mode | If set to true, then all incoming traffic with an unknown destination address will be forwarded to all peers (config) |
| | grab-endpoint | If set to true, the endpoint address for peers will be grabbed from server config (config) |
| h | help | Prints help information |
| V | version | Prints version information |
### Args
| Name | Required | Description |
| ------------- |:-------------:| -----:|
| mode | true | Runs the program in certain mode [possible values: server, client, gen_cfg, new_peer] |
## Installation ## Installation

View File

@ -16,7 +16,7 @@ use crate::udp::{UDPVpnPacket, UDPVpnHandshake, UDPSerializable};
use network_interface::NetworkInterface; use network_interface::NetworkInterface;
use network_interface::NetworkInterfaceConfig; use network_interface::NetworkInterfaceConfig;
fn configure_routes(endpoint_ip: &str) { fn configure_routes(endpoint_ip: &str, s_interface: Option<&str>) {
let interfaces = NetworkInterface::show().unwrap(); let interfaces = NetworkInterface::show().unwrap();
let net_inter = interfaces.iter() let net_inter = interfaces.iter()
@ -26,6 +26,8 @@ fn configure_routes(endpoint_ip: &str) {
info!("Main network interface: {:?}", &net_inter.name); info!("Main network interface: {:?}", &net_inter.name);
let inter_name = if s_interface.is_some() { s_interface.unwrap() } else { &net_inter.name };
let mut ip_output = Command::new("ip") let mut ip_output = Command::new("ip")
.arg("-4") .arg("-4")
.arg("route") .arg("route")
@ -45,7 +47,7 @@ fn configure_routes(endpoint_ip: &str) {
.arg("add") .arg("add")
.arg(endpoint_ip.to_owned()+"/32") .arg(endpoint_ip.to_owned()+"/32")
.arg("dev") .arg("dev")
.arg(&net_inter.name) .arg(inter_name)
.output() .output()
.expect("Failed to execute ip route command."); .expect("Failed to execute ip route command.");
@ -54,7 +56,7 @@ fn configure_routes(endpoint_ip: &str) {
} }
} }
pub async fn client_mode(client_config: ClientConfiguration) { pub async fn client_mode(client_config: ClientConfiguration, s_interface: Option<&str>) {
info!("Starting client..."); info!("Starting client...");
let sock = UdpSocket::bind("0.0.0.0:25565").await.unwrap(); let sock = UdpSocket::bind("0.0.0.0:25565").await.unwrap();
@ -93,7 +95,7 @@ pub async fn client_mode(client_config: ClientConfiguration) {
}); });
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
configure_routes(client_config.server.endpoint.split(":")[0]); configure_routes(client_config.server.endpoint.split(":")[0], s_interface);
let priv_key = BASE64_STANDARD.decode(client_config.client.private_key).unwrap(); let priv_key = BASE64_STANDARD.decode(client_config.client.private_key).unwrap();

View File

@ -1,14 +1,8 @@
use std::{fs, net::{Ipv4Addr}, str}; use std::{fs, net::{Ipv4Addr}, str};
use clap::{App, Arg, ArgMatches}; use clap::{App, Arg, ArgMatches};
use env_logger::Builder; use env_logger::Builder;
use log::{error, LevelFilter}; use log::{error, LevelFilter};
use crate::config::{ ServerConfiguration, ClientConfiguration, ObfsProtocol, ServerPeer }; use crate::config::{ ServerConfiguration, ClientConfiguration, ObfsProtocol, ServerPeer };
mod obfs; mod obfs;
@ -17,7 +11,6 @@ mod client;
mod udp; mod udp;
mod config; mod config;
fn generate_server_config(matches: &ArgMatches, config_path: &str) { fn generate_server_config(matches: &ArgMatches, config_path: &str) {
let bind_address = matches.value_of("bind-address").expect("No bind address specified"); let bind_address = matches.value_of("bind-address").expect("No bind address specified");
let internal_address = matches.value_of("internal-address").expect("No internal address specified"); let internal_address = matches.value_of("internal-address").expect("No internal address specified");
@ -66,14 +59,14 @@ fn generate_peer_config(matches: &ArgMatches, config_path: &str, cfg_raw: &Strin
let _ = fs::write(config_path, serde_yaml::to_string(&config).unwrap()); let _ = fs::write(config_path, serde_yaml::to_string(&config).unwrap());
} }
async fn init_server(cfg_raw: &str ) { 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"); let config: ServerConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad server config file structure");
server::server_mode(config).await; server::server_mode(config, s_interface).await;
} }
async fn init_client(cfg_raw: &str) { async fn init_client(cfg_raw: &str, s_interface: Option<&str>) {
let config: ClientConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad client config file structure"); let config: ClientConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad client config file structure");
client::client_mode(config).await; client::client_mode(config, s_interface).await;
} }
#[tokio::main] #[tokio::main]
@ -93,7 +86,7 @@ async fn main() {
.required(true) .required(true)
.index(1) .index(1)
.possible_values(&["server", "client", "gen_cfg", "new_peer"]) .possible_values(&["server", "client", "gen_cfg", "new_peer"])
.help("Runs the program in either server or client mode")) .help("Runs the program in certain mode"))
.arg(Arg::with_name("config") .arg(Arg::with_name("config")
.long("config") .long("config")
.required(true) .required(true)
@ -137,10 +130,16 @@ async fn main() {
.takes_value(true)) .takes_value(true))
.arg(Arg::with_name("obfs-type") .arg(Arg::with_name("obfs-type")
.long("obfs-type") .long("obfs-type")
.possible_values(&["dns", "icmp", "xor"]) .possible_values(&["dns", "veil", "xor"])
.takes_value(true) .takes_value(true)
.value_name("OBFS") .value_name("OBFS")
.help("Obfuscation protocol (config)")) .help("Obfuscation protocol (config)"))
.arg(Arg::with_name("interface")
.long("interface")
.required(false)
.takes_value(true)
.value_name("NAME")
.help("Explicitly set network interface name for routing"))
.get_matches(); .get_matches();
let mode = matches.value_of("mode").unwrap(); let mode = matches.value_of("mode").unwrap();
@ -160,8 +159,8 @@ async fn main() {
let cfg_raw = &String::from_utf8(data.unwrap()).unwrap(); let cfg_raw = &String::from_utf8(data.unwrap()).unwrap();
match mode { match mode {
"server" => init_server(cfg_raw).await, "server" => init_server(cfg_raw, matches.value_of("interface")).await,
"client" => init_client(cfg_raw).await, "client" => init_client(cfg_raw, matches.value_of("interface")).await,
"new_peer" => generate_peer_config(&matches, config_path, cfg_raw), "new_peer" => generate_peer_config(&matches, config_path, cfg_raw),
_ => error!("There is config file already") _ => error!("There is config file already")
} }

View File

@ -1,4 +1,3 @@
//use crossbeam_channel::unbounded;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::{net::UdpSocket, sync::Mutex, time}; use tokio::{net::UdpSocket, sync::Mutex, time};
@ -17,7 +16,7 @@ use network_interface::NetworkInterfaceConfig;
use crate::config::{ ServerConfiguration, ServerPeer}; use crate::config::{ ServerConfiguration, ServerPeer};
use crate::udp::{UDPKeepAlive, UDPSerializable, UDPVpnHandshake, UDPVpnPacket}; use crate::udp::{UDPKeepAlive, UDPSerializable, UDPVpnHandshake, UDPVpnPacket};
fn configure_routes() { fn configure_routes(s_interface: Option<&str>) {
let interfaces = NetworkInterface::show().unwrap(); let interfaces = NetworkInterface::show().unwrap();
let net_inter = interfaces.iter() let net_inter = interfaces.iter()
@ -27,13 +26,15 @@ fn configure_routes() {
info!("Main network interface: {:?}", net_inter.name); info!("Main network interface: {:?}", net_inter.name);
let inter_name = if s_interface.is_some() { s_interface.unwrap() } else { &net_inter.name };
let mut ip_output = Command::new("iptables") let mut ip_output = Command::new("iptables")
.arg("-A") .arg("-A")
.arg("FORWARD") .arg("FORWARD")
.arg("-i") .arg("-i")
.arg("tun0") .arg("tun0")
.arg("-o") .arg("-o")
.arg(&net_inter.name) .arg(inter_name)
.arg("-j") .arg("-j")
.arg("ACCEPT") .arg("ACCEPT")
.output() .output()
@ -47,7 +48,7 @@ fn configure_routes() {
.arg("-A") .arg("-A")
.arg("FORWARD") .arg("FORWARD")
.arg("-i") .arg("-i")
.arg(&net_inter.name) .arg(inter_name)
.arg("-o") .arg("-o")
.arg("tun0") .arg("tun0")
.arg("-m") .arg("-m")
@ -69,7 +70,7 @@ fn configure_routes() {
.arg("-A") .arg("-A")
.arg("POSTROUTING") .arg("POSTROUTING")
.arg("-o") .arg("-o")
.arg(&net_inter.name) .arg(inter_name)
.arg("-j") .arg("-j")
.arg("MASQUERADE") .arg("MASQUERADE")
.output() .output()
@ -80,7 +81,7 @@ fn configure_routes() {
} }
} }
pub async fn server_mode(server_config: ServerConfiguration) { pub async fn server_mode(server_config: ServerConfiguration, s_interface: Option<&str>) {
info!("Starting server..."); info!("Starting server...");
let mut config = tun2::Configuration::default(); let mut config = tun2::Configuration::default();
@ -103,7 +104,7 @@ pub async fn server_mode(server_config: ServerConfiguration) {
let (send2hnd, mut recv2hnd) = mpsc::unbounded_channel::<(Vec<u8>, SocketAddr)>(); // unbounded::<(Vec<u8>, SocketAddr)>(); let (send2hnd, mut recv2hnd) = mpsc::unbounded_channel::<(Vec<u8>, SocketAddr)>(); // unbounded::<(Vec<u8>, SocketAddr)>();
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
configure_routes(); configure_routes(s_interface);
let tun_writer_task = tokio::spawn(async move { let tun_writer_task = tokio::spawn(async move {
loop { loop {