finalize P2P comm now just debugging

This commit is contained in:
PoliEcho 2025-07-30 18:09:10 +02:00
parent ddbe156846
commit c6583ea534
6 changed files with 327 additions and 17 deletions

24
Cargo.lock generated
View File

@ -749,6 +749,7 @@ dependencies = [
"clap",
"colored",
"hmac",
"libc",
"orx-concurrent-vec",
"pbkdf2",
"rand",
@ -757,6 +758,7 @@ dependencies = [
"sha2",
"smol",
"tappers",
"winapi",
]
[[package]]
@ -1076,6 +1078,28 @@ dependencies = [
"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]]
name = "windows-core"
version = "0.61.2"

View File

@ -29,5 +29,12 @@ sha2 = "0.10.9"
smol = "2.0.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]
no-timeout = []

113
src/client/config.rs Normal file
View File

@ -0,0 +1,113 @@
use std::io::ErrorKind;
use std::net::{SocketAddr, 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")]
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")]
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")]
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(())
}

View File

@ -1,3 +1,4 @@
mod config;
mod net;
mod tun;
mod types;
@ -52,14 +53,15 @@ fn main() -> std::io::Result<()> {
}
let mut buf: [u8; UDP_BUFFER_SIZE] = [0; UDP_BUFFER_SIZE];
let (socket, virtual_network, my_public_sock_addr) = {
let socket: UdpSocket = (|| -> std::io::Result<UdpSocket> {
let socket: Arc<UdpSocket> = Arc::new(|| -> std::io::Result<UdpSocket> {
match UdpSocket::bind("0.0.0.0:0") {
// bind to OS assigned random port
Ok(socket) => return Ok(socket),
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"))]
socket.set_read_timeout(Some(Duration::new(10, 0)))?; // set timeout to 10 seconds
@ -178,7 +180,7 @@ fn main() -> std::io::Result<()> {
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
eprintln!(
println!(
"{} reaching to other peers to obtain ip address",
"[LOG]".blue()
);
@ -243,17 +245,52 @@ fn main() -> std::io::Result<()> {
});
}
let tun_iface = match tun::create_tun_interface(virtual_network.read().unwrap().private_ip) {
Ok(t) => t,
Err(e) => {
eprintln!(
"{} failed to create Tun interface, Error: {}, are you running as root?",
"[CRITICAL]".red().bold(),
e
);
return Err(e);
let tun_iface = Arc::new(
match tun::create_tun_interface(virtual_network.read().unwrap().private_ip) {
Ok(t) => t,
Err(e) => {
eprintln!(
"{} failed to create Tun interface, Error: {}, are you running as root?",
"[CRITICAL]".red().bold(),
e
);
return Err(e);
}
},
);
smol::block_on(async {
smol::spawn(tun::read_tun_iface(
tun_iface.clone(),
socket.clone(),
virtual_network.clone(),
))
.detach();
loop {
buf.fill(0);
match socket.recv_from(&mut buf) {
Ok((data_lenght, src)) => {
smol::spawn(net::handle_incoming_connection(
buf,
src,
virtual_network.clone(),
tun_iface.clone(),
data_lenght,
))
.detach();
}
Err(e) => {
eprint!(
"{} failed to read from socket Error: {}",
"[ERROR]".red(),
e
);
exit(5); //EIO
}
}
}
};
});
Ok(())
}

View File

@ -5,6 +5,7 @@ use std::{
sync::{Arc, RwLock},
};
use colored::Colorize;
use pea_2_pea::*;
use rand::{RngCore, rng};
use tappers::Netmask;
@ -479,3 +480,131 @@ pub fn P2P_hello(
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>,
data_lenght: usize,
) {
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 + SALT_AND_IV_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_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;
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 + SALT_AND_IV_SIZE], &buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]) {
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-1 /*compensate for size and index diference*/]
}) {
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;
}
},
),
));
}
}
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(SALT_AND_IV_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 + SALT_AND_IV_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});
}
_ => {
eprintln!(
"{} unknown method ID: 0x{:02x}, Droping!",
"[WARNING]".bright_yellow(),
buf[0]
)
}
}
}

View File

@ -21,8 +21,8 @@ pub fn create_tun_interface(
}
pub async fn read_tun_iface(
tun_iface: &tappers::Tun,
socket: std::net::UdpSocket,
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];
@ -33,7 +33,7 @@ pub async fn read_tun_iface(
smol::spawn(handle_ip_packet(
buf[..data_lenght - 1].to_vec().into(),
network.clone(),
socket.try_clone().expect("couldn't clone the socket"),
socket.clone(),
))
.detach();
}
@ -43,7 +43,7 @@ pub async fn read_tun_iface(
pub async fn handle_ip_packet(
packet_data: Box<[u8]>,
network: Arc<RwLock<Network>>,
socket: std::net::UdpSocket,
socket: Arc<std::net::UdpSocket>,
) {
let dst_ip = std::net::Ipv4Addr::from(
match <[u8; 4]>::try_from(