This commit is contained in:
Maple 2026-01-20 20:26:44 +01:00
commit fc94f655b2
43 changed files with 1957 additions and 694 deletions

View file

@ -1,18 +1,17 @@
use once_cell::sync::Lazy;
use std::env;
use std::net::SocketAddrV4;
use once_cell::sync::Lazy;
pub static EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(||{
pub static EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(|| {
env::var("EDGE_NODE_HOLDER")
.ok()
.and_then(|s| s.parse().ok())
.expect("EDGE_NODE_HOLDER not set")
});
pub static FORWARD_DESTINATION: Lazy<SocketAddrV4> =
Lazy::new(||
env::var("FORWARD_DESTINATION")
.ok()
.and_then(|s| s.parse().ok())
.expect("FORWARD_DESTINATION not set")
);
pub static FORWARD_DESTINATION: Lazy<SocketAddrV4> = Lazy::new(|| {
env::var("FORWARD_DESTINATION")
.ok()
.and_then(|s| s.parse().ok())
.expect("FORWARD_DESTINATION not set")
});

View file

@ -1,15 +1,5 @@
use rnex_core::reggie::UnitPacketRead;
use rnex_core::reggie::UnitPacketWrite;
use rnex_core::rmc::structures::RmcSerialize;
use std::net::SocketAddrV4;
use std::sync::Arc;
use std::time::Duration;
use log::error;
use tokio::net::TcpStream;
use tokio::task;
use tokio::time::sleep;
use prudpv1::executables::common::{FORWARD_DESTINATION, EDGE_NODE_HOLDER};
use prudpv1::executables::common::{EDGE_NODE_HOLDER, FORWARD_DESTINATION};
use prudpv1::prudp::router::Router;
use prudpv1::prudp::unsecure::Unsecure;
use rnex_core::common::setup;
@ -17,32 +7,46 @@ use rnex_core::executables::common::{OWN_IP_PRIVATE, OWN_IP_PUBLIC, SERVER_PORT}
use rnex_core::prudp::virtual_port::VirtualPort;
use rnex_core::reggie::EdgeNodeHolderConnectOption::Register;
use rnex_core::reggie::RemoteEdgeNodeHolder;
use rnex_core::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
use rnex_core::reggie::UnitPacketRead;
use rnex_core::reggie::UnitPacketWrite;
use rnex_core::rmc::protocols::{OnlyRemote, new_rmc_gateway_connection};
use rnex_core::rmc::structures::RmcSerialize;
use rnex_core::rnex_proxy_common::ConnectionInitData;
use rnex_core::util::SplittableBufferConnection;
use std::net::SocketAddrV4;
use std::sync::Arc;
use std::time::Duration;
use tokio::net::TcpStream;
use tokio::task;
use tokio::time::sleep;
#[tokio::main]
async fn main() {
setup();
let conn = tokio::net::TcpStream::connect(&*EDGE_NODE_HOLDER).await.unwrap();
let conn = tokio::net::TcpStream::connect(&*EDGE_NODE_HOLDER)
.await
.unwrap();
let conn: SplittableBufferConnection = conn.into();
conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data().unwrap()).await;
conn.send(
Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT))
.to_data()
.unwrap(),
)
.await;
let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r)));
let conn = new_rmc_gateway_connection(conn, |r| {
Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))
});
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
.await
.expect("unable to start router");
let mut socket_secure = router_secure
.add_socket(VirtualPort::new(1, 10), Unsecure(
"6f599f81"
))
.add_socket(VirtualPort::new(1, 10), Unsecure("6f599f81"))
.await
.expect("unable to add socket");
@ -55,8 +59,7 @@ async fn main() {
};
task::spawn(async move {
let mut stream
= match TcpStream::connect(*FORWARD_DESTINATION).await {
let mut stream = match TcpStream::connect(*FORWARD_DESTINATION).await {
Ok(v) => v,
Err(e) => {
error!("unable to connect: {}", e);
@ -64,10 +67,17 @@ async fn main() {
}
};
if let Err(e) = stream.send_buffer(&ConnectionInitData{
prudpsock_addr: conn.socket_addr,
pid: conn.user_id
}.to_data().unwrap()).await{
if let Err(e) = stream
.send_buffer(
&ConnectionInitData {
prudpsock_addr: conn.socket_addr,
pid: conn.user_id,
}
.to_data()
.unwrap(),
)
.await
{
error!("error connecting to backend: {}", e);
return;
};
@ -92,7 +102,7 @@ async fn main() {
return;
}
};
if conn.send(data).await == None{
return;
}
@ -105,4 +115,4 @@ async fn main() {
});
}
drop(conn);
}
}

View file

@ -3,21 +3,24 @@
// force the compiler to shut up here
#![allow(unused_parens)]
use crate::prudp::packet::PacketOption::{
ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions,
};
use bytemuck::{Pod, Zeroable};
use hmac::{Hmac, Mac};
use log::{error, warn};
use md5::{Digest, Md5};
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::prudp::types_flags::TypesFlags;
use rnex_core::prudp::types_flags::flags::ACK;
use rnex_core::prudp::virtual_port::VirtualPort;
use std::fmt::{Debug, Formatter};
use std::io;
use std::io::{Cursor, Read, Seek, Write};
use std::net::SocketAddrV4;
use bytemuck::{Pod, Zeroable};
use hmac::{Hmac, Mac};
use log::{error, warn};
use md5::{Md5, Digest};
use thiserror::Error;
use v_byte_helpers::{SwapEndian};
use v_byte_helpers::SwapEndian;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use crate::prudp::packet::flags::ACK;
use crate::prudp::packet::PacketOption::{ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions};
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::prudp::virtual_port::VirtualPort;
type Md5Hmac = Hmac<Md5>;
@ -32,73 +35,11 @@ pub enum Error {
#[error("invalid option id {0}")]
InvalidOptionId(u8),
#[error("option size {size} doesnt match expected option for given option id {id}")]
InvalidOptionSize {
id: u8,
size: u8,
},
InvalidOptionSize { id: u8, size: u8 },
}
pub type Result<T> = std::result::Result<T, Error>;
#[repr(transparent)]
#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default, Eq, PartialEq)]
pub struct TypesFlags(u16);
impl TypesFlags {
#[inline]
pub const fn get_types(self) -> u8 {
(self.0 & 0x000F) as u8
}
#[inline]
pub const fn get_flags(self) -> u16 {
(self.0 & 0xFFF0) >> 4
}
#[inline]
pub const fn types(self, val: u8) -> Self {
Self((self.0 & 0xFFF0) | (val as u16 & 0x000F))
}
#[inline]
pub const fn flags(self, val: u16) -> Self {
Self((self.0 & 0x000F) | ((val << 4) & 0xFFF0))
}
#[inline]
pub const fn set_flag(&mut self, val: u16){
self.0 |= (val & 0xFFF) << 4;
}
#[inline]
pub const fn set_types(&mut self, val: u8){
self.0 |= val as u16 & 0x0F;
}
}
pub mod flags {
pub const ACK: u16 = 0x001;
pub const RELIABLE: u16 = 0x002;
pub const NEED_ACK: u16 = 0x004;
pub const HAS_SIZE: u16 = 0x008;
pub const MULTI_ACK: u16 = 0x200;
}
pub mod types {
pub const SYN: u8 = 0x0;
pub const CONNECT: u8 = 0x1;
pub const DATA: u8 = 0x2;
pub const DISCONNECT: u8 = 0x3;
pub const PING: u8 = 0x4;
/// no idea what user is supposed to mean
pub const USER: u8 = 0x5;
}
impl Debug for TypesFlags {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let stream_type = self.get_types();
let port_number = self.get_flags();
write!(f, "TypesFlags{{ types: {}, flags: {} }}", stream_type, port_number)
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)]
pub struct PRUDPV1Header {
@ -116,7 +57,7 @@ pub struct PRUDPV1Header {
impl Default for PRUDPV1Header {
fn default() -> Self {
Self{
Self {
magic: [0xEA, 0xD0],
version: 1,
session_id: 0,
@ -126,32 +67,30 @@ impl Default for PRUDPV1Header {
destination_port: VirtualPort(0),
types_and_flags: TypesFlags(0),
packet_specific_size: 0,
substream_id: 0
substream_id: 0,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PacketOption{
pub enum PacketOption {
SupportedFunctions(u32),
ConnectionSignature([u8; 16]),
FragmentId(u8),
InitialSequenceId(u16),
MaximumSubstreamId(u8)
MaximumSubstreamId(u8),
}
impl PacketOption{
fn from(option_id: OptionId, option_data: &[u8]) -> io::Result<Self>{
impl PacketOption {
fn from(option_id: OptionId, option_data: &[u8]) -> io::Result<Self> {
let mut data_cursor = Cursor::new(option_data);
let val = match option_id.into(){
let val = match option_id.into() {
0 => SupportedFunctions(data_cursor.read_struct(IS_BIG_ENDIAN)?),
1 => ConnectionSignature(data_cursor.read_struct(IS_BIG_ENDIAN)?),
2 => FragmentId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
3 => InitialSequenceId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
4 => MaximumSubstreamId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
_ => unreachable!()
_ => unreachable!(),
};
Ok(val)
@ -212,7 +151,7 @@ impl OptionId {
// Invariant is upheld because we only create the object if it doesn't violate the invariant
match val {
0 | 1 | 2 | 3 | 4 => Ok(Self(val)),
_ => Err(Error::InvalidOptionId(val))
_ => Err(Error::InvalidOptionId(val)),
}
}
@ -223,7 +162,7 @@ impl OptionId {
2 => 1,
3 => 2,
4 => 1,
_ => unreachable!()
_ => unreachable!(),
}
}
}
@ -238,8 +177,7 @@ impl PRUDPV1Packet {
pub fn new(reader: &mut (impl Read + Seek)) -> Result<Self> {
let header: PRUDPV1Header = reader.read_struct(IS_BIG_ENDIAN)?;
if header.magic[0] != 0xEA ||
header.magic[1] != 0xD0 {
if header.magic[0] != 0xEA || header.magic[1] != 0xD0 {
return Err(Error::InvalidMagic(u16::from_be_bytes(header.magic)));
}
@ -247,31 +185,31 @@ impl PRUDPV1Packet {
return Err(Error::InvalidVersion(header.version));
}
let packet_signature: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?;
//let packet_signature: [u8; 16] = [0; 16];
assert_eq!(reader.stream_position().ok(), Some(14 + 16));
let mut packet_specific_buffer = vec![0u8; header.packet_specific_size as usize];
reader.read_exact(&mut packet_specific_buffer)?;
//no clue whats up with options but they are broken
let mut packet_specific_data_cursor = Cursor::new(&packet_specific_buffer);
let mut options = Vec::new();
loop {
let Ok(option_id): io::Result<u8> = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else {
break
let Ok(option_id): io::Result<u8> =
packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN)
else {
break;
};
let Ok(value_size): io::Result<u8> = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else {
break
let Ok(value_size): io::Result<u8> =
packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN)
else {
break;
};
if value_size == 0 {
@ -291,20 +229,21 @@ impl PRUDPV1Packet {
}
let mut option_data = vec![0u8; value_size as usize];
if packet_specific_data_cursor.read_exact(&mut option_data[..]).is_err() {
if packet_specific_data_cursor
.read_exact(&mut option_data[..])
.is_err()
{
error!("unable to read options");
break;
}
options.push(PacketOption::from(option_id, &option_data)?);
}
let mut payload = vec![0u8; header.payload_size as usize];
reader.read_exact(&mut payload)?;
Ok(Self {
header,
packet_signature,
@ -313,22 +252,21 @@ impl PRUDPV1Packet {
})
}
pub fn base_acknowledgement_packet(&self) -> Self{
pub fn base_acknowledgement_packet(&self) -> Self {
let base = self.base_response_packet();
let mut flags = self.header.types_and_flags.flags(0);
flags.set_flag(ACK);
let options = self.options
let options = self
.options
.iter()
.filter(|o| matches!(o, FragmentId(_)))
.cloned()
.collect();
Self{
Self {
header: PRUDPV1Header {
types_and_flags: flags,
sequence_id: self.header.sequence_id,
@ -348,17 +286,24 @@ impl PRUDPV1Packet {
}
}
fn generate_options_bytes(&self) -> Vec<u8>{
fn generate_options_bytes(&self) -> Vec<u8> {
let mut vec = Vec::new();
for option in &self.options{
option.write_to_stream(&mut vec).expect("vec should always automatically be able to extend");
for option in &self.options {
option
.write_to_stream(&mut vec)
.expect("vec should always automatically be able to extend");
}
vec
}
pub fn calculate_signature_value(&self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>) -> [u8; 16]{
pub fn calculate_signature_value(
&self,
access_key: &str,
session_key: Option<[u8; 32]>,
connection_signature: Option<[u8; 16]>,
) -> [u8; 16] {
let access_key_bytes = access_key.as_bytes();
let access_key_sum: u32 = access_key_bytes.iter().map(|v| *v as u32).sum();
let access_key_sum_bytes: [u8; 4] = access_key_sum.to_le_bytes();
@ -374,32 +319,46 @@ impl PRUDPV1Packet {
let mut hmac = Md5Hmac::new_from_slice(&key).expect("fuck");
hmac.write(&header_data).expect("error during hmac calculation");
hmac.write(&header_data)
.expect("error during hmac calculation");
if let Some(session_key) = session_key {
hmac.write(&session_key).expect("error during hmac calculation");
hmac.write(&session_key)
.expect("error during hmac calculation");
}
hmac.write(&access_key_sum_bytes).expect("error during hmac calculation");
hmac.write(&access_key_sum_bytes)
.expect("error during hmac calculation");
if let Some(connection_signature) = connection_signature {
hmac.write(&connection_signature).expect("error during hmac calculation");
hmac.write(&connection_signature)
.expect("error during hmac calculation");
}
hmac.write(&option_bytes).expect("error during hmac calculation");
hmac.write(&option_bytes)
.expect("error during hmac calculation");
hmac.write_all(&self.payload).expect("error during hmac calculation");
hmac.write_all(&self.payload)
.expect("error during hmac calculation");
hmac.finalize().into_bytes()[0..16].try_into().expect("invalid hmac size")
hmac.finalize().into_bytes()[0..16]
.try_into()
.expect("invalid hmac size")
}
pub fn calculate_and_assign_signature(&mut self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>){
self.packet_signature = self.calculate_signature_value(access_key, session_key, connection_signature);
pub fn calculate_and_assign_signature(
&mut self,
access_key: &str,
session_key: Option<[u8; 32]>,
connection_signature: Option<[u8; 16]>,
) {
self.packet_signature =
self.calculate_signature_value(access_key, session_key, connection_signature);
}
pub fn set_sizes(&mut self){
pub fn set_sizes(&mut self) {
self.header.packet_specific_size = self.options.iter().map(|o| o.write_size()).sum();
self.header.payload_size = self.payload.len() as u16;
}
pub fn base_response_packet(&self) -> Self {
pub fn base_response_packet(&self) -> Self {
Self {
header: PRUDPV1Header {
magic: [0xEA, 0xD0],
@ -412,19 +371,18 @@ impl PRUDPV1Packet {
sequence_id: 0,
session_id: 0,
substream_id: 0,
},
packet_signature: [0; 16],
payload: Default::default(),
options: Default::default()
options: Default::default(),
}
}
pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()>{
pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()> {
writer.write_all(bytemuck::bytes_of(&self.header))?;
writer.write_all(&self.packet_signature)?;
for option in &self.options{
for option in &self.options {
option.write_to_stream(writer)?;
}
@ -436,20 +394,24 @@ impl PRUDPV1Packet {
#[cfg(test)]
mod test {
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::types::DATA;
use super::{OptionId, PacketOption, PRUDPV1Header, TypesFlags};
use rnex_core::prudp::virtual_port::VirtualPort;
use super::{OptionId, PRUDPV1Header, PacketOption, TypesFlags};
use rnex_core::prudp::{
types_flags::{
flags::{NEED_ACK, RELIABLE},
types::DATA,
},
virtual_port::VirtualPort,
};
#[test]
fn size_test() {
assert_eq!(size_of::<PRUDPV1Header>(), 14);
}
#[test]
fn test_options(){
let packet_types = [0,1,2,3,4];
fn test_options() {
let packet_types = [0, 1, 2, 3, 4];
for p_type in packet_types{
for p_type in packet_types {
let option_id = OptionId::new(p_type).unwrap();
let buf = vec![0; option_id.option_type_size() as usize];
@ -463,12 +425,10 @@ mod test {
assert_eq!(write_buf.len() as u8, opt.write_size())
}
}
}
#[test]
fn header_read(){
fn header_read() {
let header = PRUDPV1Header {
version: 0,
destination_port: VirtualPort(0),
@ -478,8 +438,8 @@ mod test {
packet_specific_size: 0,
payload_size: 0,
sequence_id: 0,
magic: [0xEA,0xD0],
source_port: VirtualPort(0)
magic: [0xEA, 0xD0],
source_port: VirtualPort(0),
};
let bytes = bytemuck::bytes_of(&header);
@ -490,11 +450,11 @@ mod test {
}
#[test]
fn test_types_flags(){
fn test_types_flags() {
let types = TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE);
assert_ne!((types.0 >> 4) & NEED_ACK, 0);
assert_ne!((types.0 >> 4) & RELIABLE, 0);
assert_ne!((types.0 & 0xFF) as u8 & DATA, 0);
}
}
}

View file

@ -1,18 +1,19 @@
use std::io::Cursor;
use crate::prudp::packet::PRUDPV1Packet;
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance};
use hmac::digest::consts::U32;
use log::error;
use rc4::cipher::StreamCipherCoreWrapper;
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher};
use rc4::consts::U16;
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher};
use rnex_core::kerberos::{TicketInternalData, derive_key};
use rnex_core::nex::account::Account;
use rnex_core::prudp::encryption::EncryptionPair;
use rnex_core::rmc::structures::RmcSerialize;
use std::io::Cursor;
use typenum::U5;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use rnex_core::kerberos::{derive_key, TicketInternalData};
use rnex_core::nex::account::Account;
use crate::prudp::packet::PRUDPV1Packet;
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
use rnex_core::rmc::structures::RmcSerialize;
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)> {
let mut cursor = Cursor::new(data);
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
@ -20,7 +21,7 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
let ticket_data_size = ticket_data.len();
let ticket_data = &mut ticket_data[0..ticket_data_size-0x10];
let ticket_data = &mut ticket_data[0..ticket_data_size - 0x10];
let server_key = derive_key(act.pid, act.kerbros_password);
@ -29,7 +30,7 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
rc4.apply_keystream(ticket_data);
let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data){
let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data) {
Ok(v) => v,
Err(e) => {
error!("unable to read internal ticket data: {}", e);
@ -39,15 +40,15 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
// todo: add ticket expiration
let TicketInternalData{
let TicketInternalData {
session_key,
pid: ticket_source_pid,
issued_time
issued_time,
} = *ticket_data;
// todo: add checking if tickets are signed with a valid md5-hmac
let request_data_length = request_data.len();
let request_data = &mut request_data[0.. request_data_length - 0x10];
let request_data = &mut request_data[0..request_data_length - 0x10];
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U32>> =
Rc4::new_from_slice(&session_key).expect("unable to init rc4 keystream");
@ -58,53 +59,55 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
if pid != ticket_source_pid{
if pid != ticket_source_pid {
let ticket_created_on = issued_time.to_regular_time();
error!("someone tried to spoof their pid, ticket was created on: {}", ticket_created_on.to_rfc2822());
error!(
"someone tried to spoof their pid, ticket was created on: {}",
ticket_created_on.to_rfc2822()
);
return None;
}
let _cid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
let response_check: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
Some((session_key, pid, response_check))
}
type Rc4U32 = StreamCipherCoreWrapper<Rc4Core<U32>>;
pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec<EncryptionPair<Rc4<U32>>>{
pub fn generate_secure_encryption_pairs(
mut session_key: [u8; 32],
count: u8,
) -> Vec<EncryptionPair<Rc4<U32>>> {
let mut vec = Vec::with_capacity(count as usize);
vec.push(EncryptionPair{
vec.push(EncryptionPair {
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
});
for _ in 1..=count{
for _ in 1..=count {
let modifier = session_key.len() + 1;
let key_length = session_key.len();
for (position, val) in (&mut session_key[0..key_length/2]).iter_mut().enumerate(){
for (position, val) in (&mut session_key[0..key_length / 2]).iter_mut().enumerate() {
*val = val.wrapping_add((modifier - position) as u8);
}
vec.push(EncryptionPair{
vec.push(EncryptionPair {
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
});
}
vec
}
pub struct Secure(pub &'static str, pub Account);
pub struct SecureInstance {
access_key: &'static str,
session_key: [u8; 32],
@ -155,18 +158,17 @@ impl CryptoHandler for Secure {
}
}
impl CryptoHandlerConnectionInstance for SecureInstance {
type Encryption = Rc4<U5>;
fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) {
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
crypt_pair.recv.apply_keystream(data);
}
}
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) {
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
crypt_pair.send.apply_keystream(data);
}
}
@ -182,10 +184,14 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
fn sign_packet(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes();
packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature));
packet.calculate_and_assign_signature(
self.access_key,
Some(self.session_key),
Some(self.self_signature),
);
}
fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool {
true
}
}
}

View file

@ -1,47 +1,34 @@
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
use crate::prudp::packet::PacketOption::{
ConnectionSignature, FragmentId, MaximumSubstreamId, SupportedFunctions,
};
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, TypesFlags};
use rnex_core::prudp::virtual_port::VirtualPort;
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet};
use async_trait::async_trait;
use log::{info, warn};
use log::error;
use log::{info, warn};
use rc4::StreamCipher;
use v_byte_helpers::ReadExtensions;
use v_byte_helpers::little_endian::read_u16;
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::prudp::types_flags::TypesFlags;
use rnex_core::prudp::types_flags::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
use rnex_core::prudp::types_flags::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
use rnex_core::prudp::virtual_port::VirtualPort;
use std::collections::{BTreeMap, HashMap};
use std::io::Cursor;
use std::marker::PhantomData;
use std::ops::Deref;
use std::sync::{Arc, Weak};
use v_byte_helpers::ReadExtensions;
use v_byte_helpers::little_endian::read_u16;
use std::time::Duration;
use tokio::net::UdpSocket;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::Mutex;
use tokio::time::{sleep, Instant};
use tokio::sync::mpsc::{Receiver, Sender, channel};
use tokio::time::{Instant, sleep};
// due to the way this is designed crashing the router thread causes deadlock, sorry ;-;
// (maybe i will fix that some day)
/// PRUDP Socket for accepting connections to then send and recieve data from those clients
pub struct EncryptionPair<T: StreamCipher + Send> {
pub send: T,
pub recv: T,
}
impl<T: StreamCipher + Send> EncryptionPair<T> {
pub fn init_both<F: Fn() -> T>(func: F) -> Self {
Self {
recv: func(),
send: func(),
}
}
}
pub struct CommonConnection {
pub user_id: u32,
pub socket_addr: PRUDPSockAddr,
@ -61,7 +48,7 @@ struct InternalConnection<E: CryptoHandlerConnectionInstance> {
socket: Arc<UdpSocket>,
packet_queue: HashMap<u16, PRUDPV1Packet>,
last_packet_time: Instant,
unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)>
unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)>,
}
impl<E: CryptoHandlerConnectionInstance> Deref for InternalConnection<E> {
@ -82,17 +69,17 @@ impl<E: CryptoHandlerConnectionInstance> InternalConnection<E> {
}
/// Sends a raw packet to a given client on the connection
///
/// a raw packet is one which does not get processed any further(other than to send it
///
/// a raw packet is one which does not get processed any further(other than to send it
/// off without buffering or anything),
/// as such you need to make sure that
/// as such you need to make sure that
/// the sizes are set correctly and so on
#[inline]
async fn send_raw_packet(&self, prudp_packet: &PRUDPV1Packet) {
send_raw_prudp_to_sockaddr(&self.socket, self.socket_addr, prudp_packet).await;
}
async fn delete_connection(&self){
async fn delete_connection(&self) {
let Some(conns) = self.connections.upgrade() else {
// this is fine as it implies the server has already quit, thus meaning that we dont
// have to remove ourselves from the server
@ -187,8 +174,6 @@ pub(super) trait AnyInternalConnection:
async fn close_connection(&mut self);
}
#[async_trait]
impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConnection<T> {
async fn send_data_packet(&mut self, data: Vec<u8>) {
@ -219,7 +204,6 @@ impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConne
self.unacknowleged_packets.push((Instant::now(), packet));
}
async fn close_connection(&mut self) {
// jon confirmed that this should be a safe way to dc a client
@ -250,7 +234,11 @@ impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConne
}
}
async fn send_raw_prudp_to_sockaddr(udp_socket: &UdpSocket, dest: PRUDPSockAddr, packet: &PRUDPV1Packet){
async fn send_raw_prudp_to_sockaddr(
udp_socket: &UdpSocket,
dest: PRUDPSockAddr,
packet: &PRUDPV1Packet,
) {
let mut vec = Vec::new();
packet
@ -281,7 +269,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
}
/// sends a raw packet to a specific prudp socket address
///
///
/// a raw packet is a packet is a packet which wont get processed any further,
/// sizes signatures etc need to be set before using this function
async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, packet: &PRUDPV1Packet) {
@ -353,13 +341,15 @@ impl<T: CryptoHandler> InternalSocket<T> {
conn.close_connection().await;
}
for (send_time, packet) in &conn.unacknowleged_packets{
if *send_time < (Instant::now() - Duration::from_millis(3000)){
warn!("failed to resend packet 5 times and never got response, destroying connection");
for (send_time, packet) in &conn.unacknowleged_packets {
if *send_time < (Instant::now() - Duration::from_millis(3000)) {
warn!(
"failed to resend packet 5 times and never got response, destroying connection"
);
conn.close_connection().await;
break;
}
if *send_time < (Instant::now() - Duration::from_millis(500)){
if *send_time < (Instant::now() - Duration::from_millis(500)) {
info!("unacknowledged packet sat arround for more than 500 ms, resending");
conn.send_raw_packet(packet).await;
}
@ -399,7 +389,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
packet_queue: Default::default(),
last_packet_time: Instant::now(),
unacknowleged_packets: Vec::new(),
supported_function_version
supported_function_version,
};
let internal = Arc::new(Mutex::new(internal));
@ -487,7 +477,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
SupportedFunctions(funcs) => {
functions = *funcs & 0xFF;
response.options.push(SupportedFunctions(*funcs & 0xFF));
},
}
_ => { /* ? */ }
}
}
@ -610,7 +600,6 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
if (packet.header.types_and_flags.get_flags() & ACK) != 0 {
info!("got ack");
if packet.header.types_and_flags.get_types() == SYN
|| packet.header.types_and_flags.get_types() == CONNECT
{
@ -645,9 +634,8 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
// remove the packet whose sequence id matches the ack packet
// or in other words keep all of those which dont match the sequence id
conn.unacknowleged_packets.retain_mut(|v| {
packet.header.sequence_id != v.1.header.sequence_id
});
conn.unacknowleged_packets
.retain_mut(|v| packet.header.sequence_id != v.1.header.sequence_id);
} else {
error!("non connection acknowledgement packet on nonexistent connection...")
}
@ -659,26 +647,23 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
if let Some(conn) = self.get_connection(address).await {
let mut conn = conn.lock().await;
if conn.supported_function_version == 1{
if conn.supported_function_version == 1 {
let mut collected_ids: Vec<u16> = Vec::new();
let mut cursor = Cursor::new(&packet.payload);
while let Ok(v) = read_u16(&mut cursor){
while let Ok(v) = read_u16(&mut cursor) {
collected_ids.push(v);
}
conn.unacknowleged_packets.retain_mut(|(_, up)| {
!(
collected_ids.iter().any(|id| up.header.sequence_id == *id) ||
up.header.sequence_id <= packet.header.sequence_id
)
!(collected_ids.iter().any(|id| up.header.sequence_id == *id)
|| up.header.sequence_id <= packet.header.sequence_id)
});
} else {
let mut collected_ids: Vec<u16> = Vec::new();
let mut cursor = Cursor::new(&packet.payload);
let Ok(_substream_id): Result<u8, _> = cursor.read_le_struct() else{
let Ok(_substream_id): Result<u8, _> = cursor.read_le_struct() else {
error!("invalid data whilest reading new version agregate acknowledgement");
return;
};
@ -690,19 +675,20 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
error!("invalid data whilest reading new version agregate acknowledgement");
return;
};
for _ in 0..additional_sequence_ids{
let Ok(additional_sequence_id): Result<u16, _> = cursor.read_le_struct() else {
error!("invalid data whilest reading new version agregate acknowledgement");
for _ in 0..additional_sequence_ids {
let Ok(additional_sequence_id): Result<u16, _> = cursor.read_le_struct()
else {
error!(
"invalid data whilest reading new version agregate acknowledgement"
);
return;
};
collected_ids.push(additional_sequence_id);
}
conn.unacknowleged_packets.retain_mut(|(_, up)| {
!(
collected_ids.iter().any(|id| up.header.sequence_id == *id) ||
up.header.sequence_id <= sequence_id
)
!(collected_ids.iter().any(|id| up.header.sequence_id == *id)
|| up.header.sequence_id <= sequence_id)
});
}
} else {

View file

@ -1,13 +1,12 @@
use crate::prudp::packet::PRUDPV1Packet;
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance};
use once_cell::sync::Lazy;
use rc4::{Key, KeyInit, Rc4, StreamCipher};
use rnex_core::prudp::encryption::{DEFAULT_KEY, EncryptionPair};
use typenum::U5;
use crate::prudp::packet::PRUDPV1Packet;
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
pub struct Unsecure(pub &'static str);
pub struct UnsecureInstance {
key: &'static str,
streams: Vec<EncryptionPair<Rc4<U5>>>,
@ -18,7 +17,6 @@ pub struct UnsecureInstance {
// my hand was forced to use lazy so that we can guarantee this code
// only runs once and so that i can put it here as a "constant" (for performance and readability)
// since for some reason rust crypto doesn't have any const time key initialization
static DEFAULT_KEY: Lazy<Key<U5>> = Lazy::new(|| Key::from(*b"CD&ML"));
impl CryptoHandler for Unsecure {
type CryptoConnectionInstance = UnsecureInstance;
@ -53,13 +51,13 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
type Encryption = Rc4<U5>;
fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) {
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
crypt_pair.recv.apply_keystream(data);
}
}
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) {
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
crypt_pair.send.apply_keystream(data);
}
}
@ -81,4 +79,4 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool {
true
}
}
}