Compare commits
6 Commits
752541c9f6
...
4d6ea8e626
Author | SHA1 | Date | |
---|---|---|---|
4d6ea8e626 | |||
a87899c402 | |||
dc55e4e1f6 | |||
c6583ea534 | |||
ddbe156846 | |||
b1335bef08 |
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -346,6 +346,15 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "3.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -738,7 +747,9 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"cipher",
|
"cipher",
|
||||||
"clap",
|
"clap",
|
||||||
|
"colored",
|
||||||
"hmac",
|
"hmac",
|
||||||
|
"libc",
|
||||||
"orx-concurrent-vec",
|
"orx-concurrent-vec",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"rand",
|
"rand",
|
||||||
@ -747,6 +758,7 @@ dependencies = [
|
|||||||
"sha2",
|
"sha2",
|
||||||
"smol",
|
"smol",
|
||||||
"tappers",
|
"tappers",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1066,6 +1078,28 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.61.2"
|
version = "0.61.2"
|
||||||
|
@ -18,6 +18,7 @@ cbc = "0.1.2"
|
|||||||
chrono = "0.4.41"
|
chrono = "0.4.41"
|
||||||
cipher = { version = "0.4.4", features = ["block-padding", "alloc"] }
|
cipher = { version = "0.4.4", features = ["block-padding", "alloc"] }
|
||||||
clap = { version = "4.5.41", features = ["derive"] }
|
clap = { version = "4.5.41", features = ["derive"] }
|
||||||
|
colored = "3.0.0"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
orx-concurrent-vec = "3.6.0"
|
orx-concurrent-vec = "3.6.0"
|
||||||
pbkdf2 = "0.12.2"
|
pbkdf2 = "0.12.2"
|
||||||
@ -28,5 +29,12 @@ sha2 = "0.10.9"
|
|||||||
smol = "2.0.2"
|
smol = "2.0.2"
|
||||||
tappers = "0.4.2"
|
tappers = "0.4.2"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = { version = "0.3", features = ["winsock2", "mswsock", "minwindef"] }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
no-timeout = []
|
no-timeout = []
|
||||||
|
@ -1,9 +1,18 @@
|
|||||||
mod net;
|
mod net;
|
||||||
|
mod net_utils;
|
||||||
|
mod tun;
|
||||||
mod types;
|
mod types;
|
||||||
|
use colored::Colorize;
|
||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use std::{net::UdpSocket, process::exit, time::Duration};
|
use std::{
|
||||||
|
net::UdpSocket,
|
||||||
|
process::exit,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::types::Network;
|
use crate::types::Network;
|
||||||
|
|
||||||
@ -29,6 +38,10 @@ struct Cli {
|
|||||||
)]
|
)]
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
|
|
||||||
|
#[arg(short = 'i', long = "interface-name")]
|
||||||
|
#[arg(help = "select tun interface name Default: pea0")]
|
||||||
|
if_name: Option<String>,
|
||||||
|
|
||||||
#[arg(short = 'v', long = "verbose")]
|
#[arg(short = 'v', long = "verbose")]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
|
||||||
@ -42,15 +55,17 @@ fn main() -> std::io::Result<()> {
|
|||||||
eprintln!("network id cannot have more then 255 charactes");
|
eprintln!("network id cannot have more then 255 charactes");
|
||||||
exit(7); // posix for E2BIG
|
exit(7); // posix for E2BIG
|
||||||
}
|
}
|
||||||
{
|
let mut buf: [u8; UDP_BUFFER_SIZE] = [0; UDP_BUFFER_SIZE];
|
||||||
let socket: UdpSocket = (|| -> std::io::Result<UdpSocket> {
|
let (socket, virtual_network, my_public_sock_addr) = {
|
||||||
|
let socket: Arc<UdpSocket> = Arc::new(|| -> std::io::Result<UdpSocket> {
|
||||||
match UdpSocket::bind("0.0.0.0:0") {
|
match UdpSocket::bind("0.0.0.0:0") {
|
||||||
// bind to OS assigned random port
|
// bind to OS assigned random port
|
||||||
Ok(socket) => return Ok(socket),
|
Ok(socket) => return Ok(socket),
|
||||||
Err(e) => Err(e), // exit on error
|
Err(e) => Err(e), // exit on error
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
.expect("Failed to bind to any available port");
|
.expect("Failed to bind to any available port")
|
||||||
|
.into();
|
||||||
|
|
||||||
#[cfg(not(feature = "no-timeout"))]
|
#[cfg(not(feature = "no-timeout"))]
|
||||||
socket.set_read_timeout(Some(Duration::new(10, 0)))?; // set timeout to 10 seconds
|
socket.set_read_timeout(Some(Duration::new(10, 0)))?; // set timeout to 10 seconds
|
||||||
@ -65,9 +80,11 @@ fn main() -> std::io::Result<()> {
|
|||||||
#[allow(non_snake_case)] // i think this is valid snake case but rustc doesnt think so
|
#[allow(non_snake_case)] // i think this is valid snake case but rustc doesnt think so
|
||||||
let server_SocketAddr: core::net::SocketAddr = format!("{}:{}", cli.registrar, server_port)
|
let server_SocketAddr: core::net::SocketAddr = format!("{}:{}", cli.registrar, server_port)
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap();
|
.expect(&format!(
|
||||||
|
"{}:{} is invalid sock addr",
|
||||||
|
cli.registrar, server_port
|
||||||
|
));
|
||||||
|
|
||||||
let mut buf: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
|
||||||
// query here
|
// query here
|
||||||
let public_sock_addr_raw: String =
|
let public_sock_addr_raw: String =
|
||||||
match net::query_request(&mut buf, &server_SocketAddr, &socket) {
|
match net::query_request(&mut buf, &server_SocketAddr, &socket) {
|
||||||
@ -75,9 +92,9 @@ fn main() -> std::io::Result<()> {
|
|||||||
Err(e) => return Err(ServerErrorResponses::into_io_error(e)),
|
Err(e) => return Err(ServerErrorResponses::into_io_error(e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut salt: [u8; SALT_AND_IV_SIZE] = [0u8; SALT_AND_IV_SIZE];
|
let mut salt: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
let mut iv: [u8; SALT_AND_IV_SIZE] = [0u8; SALT_AND_IV_SIZE];
|
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
let (public_sock_addr, encryption_key) = match cli.password {
|
let (mut public_sock_addr, encryption_key) = match cli.password {
|
||||||
Some(ref p) => {
|
Some(ref p) => {
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
rng.fill_bytes(&mut salt);
|
rng.fill_bytes(&mut salt);
|
||||||
@ -104,7 +121,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let virtual_network: Network = {
|
let virtual_network: Arc<RwLock<Network>> = RwLock::new({
|
||||||
match net::get_request(
|
match net::get_request(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&server_SocketAddr,
|
&server_SocketAddr,
|
||||||
@ -114,6 +131,10 @@ fn main() -> std::io::Result<()> {
|
|||||||
) {
|
) {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
eprintln!("Network exists joining it");
|
eprintln!("Network exists joining it");
|
||||||
|
public_sock_addr =
|
||||||
|
shared::crypto::encrypt(&n.key, &iv, public_sock_addr_raw.as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
.into_boxed_slice();
|
||||||
let _ = net::send_heartbeat(
|
let _ = net::send_heartbeat(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&server_SocketAddr,
|
&server_SocketAddr,
|
||||||
@ -152,7 +173,143 @@ fn main() -> std::io::Result<()> {
|
|||||||
exit(5); //EIO
|
exit(5); //EIO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
})
|
||||||
|
.into();
|
||||||
|
(
|
||||||
|
socket,
|
||||||
|
virtual_network,
|
||||||
|
types::EncryptablePulicSockAddr::new(iv, public_sock_addr),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
// all loops here will be auto skiped if there are no peers yet
|
||||||
|
let mut ips_used: [bool; u8::MAX as usize + 1] = [false; u8::MAX as usize + 1];
|
||||||
|
ips_used[0] = true; // ignore net addr
|
||||||
|
ips_used[u8::MAX as usize] = true; // ignore broadcast
|
||||||
|
println!(
|
||||||
|
"{} reaching to other peers to obtain ip address",
|
||||||
|
"[LOG]".blue()
|
||||||
|
);
|
||||||
|
let mut network_write_lock = virtual_network.write().unwrap(); // avoid deadlock
|
||||||
|
|
||||||
|
|
||||||
|
let encrypted = network_write_lock.encrypted;
|
||||||
|
let key = network_write_lock.key;
|
||||||
|
network_write_lock
|
||||||
|
.peers
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|peer| {
|
||||||
|
match net::P2P_query(&mut buf, &peer.sock_addr, &socket, encrypted,key) {
|
||||||
|
Ok(ip) => {
|
||||||
|
ips_used[ip.octets()[3] as usize] = true;
|
||||||
|
peer.private_ip = ip;
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} while getting ip from peer: {}, Error: {}",
|
||||||
|
"[ERROR]".red(),
|
||||||
|
peer.sock_addr,
|
||||||
|
e
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
network_write_lock.private_ip = std::net::Ipv4Addr::new(
|
||||||
|
DEFAULT_NETWORK_PREFIX[0],
|
||||||
|
DEFAULT_NETWORK_PREFIX[1],
|
||||||
|
DEFAULT_NETWORK_PREFIX[2],
|
||||||
|
ips_used.par_iter().position_first(|&b| !b).unwrap() as u8,
|
||||||
|
); // find first element that is false
|
||||||
|
|
||||||
|
network_write_lock
|
||||||
|
.peers
|
||||||
|
.retain(|peer| peer.private_ip != std::net::Ipv4Addr::UNSPECIFIED); // remove all peers without ip
|
||||||
|
|
||||||
|
network_write_lock
|
||||||
|
.peers
|
||||||
|
.iter()
|
||||||
|
.for_each(|peer| {
|
||||||
|
match net::P2P_hello(
|
||||||
|
&mut buf,
|
||||||
|
&peer.sock_addr,
|
||||||
|
&socket,
|
||||||
|
network_write_lock.private_ip,
|
||||||
|
encrypted,key
|
||||||
|
) {
|
||||||
|
Ok(_) => eprintln!(
|
||||||
|
"{} registered with peer: {}",
|
||||||
|
"[SUCCESS]".green(),
|
||||||
|
peer.sock_addr
|
||||||
|
),
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} failed to register with peer: {}, Error: {}",
|
||||||
|
"[ERROR]".red(),
|
||||||
|
peer.sock_addr,
|
||||||
|
e
|
||||||
|
),
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tun_iface = Arc::new(
|
||||||
|
match tun::create_tun_interface(virtual_network.read().unwrap().private_ip, cli.if_name) {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to create Tun interface, Error: {}, are you running as root?",
|
||||||
|
"[CRITICAL]".red().bold(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// timeout is no longer needed
|
||||||
|
#[cfg(not(feature = "no-timeout"))]
|
||||||
|
socket.set_read_timeout(None)?;
|
||||||
|
|
||||||
|
{let tun_iface_clone = tun_iface.clone();
|
||||||
|
let socket_clone = socket.clone();
|
||||||
|
let virtual_network_clone = virtual_network.clone();
|
||||||
|
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
tun::read_tun_iface(
|
||||||
|
tun_iface_clone,
|
||||||
|
socket_clone,
|
||||||
|
virtual_network_clone,
|
||||||
|
)
|
||||||
|
});} // just let me have my thread
|
||||||
|
|
||||||
|
smol::block_on(async {
|
||||||
|
loop {
|
||||||
|
buf.fill(0);
|
||||||
|
match socket.recv_from(&mut buf) {
|
||||||
|
Ok((data_lenght, src)) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("recived method 0x{:02x} spawning handler", buf[0]);
|
||||||
|
smol::spawn(net::handle_incoming_connection(
|
||||||
|
buf,
|
||||||
|
src,
|
||||||
|
virtual_network.clone(),
|
||||||
|
tun_iface.clone(),
|
||||||
|
socket.clone(),
|
||||||
|
data_lenght,
|
||||||
|
))
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to read from socket Error: {}\n{}",
|
||||||
|
"[WARNING]".red(),
|
||||||
|
e,
|
||||||
|
"Retrying".bright_yellow()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,71 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::ErrorKind,
|
io::ErrorKind,
|
||||||
net::{SocketAddr, UdpSocket},
|
net::{Ipv4Addr, SocketAddr, UdpSocket},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use pea_2_pea::*;
|
|
||||||
|
|
||||||
use super::types;
|
use super::types;
|
||||||
|
use crate::net_utils;
|
||||||
|
use crate::types::Peer;
|
||||||
|
use colored::Colorize;
|
||||||
|
use libc::socket;
|
||||||
|
use pea_2_pea::*;
|
||||||
|
use rand::{RngCore, rng};
|
||||||
|
|
||||||
// return data_lenght and number of retryes
|
// return data_lenght and number of retryes
|
||||||
pub fn send_and_recv_with_retry(
|
pub fn send_and_recv_with_retry(
|
||||||
buf: &mut [u8; BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
send_buf: &[u8],
|
send_buf: &[u8],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
retry_max: usize,
|
retry_max: usize,
|
||||||
) -> Result<(usize, usize), ServerErrorResponses> {
|
) -> Result<(usize, usize), ServerErrorResponses> {
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
|
net_utils::enable_icmp_errors(socket)?;
|
||||||
|
|
||||||
let mut retry_count: usize = 0;
|
let mut retry_count: usize = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match socket.send_to(send_buf, dst) {
|
match socket.send_to(send_buf, dst) {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("send {} bytes", s);
|
eprintln!("send {} bytes", s);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => match e.kind() {
|
||||||
panic!("Error sending data: {}", e);
|
ErrorKind::ConnectionReset
|
||||||
}
|
| ErrorKind::ConnectionRefused
|
||||||
|
| ErrorKind::NetworkUnreachable
|
||||||
|
| ErrorKind::HostUnreachable => {
|
||||||
|
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
||||||
|
e.kind(),
|
||||||
|
format!("Destination unreachable: {}", e),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
_ => return Err(ServerErrorResponses::IO(e)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
if let Err(icmp_error) = net_utils::check_icmp_error_queue(socket) {
|
||||||
|
return Err(ServerErrorResponses::IO(icmp_error));
|
||||||
}
|
}
|
||||||
|
|
||||||
match socket.recv_from(buf) {
|
match socket.recv_from(buf) {
|
||||||
Ok((data_lenght, src)) => {
|
Ok((data_length, src)) => {
|
||||||
if src != *dst {
|
if src != *dst {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match buf[0] {
|
match buf[0] {
|
||||||
x if x == send_buf[0] as u8 => {
|
x if x == send_buf[0] as u8 => {
|
||||||
return Ok((data_lenght, retry_count));
|
return Ok((data_length, retry_count));
|
||||||
}
|
}
|
||||||
x if x == ServerResponse::GENERAL_ERROR as u8 => {
|
x if x == ServerResponse::GENERAL_ERROR as u8 => {
|
||||||
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
||||||
std::io::ErrorKind::InvalidData,
|
std::io::ErrorKind::InvalidData,
|
||||||
match std::str::from_utf8(&buf[1..data_lenght]) {
|
match std::str::from_utf8(&buf[1..data_length]) {
|
||||||
// the firts byte is compensated for sice this is len not index
|
|
||||||
Ok(s) => s.to_string(),
|
Ok(s) => s.to_string(),
|
||||||
Err(e) => format!("invalid error string: {}", e).to_string(),
|
Err(e) => format!("invalid error string: {}", e),
|
||||||
},
|
},
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -59,28 +81,43 @@ pub fn send_and_recv_with_retry(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == ErrorKind::WouldBlock || e.kind() == ErrorKind::TimedOut => {
|
Err(e) if e.kind() == ErrorKind::WouldBlock || e.kind() == ErrorKind::TimedOut => {
|
||||||
// timedout
|
#[cfg(target_os = "linux")]
|
||||||
|
if let Err(icmp_error) = net_utils::check_icmp_error_queue(socket) {
|
||||||
|
return Err(ServerErrorResponses::IO(icmp_error));
|
||||||
|
}
|
||||||
|
|
||||||
if retry_count >= retry_max {
|
if retry_count >= retry_max {
|
||||||
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
||||||
ErrorKind::TimedOut,
|
ErrorKind::TimedOut,
|
||||||
"max retry count reached without responce",
|
"Max retry count reached - destination may be unreachable",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
retry_count += 1;
|
retry_count += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => match e.kind() {
|
||||||
return Err(ServerErrorResponses::IO(e));
|
ErrorKind::ConnectionReset
|
||||||
}
|
| ErrorKind::ConnectionRefused
|
||||||
|
| ErrorKind::NetworkUnreachable
|
||||||
|
| ErrorKind::HostUnreachable => {
|
||||||
|
return Err(ServerErrorResponses::IO(std::io::Error::new(
|
||||||
|
e.kind(),
|
||||||
|
format!("Destination unreachable during receive: {}", e),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
_ => return Err(ServerErrorResponses::IO(e)),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query_request(
|
pub fn query_request(
|
||||||
buf: &mut [u8; BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
) -> Result<String, ServerErrorResponses> {
|
) -> Result<String, ServerErrorResponses> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("QUERY method");
|
||||||
match send_and_recv_with_retry(
|
match send_and_recv_with_retry(
|
||||||
buf,
|
buf,
|
||||||
&[ServerMethods::QUERY as u8],
|
&[ServerMethods::QUERY as u8],
|
||||||
@ -102,13 +139,15 @@ pub fn query_request(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_request(
|
pub fn register_request(
|
||||||
buf: &mut [u8; BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
network: &types::Network,
|
network: &types::Network,
|
||||||
public_sock_addr: &Box<[u8]>,
|
public_sock_addr: &Box<[u8]>,
|
||||||
iv: &[u8; SALT_AND_IV_SIZE as usize],
|
iv: &[u8; BLOCK_SIZE as usize],
|
||||||
) -> Result<usize, ServerErrorResponses> {
|
) -> Result<usize, ServerErrorResponses> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("REGISTER method");
|
||||||
let mut send_buf: Box<[u8]> = vec![
|
let mut send_buf: Box<[u8]> = vec![
|
||||||
0u8;
|
0u8;
|
||||||
RegisterRequestDataPositions::DATA as usize
|
RegisterRequestDataPositions::DATA as usize
|
||||||
@ -142,10 +181,10 @@ pub fn register_request(
|
|||||||
.copy_from_slice(network.net_id.as_bytes()); // store network id
|
.copy_from_slice(network.net_id.as_bytes()); // store network id
|
||||||
|
|
||||||
send_buf[RegisterRequestDataPositions::IV as usize
|
send_buf[RegisterRequestDataPositions::IV as usize
|
||||||
..RegisterRequestDataPositions::IV as usize + SALT_AND_IV_SIZE as usize]
|
..RegisterRequestDataPositions::IV as usize + BLOCK_SIZE as usize]
|
||||||
.copy_from_slice(iv); // copy iv ad salt do the request
|
.copy_from_slice(iv); // copy iv ad salt do the request
|
||||||
send_buf[RegisterRequestDataPositions::SALT as usize
|
send_buf[RegisterRequestDataPositions::SALT as usize
|
||||||
..RegisterRequestDataPositions::SALT as usize + SALT_AND_IV_SIZE as usize]
|
..RegisterRequestDataPositions::SALT as usize + BLOCK_SIZE as usize]
|
||||||
.copy_from_slice(&network.salt);
|
.copy_from_slice(&network.salt);
|
||||||
|
|
||||||
send_buf[RegisterRequestDataPositions::SOCKADDR_LEN as usize] = public_sock_addr.len() as u8;
|
send_buf[RegisterRequestDataPositions::SOCKADDR_LEN as usize] = public_sock_addr.len() as u8;
|
||||||
@ -163,12 +202,14 @@ pub fn register_request(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_request(
|
pub fn get_request(
|
||||||
buf: &mut [u8; BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
network_id: &String,
|
network_id: &String,
|
||||||
password: &Option<String>,
|
password: &Option<String>,
|
||||||
) -> Result<types::Network, ServerErrorResponses> {
|
) -> Result<types::Network, ServerErrorResponses> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("GET method");
|
||||||
let mut send_buf: Box<[u8]> =
|
let mut send_buf: Box<[u8]> =
|
||||||
vec![0u8; GetRequestDataPositions::ID as usize + network_id.len()].into_boxed_slice();
|
vec![0u8; GetRequestDataPositions::ID as usize + network_id.len()].into_boxed_slice();
|
||||||
send_buf[0] = ServerMethods::GET as u8;
|
send_buf[0] = ServerMethods::GET as u8;
|
||||||
@ -202,13 +243,13 @@ pub fn get_request(
|
|||||||
|
|
||||||
let mut num_of_clients: u8 = buf[GetResponseDataPositions::NUM_OF_CLIENTS as usize];
|
let mut num_of_clients: u8 = buf[GetResponseDataPositions::NUM_OF_CLIENTS as usize];
|
||||||
|
|
||||||
let salt: [u8; SALT_AND_IV_SIZE as usize] = buf[GetResponseDataPositions::SALT as usize
|
let salt: [u8; BLOCK_SIZE as usize] = buf[GetResponseDataPositions::SALT as usize
|
||||||
..GetResponseDataPositions::SALT as usize + SALT_AND_IV_SIZE as usize]
|
..GetResponseDataPositions::SALT as usize + BLOCK_SIZE as usize]
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
let mut peers: Vec<SocketAddr> = Vec::with_capacity(1); // at least one client
|
let mut peers: Vec<Peer> = Vec::with_capacity(1); // at least one client
|
||||||
|
|
||||||
let key: [u8; 32] = match password {
|
let key: [u8; 32] = match password {
|
||||||
Some(p) => shared::crypto::derive_key_from_password(p.as_bytes(), &salt),
|
Some(p) => shared::crypto::derive_key_from_password(p.as_bytes(), &salt),
|
||||||
@ -224,24 +265,17 @@ pub fn get_request(
|
|||||||
|
|
||||||
while num_of_clients != 0 {
|
while num_of_clients != 0 {
|
||||||
let sock_addr_len: u8 = buf[GetResponseDataPositions::CLIENTS as usize + offset];
|
let sock_addr_len: u8 = buf[GetResponseDataPositions::CLIENTS as usize + offset];
|
||||||
let mut iv: [u8; SALT_AND_IV_SIZE as usize] = [0; SALT_AND_IV_SIZE as usize];
|
let mut iv: [u8; BLOCK_SIZE as usize] = [0; BLOCK_SIZE as usize];
|
||||||
let sock_addr_raw: Box<[u8]> =
|
let sock_addr_raw: Box<[u8]> =
|
||||||
buf[GetResponseDataPositions::CLIENTS as usize + 1 + offset + SALT_AND_IV_SIZE as usize
|
buf[GetResponseDataPositions::CLIENTS as usize + 1 + offset + BLOCK_SIZE as usize
|
||||||
..GetResponseDataPositions::CLIENTS as usize
|
..GetResponseDataPositions::CLIENTS as usize
|
||||||
+ 1
|
+ 1
|
||||||
+ offset
|
+ offset
|
||||||
+ SALT_AND_IV_SIZE as usize
|
+ BLOCK_SIZE as usize
|
||||||
+ sock_addr_len as usize]
|
+ sock_addr_len as usize]
|
||||||
.to_vec()
|
.to_vec()
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!(
|
|
||||||
"sock_addr_raw: {}",
|
|
||||||
sock_addr_raw
|
|
||||||
.iter()
|
|
||||||
.map(|x| format!("{:02X} ", x))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
loop {
|
loop {
|
||||||
// loop used to easily skip peer
|
// loop used to easily skip peer
|
||||||
let peer: SocketAddr = if encrypted {
|
let peer: SocketAddr = if encrypted {
|
||||||
@ -250,14 +284,23 @@ pub fn get_request(
|
|||||||
..GetResponseDataPositions::CLIENTS as usize
|
..GetResponseDataPositions::CLIENTS as usize
|
||||||
+ 1
|
+ 1
|
||||||
+ offset
|
+ offset
|
||||||
+ SALT_AND_IV_SIZE as usize],
|
+ BLOCK_SIZE as usize],
|
||||||
|
);
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"IV: {}\nSockAddr: {}",
|
||||||
|
iv.iter().map(|x| format!("{:02X} ", x)).collect::<String>(),
|
||||||
|
sock_addr_raw
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
);
|
);
|
||||||
match SocketAddr::from_str(&{
|
match SocketAddr::from_str(&{
|
||||||
// sacrificed a goat to borrow checker to make this work
|
// sacrificed a goat to borrow checker to make this work
|
||||||
let decrypted = match shared::crypto::decrypt(&key, &iv, &sock_addr_raw) {
|
let decrypted = match shared::crypto::decrypt(&key, &iv, &sock_addr_raw) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
eprintln!("Warning peer ignored due to invalid data");
|
eprintln!("Warning peer ignored due to invalid data\nError: {}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -272,8 +315,8 @@ pub fn get_request(
|
|||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
eprintln!("Warning peer ignored due to invalid data");
|
eprintln!("Warning peer ignored due to invalid data\nError: {}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,17 +330,17 @@ pub fn get_request(
|
|||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
eprintln!("Warning peer ignored due to invalid data");
|
eprintln!("Warning peer ignored due to invalid data\nError: {}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
peers.push(peer);
|
peers.push(types::Peer::new(peer, None));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset += SALT_AND_IV_SIZE as usize + sock_addr_len as usize;
|
offset += BLOCK_SIZE as usize + sock_addr_len as usize + 1 /*for size byte */;
|
||||||
num_of_clients -= 1;
|
num_of_clients -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,17 +354,19 @@ pub fn get_request(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_heartbeat(
|
pub fn send_heartbeat(
|
||||||
buf: &mut [u8; BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
network: &types::Network,
|
network: &types::Network,
|
||||||
my_public_sock_addr: &Box<[u8]>,
|
my_public_sock_addr: &Box<[u8]>,
|
||||||
iv: &[u8; SALT_AND_IV_SIZE as usize],
|
iv: &[u8; BLOCK_SIZE as usize],
|
||||||
) -> Result<usize, ServerErrorResponses> {
|
) -> Result<usize, ServerErrorResponses> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("HEARTBEAT method");
|
||||||
let mut send_buf: Box<[u8]> = vec![
|
let mut send_buf: Box<[u8]> = vec![
|
||||||
0u8;
|
0u8;
|
||||||
HeartBeatRequestDataPositions::IV as usize
|
HeartBeatRequestDataPositions::IV as usize
|
||||||
+ SALT_AND_IV_SIZE as usize
|
+ BLOCK_SIZE as usize
|
||||||
+ my_public_sock_addr.len()
|
+ my_public_sock_addr.len()
|
||||||
+ network.net_id.len()
|
+ network.net_id.len()
|
||||||
]
|
]
|
||||||
@ -333,7 +378,7 @@ pub fn send_heartbeat(
|
|||||||
my_public_sock_addr.len() as u8;
|
my_public_sock_addr.len() as u8;
|
||||||
|
|
||||||
send_buf[HeartBeatRequestDataPositions::IV as usize
|
send_buf[HeartBeatRequestDataPositions::IV as usize
|
||||||
..HeartBeatRequestDataPositions::IV as usize + SALT_AND_IV_SIZE as usize]
|
..HeartBeatRequestDataPositions::IV as usize + BLOCK_SIZE as usize]
|
||||||
.copy_from_slice(iv);
|
.copy_from_slice(iv);
|
||||||
|
|
||||||
send_buf[HeartBeatRequestDataPositions::DATA as usize
|
send_buf[HeartBeatRequestDataPositions::DATA as usize
|
||||||
@ -346,8 +391,323 @@ pub fn send_heartbeat(
|
|||||||
+ my_public_sock_addr.len()]
|
+ my_public_sock_addr.len()]
|
||||||
.copy_from_slice(&my_public_sock_addr);
|
.copy_from_slice(&my_public_sock_addr);
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"IV: {}\nSockAddr: {}",
|
||||||
|
iv.iter().map(|x| format!("{:02X} ", x)).collect::<String>(),
|
||||||
|
my_public_sock_addr
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
);
|
||||||
|
|
||||||
match send_and_recv_with_retry(buf, &send_buf, dst, socket, STANDARD_RETRY_MAX) {
|
match send_and_recv_with_retry(buf, &send_buf, dst, socket, STANDARD_RETRY_MAX) {
|
||||||
Ok((data_lenght, _)) => return Ok(data_lenght),
|
Ok((data_lenght, _)) => return Ok(data_lenght),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn P2P_query(
|
||||||
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
|
dst: &SocketAddr,
|
||||||
|
socket: &UdpSocket,
|
||||||
|
encrypted: bool, // avoid deadlock
|
||||||
|
key: [u8; 32]
|
||||||
|
) -> Result<std::net::Ipv4Addr, Box<dyn std::error::Error>> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("P2P QUERY method");
|
||||||
|
|
||||||
|
let (data_lenght, _) = send_and_recv_with_retry(
|
||||||
|
buf,
|
||||||
|
&[P2PMethods::PEER_QUERY as u8],
|
||||||
|
dst,
|
||||||
|
socket,
|
||||||
|
STANDARD_RETRY_MAX,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let iv: [u8; BLOCK_SIZE] = buf[P2PStandardDataPositions::IV as usize
|
||||||
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE]
|
||||||
|
.try_into()
|
||||||
|
.expect("this should never happen");
|
||||||
|
|
||||||
|
let tmp_decrypted: Vec<u8>;
|
||||||
|
|
||||||
|
return Ok(std::net::Ipv4Addr::from_str(
|
||||||
|
if encrypted {
|
||||||
|
match shared::crypto::decrypt(
|
||||||
|
&key,
|
||||||
|
&iv,
|
||||||
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght - 1],
|
||||||
|
) {
|
||||||
|
Ok(decrypted) => {
|
||||||
|
tmp_decrypted = decrypted;
|
||||||
|
match std::str::from_utf8(&tmp_decrypted) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => return Err(Box::new(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(Box::new(ServerErrorResponses::GENERAL_ERROR(format!(
|
||||||
|
"{}",
|
||||||
|
e
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match std::str::from_utf8(
|
||||||
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght - 1],
|
||||||
|
) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => return Err(Box::new(e)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn P2P_hello(
|
||||||
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
|
dst: &SocketAddr,
|
||||||
|
socket: &UdpSocket,
|
||||||
|
private_ip: Ipv4Addr,
|
||||||
|
encrypted: bool, // avoid deadlock
|
||||||
|
key: [u8; 32],
|
||||||
|
) -> Result<usize, ServerErrorResponses> {
|
||||||
|
let private_ip_str = private_ip.to_string();
|
||||||
|
let (private_ip_final, iv) = if encrypted {
|
||||||
|
let mut rng = rng();
|
||||||
|
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
|
rng.fill_bytes(&mut iv);
|
||||||
|
(
|
||||||
|
shared::crypto::encrypt(
|
||||||
|
&key,
|
||||||
|
&iv,
|
||||||
|
&private_ip_str.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into_boxed_slice(),
|
||||||
|
iv,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
private_ip_str.as_bytes().to_vec().into_boxed_slice(),
|
||||||
|
[0u8; BLOCK_SIZE],
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut send_buf: Box<[u8]> =
|
||||||
|
vec![0u8; P2PStandardDataPositions::DATA as usize + private_ip_final.len()].into();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"registering network:\niv: {}\nIP: {}",
|
||||||
|
iv.iter().map(|x| format!("{:02X} ", x)).collect::<String>(),
|
||||||
|
private_ip_final
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
send_buf[0] = P2PMethods::PEER_HELLO as u8;
|
||||||
|
send_buf[P2PStandardDataPositions::IV as usize
|
||||||
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE]
|
||||||
|
.copy_from_slice(&iv);
|
||||||
|
|
||||||
|
send_buf[P2PStandardDataPositions::DATA as usize..].copy_from_slice(&private_ip_final);
|
||||||
|
|
||||||
|
match send_and_recv_with_retry(buf, &send_buf, dst, socket, STANDARD_RETRY_MAX) {
|
||||||
|
Ok((data_lenght, _)) => return Ok(data_lenght),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_incoming_connection(
|
||||||
|
buf: [u8; UDP_BUFFER_SIZE],
|
||||||
|
src: SocketAddr,
|
||||||
|
network: Arc<RwLock<types::Network>>,
|
||||||
|
tun_iface: Arc<tappers::Tun>,
|
||||||
|
socket: Arc<std::net::UdpSocket>,
|
||||||
|
data_lenght: usize,
|
||||||
|
) {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("recived method 0x{:02x}", buf[0]);
|
||||||
|
match buf[0] {
|
||||||
|
|
||||||
|
x if x == P2PMethods::PACKET as u8 => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("PACKET from difernt peer receved");
|
||||||
|
|
||||||
|
if network.read().unwrap().encrypted {
|
||||||
|
match shared::crypto::decrypt(
|
||||||
|
&network.read().unwrap().key,
|
||||||
|
&buf[P2PStandardDataPositions::IV as usize
|
||||||
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE],
|
||||||
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/],
|
||||||
|
) {
|
||||||
|
Ok(data) => match tun_iface.send(&data) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} failed to write packet to tun interface, Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} failed to decrypt packet, Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match tun_iface.send(&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]) {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(e) => eprintln!("{} failed to write packet to tun interface, Error: {}", "[WARNING]".yellow(), e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x if x == P2PMethods::PEER_QUERY as u8 => {
|
||||||
|
let encrypted = network.read().unwrap().encrypted;
|
||||||
|
let private_ip = network.read().unwrap().private_ip;
|
||||||
|
let private_ip_str = private_ip.to_string();
|
||||||
|
let mut send_buf: Box<[u8]> = if encrypted {
|
||||||
|
vec![0; P2PStandardDataPositions::DATA as usize + 1 + (private_ip_str.len() + (BLOCK_SIZE - (private_ip_str.len() % BLOCK_SIZE)))].into() // calculate lenght of data with block alligment
|
||||||
|
} else {
|
||||||
|
vec![0; P2PStandardDataPositions::DATA as usize + 1 + private_ip_str.len()].into()
|
||||||
|
};
|
||||||
|
|
||||||
|
send_buf[0] = P2PMethods::PEER_QUERY as u8;
|
||||||
|
let mut iv = [0u8; BLOCK_SIZE];
|
||||||
|
if encrypted {
|
||||||
|
let mut rng = rng();
|
||||||
|
rng.fill_bytes(&mut iv);
|
||||||
|
send_buf[P2PStandardDataPositions::IV as usize..P2PStandardDataPositions::IV as usize+BLOCK_SIZE].copy_from_slice(&iv);
|
||||||
|
send_buf[P2PStandardDataPositions::DATA as usize..P2PStandardDataPositions::DATA as usize + (private_ip_str.len() + (BLOCK_SIZE - (private_ip_str.len() % BLOCK_SIZE)))].copy_from_slice(shared::crypto::encrypt(&network.read().unwrap().key, &iv, private_ip_str.as_bytes()).unwrap().as_slice());
|
||||||
|
} else {
|
||||||
|
send_buf[P2PStandardDataPositions::DATA as usize..P2PStandardDataPositions::DATA as usize + private_ip_str.len()].copy_from_slice(private_ip_str.as_bytes());
|
||||||
|
}
|
||||||
|
match socket.send_to(&send_buf, &src) {
|
||||||
|
Ok(s) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("send {} bytes", s);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error sending data: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
x if x == P2PMethods::PEER_HELLO as u8 => {
|
||||||
|
println!("{} peer hello receved from: {}", "[LOG]".blue(), src);
|
||||||
|
|
||||||
|
let tmp_data: Vec<u8>;
|
||||||
|
{
|
||||||
|
let mut network_write_lock = network.write().unwrap();
|
||||||
|
let key: [u8; 32] = network_write_lock.key;
|
||||||
|
let encrypted: bool = network_write_lock.encrypted;
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"registering network:\niv: {}\nIP: {}",
|
||||||
|
&buf[P2PStandardDataPositions::IV as usize
|
||||||
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE].iter().map(|x| format!("{:02X} ", x)).collect::<String>(),
|
||||||
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
);
|
||||||
|
network_write_lock.peers.push(Peer::new(
|
||||||
|
src,
|
||||||
|
Some(
|
||||||
|
match std::net::Ipv4Addr::from_str(
|
||||||
|
match std::str::from_utf8(if encrypted {
|
||||||
|
match shared::crypto::decrypt(&key, &buf[P2PStandardDataPositions::IV as usize
|
||||||
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE], &buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize]) {
|
||||||
|
Ok(data) => {tmp_data = data; &tmp_data},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to decrypt ip from peer, ignoring it Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize]
|
||||||
|
}) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to parse ip from peer, ignoring it Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Ok(ip) => ip,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to parse ip from peer, ignoring it Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
match socket.send_to(&[P2PMethods::PEER_HELLO as u8], &src) {
|
||||||
|
Ok(s) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("send {} bytes", s);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error sending data: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x if x == P2PMethods::PEER_GOODBYE as u8 => {
|
||||||
|
println!("{} peer goodbye receved from: {}", "[LOG]".blue(), src);
|
||||||
|
|
||||||
|
let mut network_lock = network.write().unwrap();
|
||||||
|
|
||||||
|
let key = network_lock.key;
|
||||||
|
let encrypted: bool = network_lock.encrypted;
|
||||||
|
|
||||||
|
let mut data_tmp: Vec<u8> = Vec::with_capacity(BLOCK_SIZE); // block size
|
||||||
|
|
||||||
|
network_lock.peers.retain(|peer| !{peer.private_ip == match std::net::Ipv4Addr::from_str(match std::str::from_utf8( if encrypted {
|
||||||
|
match shared::crypto::decrypt(&key, &buf[P2PStandardDataPositions::IV as usize..P2PStandardDataPositions::IV as usize + BLOCK_SIZE], &buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]) {
|
||||||
|
Ok(data) => {data_tmp = data;
|
||||||
|
&data_tmp},
|
||||||
|
Err(e) => {eprintln!("{} error parsing ip, Error: {}", "[ERROR]".red(), e); return false;},
|
||||||
|
}
|
||||||
|
} else {&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]}) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {eprintln!("{} error parsing ip, Error: {}", "[ERROR]".red(), e); return false;},
|
||||||
|
}) {
|
||||||
|
Ok(ip) => ip,
|
||||||
|
Err(e) => {eprintln!("{} error parsing ip, Error: {}", "[ERROR]".red(), e); return false;},
|
||||||
|
} && peer.sock_addr == src});
|
||||||
|
match socket.send_to(&[P2PMethods::PEER_GOODBYE as u8], &src) {
|
||||||
|
Ok(s) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("send {} bytes", s);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error sending data: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
eprintln!(
|
||||||
|
"{} unknown method ID: 0x{:02x}, Droping!",
|
||||||
|
"[WARNING]".bright_yellow(),
|
||||||
|
buf[0]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
112
src/client/net_utils.rs
Normal file
112
src/client/net_utils.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use std::os::windows::io::AsRawSocket;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use winapi::shared::minwindef::{BOOL, DWORD, FALSE};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use winapi::um::mswsock::SIO_UDP_CONNRESET;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use winapi::um::winsock2::{SOCKET_ERROR, WSAIoctl};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn enable_icmp_errors(socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
let socket_handle = socket.as_raw_socket();
|
||||||
|
let mut bytes_returned: DWORD = 0;
|
||||||
|
let enable: BOOL = FALSE;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
WSAIoctl(
|
||||||
|
socket_handle as usize,
|
||||||
|
SIO_UDP_CONNRESET,
|
||||||
|
&enable as *const _ as *mut _,
|
||||||
|
std::mem::size_of::<BOOL>() as DWORD,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
0,
|
||||||
|
&mut bytes_returned,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if result == SOCKET_ERROR {
|
||||||
|
Err(std::io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn enable_icmp_errors(socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
let fd = socket.as_raw_fd();
|
||||||
|
let optval: libc::c_int = 1;
|
||||||
|
|
||||||
|
let ret = unsafe {
|
||||||
|
libc::setsockopt(
|
||||||
|
fd,
|
||||||
|
libc::SOL_IP,
|
||||||
|
libc::IP_RECVERR,
|
||||||
|
&optval as *const _ as *const libc::c_void,
|
||||||
|
std::mem::size_of::<libc::c_int>() as libc::socklen_t,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if ret < 0 {
|
||||||
|
Err(std::io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn check_icmp_error_queue(socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
use libc::{MSG_ERRQUEUE, iovec, msghdr, recvmsg};
|
||||||
|
|
||||||
|
let fd = socket.as_raw_fd();
|
||||||
|
let mut buf = [0u8; 1024];
|
||||||
|
let mut control_buf = [0u8; 1024];
|
||||||
|
|
||||||
|
let mut iov = iovec {
|
||||||
|
iov_base: buf.as_mut_ptr() as *mut libc::c_void,
|
||||||
|
iov_len: buf.len(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut msg: msghdr = unsafe { std::mem::zeroed() };
|
||||||
|
msg.msg_iov = &mut iov;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_control = control_buf.as_mut_ptr() as *mut libc::c_void;
|
||||||
|
msg.msg_controllen = control_buf.len();
|
||||||
|
|
||||||
|
let result = unsafe { recvmsg(fd, &mut msg, MSG_ERRQUEUE) };
|
||||||
|
|
||||||
|
if result < 0 {
|
||||||
|
let error = std::io::Error::last_os_error();
|
||||||
|
if error.kind() == std::io::ErrorKind::WouldBlock {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::NetworkUnreachable,
|
||||||
|
"ICMP destination unreachable received",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn check_icmp_error_queue(_socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
|
||||||
|
fn enable_icmp_errors(_socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
|
||||||
|
fn check_icmp_error_queue(_socket: &UdpSocket) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
105
src/client/tun.rs
Normal file
105
src/client/tun.rs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use pea_2_pea::*;
|
||||||
|
use rand::RngCore;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
use crate::types::Network;
|
||||||
|
|
||||||
|
pub fn create_tun_interface(
|
||||||
|
private_ip: std::net::Ipv4Addr,
|
||||||
|
if_name: Option<String>,
|
||||||
|
) -> Result<tappers::Tun, std::io::Error> {
|
||||||
|
let mut tun_iface: tappers::Tun = tappers::Tun::new_named(tappers::Interface::new(
|
||||||
|
if_name.unwrap_or("pea0".to_owned()),
|
||||||
|
)?)?;
|
||||||
|
let mut addr_req = tappers::AddAddressV4::new(private_ip);
|
||||||
|
addr_req.set_netmask(24);
|
||||||
|
let mut broadcast_addr_oct = private_ip.octets();
|
||||||
|
broadcast_addr_oct[3] = 255;
|
||||||
|
addr_req.set_broadcast(std::net::Ipv4Addr::from(broadcast_addr_oct));
|
||||||
|
tun_iface.add_addr(addr_req)?;
|
||||||
|
tun_iface.set_up()?;
|
||||||
|
return Ok(tun_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_tun_iface(
|
||||||
|
tun_iface: Arc<tappers::Tun>,
|
||||||
|
socket: Arc<std::net::UdpSocket>,
|
||||||
|
network: Arc<RwLock<Network>>,
|
||||||
|
) {
|
||||||
|
let mut buf: [u8; IP_BUFFER_SIZE] = [0u8; IP_BUFFER_SIZE];
|
||||||
|
|
||||||
|
smol::block_on(async {
|
||||||
|
loop {
|
||||||
|
let data_lenght = tun_iface.recv(&mut buf).unwrap(); // build in auto termination, isn't it great
|
||||||
|
smol::spawn(handle_ip_packet(
|
||||||
|
buf[..data_lenght - 1].to_vec().into(),
|
||||||
|
network.clone(),
|
||||||
|
socket.clone(),
|
||||||
|
))
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_ip_packet(
|
||||||
|
packet_data: Box<[u8]>,
|
||||||
|
network: Arc<RwLock<Network>>,
|
||||||
|
socket: Arc<std::net::UdpSocket>,
|
||||||
|
) {
|
||||||
|
let dst_ip = std::net::Ipv4Addr::from(
|
||||||
|
match <[u8; 4]>::try_from(
|
||||||
|
&packet_data[DEST_IN_IPV4_OFFSET..DEST_IN_IPV4_OFFSET + IPV4_SIZE],
|
||||||
|
) {
|
||||||
|
Ok(slice) => slice,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Procesing of IP packet failed, Invalid dst IP: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
|
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
|
rng.fill_bytes(&mut iv);
|
||||||
|
|
||||||
|
let mut encrypted_data =
|
||||||
|
match shared::crypto::encrypt(&network.read().unwrap().key, &iv, &packet_data) {
|
||||||
|
Ok(cr) => cr,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to encrypt packet droping it: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
encrypted_data.insert(0, P2PMethods::PACKET as u8);
|
||||||
|
encrypted_data.splice(1..1, iv);
|
||||||
|
|
||||||
|
if dst_ip.octets()[3] == 255 {
|
||||||
|
network.read().unwrap().peers.par_iter().for_each(|peer| {
|
||||||
|
// broadcast
|
||||||
|
match socket.send_to(&encrypted_data, peer.sock_addr) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => eprintln!("failed to send packet: {}", e),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let dst = match network
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.peers
|
||||||
|
.par_iter()
|
||||||
|
.find_any(|&p| p.private_ip == dst_ip)
|
||||||
|
.map(|p| p.sock_addr)
|
||||||
|
{
|
||||||
|
Some(sa) => sa,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
match socket.send_to(&encrypted_data, dst) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => eprintln!("failed to send packet: {}", e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,23 @@
|
|||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
|
|
||||||
|
#[readonly::make]
|
||||||
|
pub struct Peer {
|
||||||
|
#[readonly]
|
||||||
|
pub sock_addr: std::net::SocketAddr,
|
||||||
|
pub private_ip: std::net::Ipv4Addr,
|
||||||
|
}
|
||||||
|
impl Peer {
|
||||||
|
pub fn new(sock_addr: std::net::SocketAddr, private_ip: Option<std::net::Ipv4Addr>) -> Self {
|
||||||
|
Peer {
|
||||||
|
sock_addr,
|
||||||
|
private_ip: match private_ip {
|
||||||
|
Some(ip) => ip,
|
||||||
|
None => std::net::Ipv4Addr::UNSPECIFIED,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[readonly::make]
|
#[readonly::make]
|
||||||
pub struct Network {
|
pub struct Network {
|
||||||
#[readonly]
|
#[readonly]
|
||||||
@ -8,9 +27,9 @@ pub struct Network {
|
|||||||
#[readonly]
|
#[readonly]
|
||||||
pub net_id: String,
|
pub net_id: String,
|
||||||
#[readonly]
|
#[readonly]
|
||||||
pub salt: [u8; SALT_AND_IV_SIZE as usize],
|
pub salt: [u8; BLOCK_SIZE as usize],
|
||||||
#[readonly]
|
pub peers: Vec<Peer>,
|
||||||
pub peers: Vec<std::net::SocketAddr>,
|
pub private_ip: std::net::Ipv4Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
@ -18,8 +37,8 @@ impl Network {
|
|||||||
encrypted: bool,
|
encrypted: bool,
|
||||||
key: [u8; 32],
|
key: [u8; 32],
|
||||||
net_id: String,
|
net_id: String,
|
||||||
salt: [u8; SALT_AND_IV_SIZE as usize],
|
salt: [u8; BLOCK_SIZE as usize],
|
||||||
peers: Vec<std::net::SocketAddr>,
|
peers: Vec<Peer>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Network {
|
Network {
|
||||||
encrypted,
|
encrypted,
|
||||||
@ -27,6 +46,21 @@ impl Network {
|
|||||||
net_id,
|
net_id,
|
||||||
salt,
|
salt,
|
||||||
peers,
|
peers,
|
||||||
|
private_ip: std::net::Ipv4Addr::UNSPECIFIED,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[readonly::make]
|
||||||
|
pub struct EncryptablePulicSockAddr {
|
||||||
|
#[readonly]
|
||||||
|
pub iv: [u8; BLOCK_SIZE],
|
||||||
|
#[readonly]
|
||||||
|
pub sock_addr: Box<[u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncryptablePulicSockAddr {
|
||||||
|
pub fn new(iv: [u8; BLOCK_SIZE], sock_addr: Box<[u8]>) -> Self {
|
||||||
|
EncryptablePulicSockAddr { iv, sock_addr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
33
src/lib.rs
33
src/lib.rs
@ -1,12 +1,18 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
pub const SERVER_PORT: u16 = 3543;
|
pub const SERVER_PORT: u16 = 3543;
|
||||||
pub const BUFFER_SIZE: usize = 65535;
|
pub const UDP_BUFFER_SIZE: usize = 65527;
|
||||||
|
pub const IP_BUFFER_SIZE: usize = 65535;
|
||||||
pub const DEFAULT_TIMEOUT: u64 = 30;
|
pub const DEFAULT_TIMEOUT: u64 = 30;
|
||||||
pub const VERSION: &str = "v0.1";
|
pub const VERSION: &str = "v0.1";
|
||||||
pub const SALT_AND_IV_SIZE: usize = 16;
|
pub const BLOCK_SIZE: usize = 16;
|
||||||
pub const STANDARD_RETRY_MAX: usize = 10;
|
pub const STANDARD_RETRY_MAX: usize = 10;
|
||||||
|
|
||||||
|
pub const DEST_IN_IPV4_OFFSET: usize = 16;
|
||||||
|
pub const IPV4_SIZE: usize = 4;
|
||||||
|
|
||||||
|
pub const DEFAULT_NETWORK_PREFIX: [u8; 3] = [172, 22, 44];
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ServerMethods {
|
pub enum ServerMethods {
|
||||||
QUERY = 0, // return IP and port of the client
|
QUERY = 0, // return IP and port of the client
|
||||||
@ -76,8 +82,8 @@ pub enum RegisterRequestDataPositions {
|
|||||||
ID_LEN = 2,
|
ID_LEN = 2,
|
||||||
SOCKADDR_LEN = 3,
|
SOCKADDR_LEN = 3,
|
||||||
SALT = 4,
|
SALT = 4,
|
||||||
IV = (SALT_AND_IV_SIZE as usize + RegisterRequestDataPositions::SALT as usize) as usize,
|
IV = (BLOCK_SIZE as usize + RegisterRequestDataPositions::SALT as usize) as usize,
|
||||||
DATA = (SALT_AND_IV_SIZE as usize + RegisterRequestDataPositions::IV as usize) as usize, // after this there will be id and sockaddr in string or encrypted form after
|
DATA = (BLOCK_SIZE as usize + RegisterRequestDataPositions::IV as usize) as usize, // after this there will be id and sockaddr in string or encrypted form after
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
@ -93,7 +99,7 @@ pub enum GetResponseDataPositions {
|
|||||||
NUM_OF_CLIENTS = 2,
|
NUM_OF_CLIENTS = 2,
|
||||||
SALT = 3,
|
SALT = 3,
|
||||||
CLIENTS =
|
CLIENTS =
|
||||||
(SALT_AND_IV_SIZE as usize + RegisterRequestDataPositions::SALT as usize) - 1 as usize,
|
(BLOCK_SIZE as usize + RegisterRequestDataPositions::SALT as usize) - 1 as usize,
|
||||||
// after this there will be blocks of this sturcture: one byte size of sockaddr than there will be IV that is SALT_AND_IV_SIZE long and after that there will be sockaddr this repeats until the end of packet
|
// after this there will be blocks of this sturcture: one byte size of sockaddr than there will be IV that is SALT_AND_IV_SIZE long and after that there will be sockaddr this repeats until the end of packet
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +109,22 @@ pub enum HeartBeatRequestDataPositions {
|
|||||||
ID_LEN = 1,
|
ID_LEN = 1,
|
||||||
SOCKADDR_LEN = 2,
|
SOCKADDR_LEN = 2,
|
||||||
IV = 3,
|
IV = 3,
|
||||||
DATA = (HeartBeatRequestDataPositions::IV as usize + SALT_AND_IV_SIZE as usize) as usize, // first ID than sockaddr
|
DATA = (HeartBeatRequestDataPositions::IV as usize + BLOCK_SIZE as usize) as usize, // first ID than sockaddr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum P2PMethods {
|
||||||
|
PEER_QUERY = 20, // responds with its private ip
|
||||||
|
PEER_HELLO = 21, // sends private ip encrypted if on
|
||||||
|
PEER_GOODBYE = 22, // sends private ip encrypted if on
|
||||||
|
PACKET = 23, // sends IP packet encrypted if on
|
||||||
|
}
|
||||||
|
#[repr(usize)]
|
||||||
|
pub enum P2PStandardDataPositions {
|
||||||
|
// sould apply to all P2P Methods
|
||||||
|
IV = 1,
|
||||||
|
DATA = P2PStandardDataPositions::IV as usize + BLOCK_SIZE,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
@ -24,7 +24,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let registration_vector: Arc<ConcurrentVec<types::Registration>> =
|
let registration_vector: Arc<ConcurrentVec<types::Registration>> =
|
||||||
Arc::new(orx_concurrent_vec::ConcurrentVec::new());
|
Arc::new(orx_concurrent_vec::ConcurrentVec::new());
|
||||||
|
|
||||||
let mut buf: [u8; pea_2_pea::BUFFER_SIZE] = [0u8; pea_2_pea::BUFFER_SIZE];
|
let mut buf: [u8; pea_2_pea::UDP_BUFFER_SIZE] = [0u8; pea_2_pea::UDP_BUFFER_SIZE];
|
||||||
smol::block_on(async {
|
smol::block_on(async {
|
||||||
loop {
|
loop {
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
@ -9,7 +9,7 @@ use rayon::prelude::*;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::u8;
|
use std::u8;
|
||||||
pub async fn handle_request(
|
pub async fn handle_request(
|
||||||
buf: [u8; BUFFER_SIZE],
|
buf: [u8; UDP_BUFFER_SIZE],
|
||||||
socket: std::sync::Arc<std::net::UdpSocket>,
|
socket: std::sync::Arc<std::net::UdpSocket>,
|
||||||
src: core::net::SocketAddr,
|
src: core::net::SocketAddr,
|
||||||
data_len: usize,
|
data_len: usize,
|
||||||
@ -77,7 +77,7 @@ pub async fn handle_request(
|
|||||||
.cloned();
|
.cloned();
|
||||||
let mut send_vec: Vec<u8> = Vec::with_capacity(
|
let mut send_vec: Vec<u8> = Vec::with_capacity(
|
||||||
1/*initial status byte */ +
|
1/*initial status byte */ +
|
||||||
GetResponseDataPositions::SALT as usize + /*2 times one for SALT and other for first IV*/ 2*SALT_AND_IV_SIZE as usize + 20, /*magic number guess for how long is encrypted residencial ipv4 with port long */
|
GetResponseDataPositions::SALT as usize + /*2 times one for SALT and other for first IV*/ 2*BLOCK_SIZE as usize + 20, /*magic number guess for how long is encrypted residencial ipv4 with port long */
|
||||||
); // use vector to handle many clients
|
); // use vector to handle many clients
|
||||||
|
|
||||||
send_vec.push(ServerMethods::GET as u8); // this means success
|
send_vec.push(ServerMethods::GET as u8); // this means success
|
||||||
@ -92,6 +92,20 @@ pub async fn handle_request(
|
|||||||
eprintln!("Found {} clients", registration.clients.len());
|
eprintln!("Found {} clients", registration.clients.len());
|
||||||
|
|
||||||
registration.clients.iter().for_each(|client| {
|
registration.clients.iter().for_each(|client| {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"Client:\nIV: {}\nSockAddr: {}",
|
||||||
|
client
|
||||||
|
.iv
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
client
|
||||||
|
.client_sock_addr
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
);
|
||||||
let sock_addr_len: u8 = client.client_sock_addr.len() as u8;
|
let sock_addr_len: u8 = client.client_sock_addr.len() as u8;
|
||||||
|
|
||||||
send_vec.push(sock_addr_len);
|
send_vec.push(sock_addr_len);
|
||||||
@ -101,7 +115,7 @@ pub async fn handle_request(
|
|||||||
send_vec.extend_from_slice(&client.client_sock_addr);
|
send_vec.extend_from_slice(&client.client_sock_addr);
|
||||||
});
|
});
|
||||||
|
|
||||||
if send_vec.len() > BUFFER_SIZE {
|
if send_vec.len() > UDP_BUFFER_SIZE {
|
||||||
send_general_error_to_client(
|
send_general_error_to_client(
|
||||||
src,
|
src,
|
||||||
std::io::Error::new(
|
std::io::Error::new(
|
||||||
@ -177,21 +191,21 @@ pub async fn handle_request(
|
|||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let salt: Option<[u8; SALT_AND_IV_SIZE as usize]>;
|
let salt: Option<[u8; BLOCK_SIZE as usize]>;
|
||||||
let iv: Option<[u8; SALT_AND_IV_SIZE as usize]>;
|
let iv: Option<[u8; BLOCK_SIZE as usize]>;
|
||||||
|
|
||||||
if encrypted {
|
if encrypted {
|
||||||
salt = Some(
|
salt = Some(
|
||||||
buf[(RegisterRequestDataPositions::SALT as usize)
|
buf[(RegisterRequestDataPositions::SALT as usize)
|
||||||
..(RegisterRequestDataPositions::SALT as usize)
|
..(RegisterRequestDataPositions::SALT as usize)
|
||||||
+ (SALT_AND_IV_SIZE as usize)]
|
+ (BLOCK_SIZE as usize)]
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("this should never happen"),
|
.expect("this should never happen"),
|
||||||
);
|
);
|
||||||
iv = Some(
|
iv = Some(
|
||||||
buf[(RegisterRequestDataPositions::IV as usize)
|
buf[(RegisterRequestDataPositions::IV as usize)
|
||||||
..(RegisterRequestDataPositions::IV as usize)
|
..(RegisterRequestDataPositions::IV as usize)
|
||||||
+ (SALT_AND_IV_SIZE as usize)]
|
+ (BLOCK_SIZE as usize)]
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("this should never happen"),
|
.expect("this should never happen"),
|
||||||
)
|
)
|
||||||
@ -283,9 +297,9 @@ pub async fn handle_request(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let iv: [u8; SALT_AND_IV_SIZE as usize] =
|
let iv: [u8; BLOCK_SIZE as usize] =
|
||||||
buf[HeartBeatRequestDataPositions::IV as usize
|
buf[HeartBeatRequestDataPositions::IV as usize
|
||||||
..HeartBeatRequestDataPositions::IV as usize + SALT_AND_IV_SIZE as usize]
|
..HeartBeatRequestDataPositions::IV as usize + BLOCK_SIZE as usize]
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -296,6 +310,16 @@ pub async fn handle_request(
|
|||||||
+ sock_addr_len as usize]
|
+ sock_addr_len as usize]
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"IV: {}\nSockAddr: {}",
|
||||||
|
iv.iter().map(|x| format!("{:02X} ", x)).collect::<String>(),
|
||||||
|
sock_addr
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
);
|
||||||
|
|
||||||
match registration_vector
|
match registration_vector
|
||||||
.iter()
|
.iter()
|
||||||
.find(|elem| elem.map(|s| &s.net_id == &net_id)) // find if id exists
|
.find(|elem| elem.map(|s| &s.net_id == &net_id)) // find if id exists
|
||||||
@ -303,7 +327,7 @@ pub async fn handle_request(
|
|||||||
Some(reg) => {
|
Some(reg) => {
|
||||||
let current_time = chrono::Utc::now().timestamp();
|
let current_time = chrono::Utc::now().timestamp();
|
||||||
reg.update(|r| {r.last_heart_beat = current_time;
|
reg.update(|r| {r.last_heart_beat = current_time;
|
||||||
match r.clients.par_iter_mut().find_first(|c| *c.client_sock_addr == *sock_addr && c.iv == iv) {
|
match r.clients.par_iter_mut().find_any(|c| *c.client_sock_addr == *sock_addr && c.iv == iv) {
|
||||||
Some(c) => c.last_heart_beat = current_time,
|
Some(c) => c.last_heart_beat = current_time,
|
||||||
None => {// add new client if it isn't found
|
None => {// add new client if it isn't found
|
||||||
r.clients.push(types::Client::new(sock_addr.clone(), current_time, iv));
|
r.clients.push(types::Client::new(sock_addr.clone(), current_time, iv));
|
||||||
|
@ -8,11 +8,11 @@ pub struct Client {
|
|||||||
pub client_sock_addr: Vec<u8>,
|
pub client_sock_addr: Vec<u8>,
|
||||||
pub last_heart_beat: i64,
|
pub last_heart_beat: i64,
|
||||||
#[readonly]
|
#[readonly]
|
||||||
pub iv: [u8; SALT_AND_IV_SIZE as usize],
|
pub iv: [u8; BLOCK_SIZE as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(client_addr: Vec<u8>, heart_beat: i64, iv: [u8; SALT_AND_IV_SIZE as usize]) -> Self {
|
pub fn new(client_addr: Vec<u8>, heart_beat: i64, iv: [u8; BLOCK_SIZE as usize]) -> Self {
|
||||||
Client {
|
Client {
|
||||||
client_sock_addr: client_addr,
|
client_sock_addr: client_addr,
|
||||||
last_heart_beat: heart_beat,
|
last_heart_beat: heart_beat,
|
||||||
@ -32,7 +32,7 @@ pub struct Registration {
|
|||||||
#[readonly]
|
#[readonly]
|
||||||
pub encrypted: bool,
|
pub encrypted: bool,
|
||||||
#[readonly]
|
#[readonly]
|
||||||
pub salt: [u8; SALT_AND_IV_SIZE as usize],
|
pub salt: [u8; BLOCK_SIZE as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Registration {
|
impl Registration {
|
||||||
@ -41,19 +41,19 @@ impl Registration {
|
|||||||
client_addr: Vec<u8>,
|
client_addr: Vec<u8>,
|
||||||
encrypted: bool,
|
encrypted: bool,
|
||||||
heart_beat: i64,
|
heart_beat: i64,
|
||||||
salt: Option<[u8; SALT_AND_IV_SIZE as usize]>,
|
salt: Option<[u8; BLOCK_SIZE as usize]>,
|
||||||
iv: Option<[u8; SALT_AND_IV_SIZE as usize]>,
|
iv: Option<[u8; BLOCK_SIZE as usize]>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Registration {
|
Registration {
|
||||||
net_id,
|
net_id,
|
||||||
clients: vec![Client::new(
|
clients: vec![Client::new(
|
||||||
client_addr,
|
client_addr,
|
||||||
heart_beat,
|
heart_beat,
|
||||||
iv.unwrap_or([0; SALT_AND_IV_SIZE as usize]),
|
iv.unwrap_or([0; BLOCK_SIZE as usize]),
|
||||||
)],
|
)],
|
||||||
encrypted,
|
encrypted,
|
||||||
last_heart_beat: heart_beat,
|
last_heart_beat: heart_beat,
|
||||||
salt: salt.unwrap_or([0; SALT_AND_IV_SIZE as usize]),
|
salt: salt.unwrap_or([0; BLOCK_SIZE as usize]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ pub fn decrypt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
pub fn test_all_crypto_functions() {
|
pub fn test_all_crypto_functions() {
|
||||||
// Test data
|
// Test data
|
||||||
let password = b"test_password_123";
|
let password = b"test_password_123";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user