things
This commit is contained in:
parent
4d4fc6c7bf
commit
fc94f655b2
43 changed files with 1957 additions and 694 deletions
|
|
@ -5,3 +5,15 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
||||
tokio = { version = "1.47.0", features = ["full"] }
|
||||
bytemuck = { version = "1.23.1", features = ["derive"] }
|
||||
typenum = "1.18.0"
|
||||
rc4 = "0.1.0"
|
||||
log = "0.4.25"
|
||||
cfg-if = "1.0.4"
|
||||
proxy-common = {path = "../proxy-common"}
|
||||
hmac = "0.12.1"
|
||||
md-5 = "^0.10.6"
|
||||
|
||||
[features]
|
||||
friends = []
|
||||
|
|
|
|||
54
prudpv0/src/crypto/common_crypto.rs
Normal file
54
prudpv0/src/crypto/common_crypto.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
trait IterExtra: Iterator {
|
||||
fn sum_wrapping_u8(&mut self) -> u8
|
||||
where
|
||||
Self::Item: Into<u8>;
|
||||
|
||||
fn sum_wrapping_u32(&mut self) -> u32
|
||||
where
|
||||
Self::Item: Into<u32>;
|
||||
}
|
||||
|
||||
impl<T: Iterator> IterExtra for T {
|
||||
fn sum_wrapping_u8(&mut self) -> u8
|
||||
where
|
||||
Self::Item: Into<u8>,
|
||||
{
|
||||
let mut sum = 0u8;
|
||||
for v in self {
|
||||
let val: u8 = v.into();
|
||||
sum = sum.wrapping_add(val);
|
||||
}
|
||||
sum
|
||||
}
|
||||
fn sum_wrapping_u32(&mut self) -> u32
|
||||
where
|
||||
Self::Item: Into<u32>,
|
||||
{
|
||||
let mut sum = 0u32;
|
||||
for v in self {
|
||||
let val: u32 = v.into();
|
||||
sum = sum.wrapping_add(val);
|
||||
}
|
||||
sum
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn common_checksum(access_key: &str, data: &[u8]) -> u8 {
|
||||
let leftover = data.len() % 4;
|
||||
let word_sum = bytemuck::cast_slice::<_, u32>(&data[..data.len() - leftover])
|
||||
.iter()
|
||||
.copied()
|
||||
.sum_wrapping_u32();
|
||||
|
||||
let checksum = access_key.as_bytes().iter().copied().sum_wrapping_u8();
|
||||
let checksum = checksum.wrapping_add(
|
||||
(&data[data.len() - leftover..])
|
||||
.iter()
|
||||
.copied()
|
||||
.sum_wrapping_u8(),
|
||||
);
|
||||
let checksum = checksum.wrapping_add(word_sum.to_ne_bytes().into_iter().sum_wrapping_u8());
|
||||
|
||||
checksum
|
||||
}
|
||||
5
prudpv0/src/crypto/friends_common.rs
Normal file
5
prudpv0/src/crypto/friends_common.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
use hmac::Hmac;
|
||||
use md5::Md5;
|
||||
|
||||
pub const ACCESS_KEY: &str = "ridfebb9";
|
||||
pub type HmacMd5 = Hmac<Md5>;
|
||||
52
prudpv0/src/crypto/friends_insecure.rs
Normal file
52
prudpv0/src/crypto/friends_insecure.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use hmac::Mac;
|
||||
use rc4::{KeyInit, Rc4, StreamCipher};
|
||||
use rnex_core::prudp::encryption::{DEFAULT_KEY, EncryptionPair};
|
||||
use typenum::U5;
|
||||
|
||||
use crate::crypto::{
|
||||
Crypto, CryptoInstance,
|
||||
common_crypto::common_checksum,
|
||||
friends_common::{ACCESS_KEY, HmacMd5},
|
||||
};
|
||||
|
||||
pub struct InsecureInstance {
|
||||
pair: EncryptionPair<Rc4<U5>>,
|
||||
}
|
||||
|
||||
impl CryptoInstance for InsecureInstance {
|
||||
fn decrypt_incoming(&mut self, data: &mut [u8]) {
|
||||
self.pair.recv.apply_keystream(data);
|
||||
}
|
||||
fn encrypt_outgoing(&mut self, data: &mut [u8]) {
|
||||
self.pair.send.apply_keystream(data);
|
||||
}
|
||||
fn get_user_id(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4] {
|
||||
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
||||
.expect("unable to create hmac md5");
|
||||
hmac.update(data);
|
||||
hmac.finalize().into_bytes()[0..4].try_into().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Insecure();
|
||||
|
||||
impl Crypto for Insecure {
|
||||
type Instance = InsecureInstance;
|
||||
fn new() -> Self {
|
||||
Self()
|
||||
}
|
||||
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
||||
common_checksum(ACCESS_KEY, data)
|
||||
}
|
||||
|
||||
fn instantiate(&self, packet_data: &[u8]) -> Self::Instance {
|
||||
InsecureInstance {
|
||||
pair: EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY)),
|
||||
}
|
||||
}
|
||||
}
|
||||
47
prudpv0/src/crypto/friends_secure.rs
Normal file
47
prudpv0/src/crypto/friends_secure.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use hmac::Mac;
|
||||
use rc4::Rc4;
|
||||
use rnex_core::prudp::encryption::EncryptionPair;
|
||||
use typenum::U32;
|
||||
|
||||
use crate::crypto::{
|
||||
Crypto, CryptoInstance,
|
||||
common_crypto::common_checksum,
|
||||
friends_common::{ACCESS_KEY, HmacMd5},
|
||||
};
|
||||
|
||||
pub struct SecureInstance {
|
||||
pair: EncryptionPair<Rc4<U32>>,
|
||||
}
|
||||
|
||||
impl CryptoInstance for SecureInstance {
|
||||
fn decrypt_incoming(&mut self, data: &mut [u8]) {
|
||||
todo!()
|
||||
}
|
||||
fn encrypt_outgoing(&mut self, data: &mut [u8]) {
|
||||
todo!()
|
||||
}
|
||||
fn get_user_id(&self) -> u32 {
|
||||
todo!()
|
||||
}
|
||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4] {
|
||||
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
||||
.expect("unable to create hmac md5");
|
||||
hmac.update(data);
|
||||
hmac.finalize().into_bytes()[0..4].try_into().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Secure();
|
||||
|
||||
impl Crypto for Secure {
|
||||
type Instance = SecureInstance;
|
||||
fn new() -> Self {
|
||||
Self()
|
||||
}
|
||||
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
||||
common_checksum(ACCESS_KEY, data)
|
||||
}
|
||||
fn instantiate(&self, data: &[u8]) -> Self::Instance {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
9
prudpv0/src/crypto/insecure.rs
Normal file
9
prudpv0/src/crypto/insecure.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::crypto::Crypto;
|
||||
|
||||
pub struct Insecure();
|
||||
|
||||
impl Crypto for Insecure {
|
||||
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
32
prudpv0/src/crypto/mod.rs
Normal file
32
prudpv0/src/crypto/mod.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use cfg_if::cfg_if;
|
||||
|
||||
mod common_crypto;
|
||||
|
||||
pub trait CryptoInstance: Send + 'static {
|
||||
fn decrypt_incoming(&mut self, data: &mut [u8]);
|
||||
fn encrypt_outgoing(&mut self, data: &mut [u8]);
|
||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4];
|
||||
fn get_user_id(&self) -> u32;
|
||||
}
|
||||
|
||||
pub trait Crypto: Send + Sync + 'static {
|
||||
type Instance: CryptoInstance;
|
||||
fn new() -> Self;
|
||||
fn calculate_checksum(&self, data: &[u8]) -> u8;
|
||||
fn instantiate(&self, data: &[u8]) -> Self::Instance;
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "friends")]{
|
||||
pub mod friends_common;
|
||||
pub mod friends_insecure;
|
||||
pub use friends_insecure::*;
|
||||
pub mod friends_secure;
|
||||
pub use friends_secure::*;
|
||||
} else {
|
||||
pub mod secure;
|
||||
pub use secure::*;
|
||||
pub mod insecure;
|
||||
pub use insecure::*;
|
||||
}
|
||||
}
|
||||
9
prudpv0/src/crypto/secure.rs
Normal file
9
prudpv0/src/crypto/secure.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::crypto::Crypto;
|
||||
|
||||
pub struct Secure();
|
||||
|
||||
impl Crypto for Secure {
|
||||
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
use log::{error, info, warn};
|
||||
use proxy_common::{ProxyStartupParam, setup_edge_node_connection};
|
||||
use rnex_core::executables::common::{OWN_IP_PRIVATE, OWN_IP_PUBLIC, SERVER_PORT};
|
||||
use rnex_core::prudp::types_flags::TypesFlags;
|
||||
use rnex_core::prudp::types_flags::types::SYN;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use rnex_core::reggie::EdgeNodeHolderConnectOption::Register;
|
||||
use rnex_core::reggie::RemoteEdgeNodeHolder;
|
||||
use rnex_core::rmc::protocols::{OnlyRemote, new_rmc_gateway_connection};
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use rnex_core::util::SplittableBufferConnection;
|
||||
use std::env;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::process::abort;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use crate::crypto::{Crypto, Insecure, Secure};
|
||||
use crate::packet::PRUDPV0Packet;
|
||||
use crate::server::Server;
|
||||
|
||||
mod crypto;
|
||||
mod packet;
|
||||
mod server;
|
||||
|
||||
pub static EDGE_NODE_HOLDER: LazyLock<SocketAddrV4> = LazyLock::new(|| {
|
||||
env::var("EDGE_NODE_HOLDER")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.expect("EDGE_NODE_HOLDER not set")
|
||||
});
|
||||
|
||||
pub static FORWARD_DESTINATION: LazyLock<SocketAddrV4> = LazyLock::new(|| {
|
||||
env::var("FORWARD_DESTINATION")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.expect("FORWARD_DESTINATION not set")
|
||||
});
|
||||
//same as with prudpv1 this is responsible for handeling the different cryptography
|
||||
//implementations, e.g. secure and insecure(this also includes special cases like friends)
|
||||
|
||||
async fn start_proxy<T: Crypto>(param: ProxyStartupParam) {
|
||||
setup_edge_node_connection(¶m, || abort());
|
||||
|
||||
info!("creating cryptography instance");
|
||||
let mut crypto = Arc::new(T::new());
|
||||
info!("binding to socket");
|
||||
|
||||
let server: Arc<Server<T>> = Arc::new(Server::new().await);
|
||||
|
||||
info!("waiting on packets");
|
||||
server.run_task().await;
|
||||
}
|
||||
|
||||
pub async fn start_secure(param: ProxyStartupParam) {
|
||||
start_proxy::<Secure>(param).await;
|
||||
}
|
||||
|
||||
pub async fn start_insecure(param: ProxyStartupParam) {
|
||||
start_proxy::<Insecure>(param).await;
|
||||
}
|
||||
187
prudpv0/src/packet.rs
Normal file
187
prudpv0/src/packet.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
use std::mem::transmute;
|
||||
|
||||
use bytemuck::{Pod, Zeroable, try_from_bytes, try_from_bytes_mut};
|
||||
use log::error;
|
||||
use rnex_core::prudp::{
|
||||
types_flags::{
|
||||
TypesFlags,
|
||||
flags::{HAS_SIZE, NEED_ACK},
|
||||
types::{CONNECT, DATA, SYN},
|
||||
},
|
||||
virtual_port::VirtualPort,
|
||||
};
|
||||
|
||||
use crate::crypto::{Crypto, CryptoInstance};
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Clone, Copy, Pod, Zeroable, Debug)]
|
||||
pub struct PRUDPV0Header {
|
||||
pub source: VirtualPort,
|
||||
pub destination: VirtualPort,
|
||||
pub type_flags: TypesFlags,
|
||||
pub session_id: u8,
|
||||
pub packet_signature: [u8; 4],
|
||||
pub sequence_id: u16,
|
||||
}
|
||||
#[repr(transparent)]
|
||||
pub struct PRUDPV0Packet<T: AsRef<[u8]>>(pub T);
|
||||
|
||||
impl<T: AsRef<[u8]>> PRUDPV0Packet<T> {
|
||||
#[inline(always)]
|
||||
pub fn get_packet_specific_size(&self) -> Option<usize> {
|
||||
Some(get_types_flags_size_from_types_flags(
|
||||
self.header()?.type_flags,
|
||||
))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn header(&self) -> Option<&PRUDPV0Header> {
|
||||
try_from_bytes(self.0.as_ref().get(..size_of::<PRUDPV0Header>())?).ok()
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn header_mut(&mut self) -> Option<&mut PRUDPV0Header>
|
||||
where
|
||||
T: AsMut<[u8]>,
|
||||
{
|
||||
try_from_bytes_mut(self.0.as_mut().get_mut(..size_of::<PRUDPV0Header>())?).ok()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn connection_signature(&self) -> Option<&[u8; 4]> {
|
||||
let offset = size_of::<PRUDPV0Header>();
|
||||
Some(self.0.as_ref().get(offset..offset + 4)?.try_into().ok()?)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn connection_signature_mut(&mut self) -> Option<&mut [u8; 4]>
|
||||
where
|
||||
T: AsMut<[u8]>,
|
||||
{
|
||||
let offset = size_of::<PRUDPV0Header>();
|
||||
Some(
|
||||
self.0
|
||||
.as_mut()
|
||||
.get_mut(offset..offset + 4)?
|
||||
.try_into()
|
||||
.ok()?,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_payload_offset(&self) -> Option<usize> {
|
||||
Some(size_of::<PRUDPV0Header>() + self.get_packet_specific_size()?)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn payload(&self) -> Option<&[u8]> {
|
||||
self.0
|
||||
.as_ref()
|
||||
.get(self.get_payload_offset()?..(self.0.as_ref().len().saturating_sub(1)))
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn payload_mut(&mut self) -> Option<&mut [u8]>
|
||||
where
|
||||
T: AsMut<[u8]>,
|
||||
{
|
||||
let start_offset = self.get_payload_offset()?;
|
||||
let end_offset = self.0.as_ref().len().saturating_sub(1);
|
||||
self.0.as_mut().get_mut(start_offset..end_offset)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn checksummed_data(&self) -> Option<&[u8]> {
|
||||
self.0
|
||||
.as_ref()
|
||||
.get(..self.0.as_ref().len().saturating_sub(1))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn checksum(&self) -> Option<u8> {
|
||||
self.0.as_ref().last().copied()
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn checksum_mut(&mut self) -> Option<&mut u8>
|
||||
where
|
||||
T: AsMut<[u8]>,
|
||||
{
|
||||
self.0.as_mut().last_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn check_checksum(&self, crypto: &impl Crypto) -> bool {
|
||||
let Some(data) = self.checksummed_data() else {
|
||||
return false;
|
||||
};
|
||||
let Some(checksum) = self.checksum() else {
|
||||
return false;
|
||||
};
|
||||
checksum == crypto.calculate_checksum(data)
|
||||
}
|
||||
|
||||
pub fn new(data: T) -> Self {
|
||||
Self(data)
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_SIGNAT: [u8; 4] = [0x12, 0x34, 0x56, 0x78];
|
||||
#[inline(always)]
|
||||
const fn get_size_offset(tf: TypesFlags) -> usize {
|
||||
size_of::<PRUDPV0Header>()
|
||||
+ (if tf.get_types() & (SYN | CONNECT) != 0 {
|
||||
4
|
||||
} else if tf.get_types() & DATA != 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
})
|
||||
}
|
||||
#[inline(always)]
|
||||
const fn get_type_specific_size(tf: TypesFlags) -> usize {
|
||||
if tf.get_types() & (SYN | CONNECT) != 0 {
|
||||
4
|
||||
} else if tf.get_types() & DATA != 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
const fn get_types_flags_size_from_types_flags(tf: TypesFlags) -> usize {
|
||||
get_type_specific_size(tf) + (if tf.get_flags() & HAS_SIZE != 0 { 2 } else { 0 })
|
||||
}
|
||||
#[inline(always)]
|
||||
pub const fn precalc_size(tf: TypesFlags, payload_size: usize) -> usize {
|
||||
size_of::<PRUDPV0Header>() + get_types_flags_size_from_types_flags(tf) + payload_size + 1
|
||||
}
|
||||
pub fn new_syn_packet(
|
||||
flags: u16,
|
||||
source: VirtualPort,
|
||||
destination: VirtualPort,
|
||||
signat: [u8; 4],
|
||||
crypto: &impl Crypto,
|
||||
) -> Vec<u8> {
|
||||
let type_flags = TypesFlags::default().types(SYN).flags(flags);
|
||||
|
||||
let vec = vec![0; precalc_size(type_flags, 0)];
|
||||
let mut packet = PRUDPV0Packet::new(vec);
|
||||
let header = packet.header_mut().expect("packet malformed in creation");
|
||||
|
||||
*header = PRUDPV0Header {
|
||||
destination,
|
||||
source,
|
||||
packet_signature: DEFAULT_SIGNAT,
|
||||
sequence_id: 0,
|
||||
session_id: 0,
|
||||
type_flags,
|
||||
};
|
||||
*packet
|
||||
.connection_signature_mut()
|
||||
.expect("packet malformed in creation") = signat;
|
||||
|
||||
*packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum(
|
||||
packet
|
||||
.checksummed_data()
|
||||
.expect("packet malformed in creation"),
|
||||
);
|
||||
|
||||
packet.0
|
||||
}
|
||||
256
prudpv0/src/server.rs
Normal file
256
prudpv0/src/server.rs
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
hash::Hash,
|
||||
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||
sync::{
|
||||
Arc, LazyLock,
|
||||
atomic::{AtomicBool, AtomicU32},
|
||||
},
|
||||
};
|
||||
|
||||
use log::{error, info, warn};
|
||||
use proxy_common::{ProxyStartupParam, new_backend_connection};
|
||||
use rnex_core::{
|
||||
executables::common::{OWN_IP_PRIVATE, SERVER_PORT},
|
||||
prudp::{
|
||||
socket_addr::PRUDPSockAddr,
|
||||
types_flags::{
|
||||
TypesFlags,
|
||||
flags::{ACK, HAS_SIZE, NEED_ACK},
|
||||
types::{CONNECT, DATA, SYN},
|
||||
},
|
||||
virtual_port::VirtualPort,
|
||||
},
|
||||
rnex_proxy_common::ConnectionInitData,
|
||||
util::{SendingBufferConnection, SplittableBufferConnection},
|
||||
};
|
||||
use tokio::{
|
||||
net::{TcpSocket, UdpSocket},
|
||||
spawn,
|
||||
sync::{Mutex, RwLock},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
crypto::{Crypto, CryptoInstance},
|
||||
packet::{PRUDPV0Header, PRUDPV0Packet, new_syn_packet, precalc_size},
|
||||
};
|
||||
|
||||
pub struct InternalConnection<C: CryptoInstance> {
|
||||
last_action: Instant,
|
||||
crypto_instance: C,
|
||||
server_packet_counter: u16,
|
||||
client_packet_counter: u16,
|
||||
unacknowledged_packets: HashMap<u16, Arc<Vec<u8>>>,
|
||||
}
|
||||
pub struct Connection<C: CryptoInstance> {
|
||||
alive: AtomicBool,
|
||||
session_id: u8,
|
||||
target: SendingBufferConnection,
|
||||
self_signat: [u8; 4],
|
||||
remote_signat: [u8; 4],
|
||||
addr: PRUDPSockAddr,
|
||||
inner: Mutex<InternalConnection<C>>,
|
||||
}
|
||||
|
||||
impl<C: CryptoInstance> InternalConnection<C> {
|
||||
fn next_server_count(&mut self) -> u16 {
|
||||
let prev_val = self.server_packet_counter;
|
||||
let (val, _) = self.server_packet_counter.overflowing_add(1);
|
||||
self.server_packet_counter = val;
|
||||
|
||||
prev_val
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Server<C: Crypto> {
|
||||
param: ProxyStartupParam,
|
||||
socket: UdpSocket,
|
||||
crypto: C,
|
||||
connections: RwLock<HashMap<PRUDPSockAddr, Arc<Connection<C::Instance>>>>,
|
||||
}
|
||||
|
||||
impl<C: Crypto> Server<C> {
|
||||
async fn send_data_packet(&self, conn: &Connection<C::Instance>, data: &[u8]) {
|
||||
let type_flags = TypesFlags::default().types(DATA).flags(HAS_SIZE | NEED_ACK);
|
||||
let vec = vec![0; precalc_size(type_flags, data.len())];
|
||||
let mut packet = PRUDPV0Packet::new(vec);
|
||||
|
||||
let payload = packet.payload_mut().expect("packet malformed in creation");
|
||||
payload.copy_from_slice(data);
|
||||
|
||||
let mut inner = conn.inner.lock().await;
|
||||
inner.crypto_instance.encrypt_outgoing(payload);
|
||||
let packet_signat = inner.crypto_instance.generate_signature(payload);
|
||||
let seq = inner.next_server_count();
|
||||
|
||||
*packet.header_mut().expect("packet malformed in creation") = PRUDPV0Header {
|
||||
source: self.param.virtual_port,
|
||||
destination: conn.addr.virtual_port,
|
||||
type_flags,
|
||||
session_id: conn.session_id,
|
||||
packet_signature: packet_signat,
|
||||
sequence_id: seq,
|
||||
};
|
||||
/* we leave the sequence id as is for now as it defaults to 0 */
|
||||
|
||||
*packet.checksum_mut().expect("packet malformed in creation") =
|
||||
self.crypto.calculate_checksum(
|
||||
packet
|
||||
.checksummed_data()
|
||||
.expect("packet malformed in creation"),
|
||||
);
|
||||
|
||||
let packet_raw = packet.0;
|
||||
|
||||
let packet = Arc::new(packet_raw);
|
||||
|
||||
let packet_ref = Arc::downgrade(&packet);
|
||||
|
||||
inner.unacknowledged_packets.insert(seq, packet);
|
||||
|
||||
drop(inner);
|
||||
|
||||
spawn(async move {
|
||||
for n in 0..5 {
|
||||
let Some(data) = packet_ref.upgrade() else {
|
||||
return;
|
||||
};
|
||||
info!("send attempt {}", n);
|
||||
}
|
||||
});
|
||||
}
|
||||
async fn connection_thread(
|
||||
self: Arc<Self>,
|
||||
conn: Arc<Connection<C::Instance>>,
|
||||
mut recv: SplittableBufferConnection,
|
||||
) {
|
||||
while let Some(data) = recv.recv().await {}
|
||||
}
|
||||
async fn timeout_thread(self: Arc<Self>, conn: Arc<Connection<C::Instance>>) {
|
||||
loop {
|
||||
conn
|
||||
}
|
||||
}
|
||||
async fn handle_syn(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: PRUDPSockAddr) {
|
||||
info!("got syn");
|
||||
let header = packet.header().unwrap();
|
||||
|
||||
let signat = addr.calculate_connection_signature();
|
||||
let signat = [signat[0], signat[1], signat[2], signat[3]];
|
||||
|
||||
let packet = new_syn_packet(ACK, header.destination, header.source, signat, &self.crypto);
|
||||
self.socket.send_to(&packet, addr.regular_socket_addr).await;
|
||||
}
|
||||
async fn handle_connect(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: PRUDPSockAddr) {
|
||||
let conn = self.connections.write().await;
|
||||
let Some(data) = packet.payload() else {
|
||||
warn!("malformed packet from: {:?}", addr.regular_socket_addr);
|
||||
return;
|
||||
};
|
||||
let Some(self_signat) = packet.connection_signature().copied() else {
|
||||
warn!(
|
||||
"malformed packet(unable to find connection signature) from: {:?}",
|
||||
addr
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let ci = self.crypto.instantiate(data);
|
||||
|
||||
let pid = ci.get_user_id();
|
||||
let conn = new_backend_connection(&self.param, addr, pid).await;
|
||||
let Some(conn) = conn else {
|
||||
error!("unable to connect to backend");
|
||||
return;
|
||||
};
|
||||
|
||||
let remote_signat = addr.calculate_connection_signature();
|
||||
let remote_signat = [
|
||||
remote_signat[0],
|
||||
remote_signat[1],
|
||||
remote_signat[2],
|
||||
remote_signat[3],
|
||||
];
|
||||
|
||||
let header = packet.header().expect("header should be validated by now");
|
||||
|
||||
let conn = Arc::new(Connection {
|
||||
target: conn.duplicate_sender(),
|
||||
remote_signat,
|
||||
self_signat,
|
||||
addr,
|
||||
session_id: header.session_id,
|
||||
alive: AtomicBool::new(true),
|
||||
inner: Mutex::new(InternalConnection {
|
||||
last_action: Instant::now(),
|
||||
crypto_instance: ci,
|
||||
client_packet_counter: 2,
|
||||
server_packet_counter: 1,
|
||||
unacknowledged_packets: HashMap::new(),
|
||||
}),
|
||||
});
|
||||
}
|
||||
async fn process_packet<'a>(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: SocketAddrV4) {
|
||||
if !packet.check_checksum(&self.crypto) {
|
||||
warn!("invalid checksum from: {}", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(header) = packet.header() else {
|
||||
warn!("malformatted packet from: {}", addr);
|
||||
return;
|
||||
};
|
||||
|
||||
let addr = PRUDPSockAddr::new(addr, header.source);
|
||||
println!("{:?}", header);
|
||||
match header.type_flags.get_types() {
|
||||
SYN => {
|
||||
self.handle_syn(packet, addr).await;
|
||||
}
|
||||
CONNECT => {
|
||||
self.handle_connect(packet, addr).await;
|
||||
}
|
||||
v => {
|
||||
println!("unimplemented packed type: {}", v);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn run_task(self: Arc<Self>) {
|
||||
loop {
|
||||
let mut vec: Vec<u8> = vec![];
|
||||
let addr = match self.socket.recv_buf_from(&mut vec).await {
|
||||
Err(e) => {
|
||||
error!("unable to recv: {}", e);
|
||||
break;
|
||||
}
|
||||
Ok(v) => {
|
||||
assert_eq!(vec.len(), v.0);
|
||||
v.1
|
||||
}
|
||||
};
|
||||
let this = self.clone();
|
||||
tokio::spawn(async move {
|
||||
let data = vec;
|
||||
let packet = PRUDPV0Packet::new(&data[..]);
|
||||
|
||||
let SocketAddr::V4(addr) = addr else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
this.process_packet(packet, addr).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
pub async fn new(param: ProxyStartupParam) -> Self {
|
||||
let socket = UdpSocket::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
||||
.await
|
||||
.expect("unable to bind socket");
|
||||
Self {
|
||||
socket,
|
||||
crypto: C::new(),
|
||||
connections: RwLock::new(HashMap::new()),
|
||||
param,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue