updates
This commit is contained in:
parent
fc94f655b2
commit
1b802ff33f
15 changed files with 379 additions and 74 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -541,6 +541,7 @@ name = "proxy"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"proxy-common",
|
||||||
"prudpv0",
|
"prudpv0",
|
||||||
"prudpv1",
|
"prudpv1",
|
||||||
"rnex-core",
|
"rnex-core",
|
||||||
|
|
@ -551,6 +552,7 @@ dependencies = [
|
||||||
name = "proxy-common"
|
name = "proxy-common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log",
|
||||||
"rnex-core",
|
"rnex-core",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,4 @@ edition = "2024"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
||||||
tokio = { version = "1.47.0", features = ["full"] }
|
tokio = { version = "1.47.0", features = ["full"] }
|
||||||
|
log = "0.4.25"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use log::{error, info};
|
||||||
use rnex_core::{
|
use rnex_core::{
|
||||||
executables::common::{OWN_IP_PUBLIC, try_get_ip},
|
executables::common::{OWN_IP_PUBLIC, try_get_ip},
|
||||||
prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort},
|
prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort},
|
||||||
|
|
@ -87,8 +88,8 @@ impl ProxyStartupParam {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
forward_destination: try_get_env("EDGE_NODE_HOLDER")?,
|
forward_destination: try_get_env("FORWARD_DESTINATION")?,
|
||||||
edge_node_holder: try_get_env("FORWARD_DESTINATION")?,
|
edge_node_holder: try_get_env("EDGE_NODE_HOLDER")?,
|
||||||
self_private,
|
self_private,
|
||||||
self_public,
|
self_public,
|
||||||
virtual_port: match prox_ty {
|
virtual_port: match prox_ty {
|
||||||
|
|
@ -174,9 +175,11 @@ pub async fn new_backend_connection(
|
||||||
addr: PRUDPSockAddr,
|
addr: PRUDPSockAddr,
|
||||||
pid: u32,
|
pid: u32,
|
||||||
) -> Option<SplittableBufferConnection> {
|
) -> Option<SplittableBufferConnection> {
|
||||||
|
info!("attempting to connect to: {}", param.forward_destination);
|
||||||
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
error!("unable to establish connection to backend: {}", e);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -192,6 +195,7 @@ pub async fn new_backend_connection(
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
error!("unable to send establishment data to backend: {}", e);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ edition = "2024"
|
||||||
tokio = { version = "1.47.0", features = ["full"] }
|
tokio = { version = "1.47.0", features = ["full"] }
|
||||||
prudpv0 = { path = "../prudpv0", optional = true }
|
prudpv0 = { path = "../prudpv0", optional = true }
|
||||||
prudpv1 = { path = "../prudpv1", optional = true }
|
prudpv1 = { path = "../prudpv1", optional = true }
|
||||||
|
proxy-common = { path = "../proxy-common" }
|
||||||
cfg-if = "1.0.4"
|
cfg-if = "1.0.4"
|
||||||
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
|
use proxy_common::ProxyStartupParam;
|
||||||
use rnex_core::common::setup;
|
use rnex_core::common::setup;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
proxy::start_insecure(ProxyStartupParam::new()).await;
|
proxy::start_insecure(
|
||||||
|
ProxyStartupParam::new(proxy_common::ProxyType::Insecure)
|
||||||
|
.expect("unable to get startup parameters"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
|
use proxy_common::ProxyStartupParam;
|
||||||
use rnex_core::common::setup;
|
use rnex_core::common::setup;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
proxy::start_secure(ProxyStartupParam::new()).await;
|
proxy::start_secure(
|
||||||
|
ProxyStartupParam::new(proxy_common::ProxyType::Secure)
|
||||||
|
.expect("unable to get startup parameters"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use hmac::Mac;
|
use hmac::Mac;
|
||||||
use rc4::{KeyInit, Rc4, StreamCipher};
|
use rc4::{KeyInit, Rc4, StreamCipher};
|
||||||
use rnex_core::prudp::encryption::{DEFAULT_KEY, EncryptionPair};
|
use rnex_core::prudp::{
|
||||||
|
encryption::{DEFAULT_KEY, EncryptionPair},
|
||||||
|
types_flags::{TypesFlags, types::DATA},
|
||||||
|
};
|
||||||
use typenum::U5;
|
use typenum::U5;
|
||||||
|
|
||||||
use crate::crypto::{
|
use crate::crypto::{
|
||||||
|
|
@ -13,6 +16,8 @@ use crate::crypto::{
|
||||||
|
|
||||||
pub struct InsecureInstance {
|
pub struct InsecureInstance {
|
||||||
pair: EncryptionPair<Rc4<U5>>,
|
pair: EncryptionPair<Rc4<U5>>,
|
||||||
|
self_signat: [u8; 4],
|
||||||
|
remote_signat: [u8; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CryptoInstance for InsecureInstance {
|
impl CryptoInstance for InsecureInstance {
|
||||||
|
|
@ -25,12 +30,20 @@ impl CryptoInstance for InsecureInstance {
|
||||||
fn get_user_id(&self) -> u32 {
|
fn get_user_id(&self) -> u32 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4] {
|
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] {
|
||||||
|
if types_flags.get_types() == DATA {
|
||||||
|
if data.len() == 0 {
|
||||||
|
[0x12, 0x34, 0x56, 0x78]
|
||||||
|
} else {
|
||||||
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
||||||
.expect("unable to create hmac md5");
|
.expect("unable to create hmac md5");
|
||||||
hmac.update(data);
|
hmac.update(data);
|
||||||
hmac.finalize().into_bytes()[0..4].try_into().unwrap()
|
hmac.finalize().into_bytes()[0..4].try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.self_signat
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Insecure();
|
pub struct Insecure();
|
||||||
|
|
@ -44,9 +57,16 @@ impl Crypto for Insecure {
|
||||||
common_checksum(ACCESS_KEY, data)
|
common_checksum(ACCESS_KEY, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate(&self, packet_data: &[u8]) -> Self::Instance {
|
fn instantiate(
|
||||||
|
&self,
|
||||||
|
packet_data: &[u8],
|
||||||
|
self_signat: [u8; 4],
|
||||||
|
remote_signat: [u8; 4],
|
||||||
|
) -> Self::Instance {
|
||||||
InsecureInstance {
|
InsecureInstance {
|
||||||
pair: EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY)),
|
pair: EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY)),
|
||||||
|
self_signat,
|
||||||
|
remote_signat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use hmac::Mac;
|
use hmac::Mac;
|
||||||
use rc4::Rc4;
|
use rc4::Rc4;
|
||||||
use rnex_core::prudp::encryption::EncryptionPair;
|
use rnex_core::prudp::{encryption::EncryptionPair, types_flags::TypesFlags};
|
||||||
use typenum::U32;
|
use typenum::U32;
|
||||||
|
|
||||||
use crate::crypto::{
|
use crate::crypto::{
|
||||||
|
|
@ -23,7 +23,7 @@ impl CryptoInstance for SecureInstance {
|
||||||
fn get_user_id(&self) -> u32 {
|
fn get_user_id(&self) -> u32 {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4] {
|
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] {
|
||||||
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
let mut hmac = <HmacMd5 as Mac>::new_from_slice(ACCESS_KEY.as_bytes())
|
||||||
.expect("unable to create hmac md5");
|
.expect("unable to create hmac md5");
|
||||||
hmac.update(data);
|
hmac.update(data);
|
||||||
|
|
@ -41,7 +41,12 @@ impl Crypto for Secure {
|
||||||
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
fn calculate_checksum(&self, data: &[u8]) -> u8 {
|
||||||
common_checksum(ACCESS_KEY, data)
|
common_checksum(ACCESS_KEY, data)
|
||||||
}
|
}
|
||||||
fn instantiate(&self, data: &[u8]) -> Self::Instance {
|
fn instantiate(
|
||||||
|
&self,
|
||||||
|
data: &[u8],
|
||||||
|
self_signat: [u8; 4],
|
||||||
|
remote_signat: [u8; 4],
|
||||||
|
) -> Self::Instance {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
use rnex_core::prudp::types_flags::TypesFlags;
|
||||||
|
|
||||||
mod common_crypto;
|
mod common_crypto;
|
||||||
|
|
||||||
pub trait CryptoInstance: Send + 'static {
|
pub trait CryptoInstance: Send + 'static {
|
||||||
fn decrypt_incoming(&mut self, data: &mut [u8]);
|
fn decrypt_incoming(&mut self, data: &mut [u8]);
|
||||||
fn encrypt_outgoing(&mut self, data: &mut [u8]);
|
fn encrypt_outgoing(&mut self, data: &mut [u8]);
|
||||||
fn generate_signature(&self, data: &[u8]) -> [u8; 4];
|
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4];
|
||||||
fn get_user_id(&self) -> u32;
|
fn get_user_id(&self) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13,7 +14,12 @@ pub trait Crypto: Send + Sync + 'static {
|
||||||
type Instance: CryptoInstance;
|
type Instance: CryptoInstance;
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn calculate_checksum(&self, data: &[u8]) -> u8;
|
fn calculate_checksum(&self, data: &[u8]) -> u8;
|
||||||
fn instantiate(&self, data: &[u8]) -> Self::Instance;
|
fn instantiate(
|
||||||
|
&self,
|
||||||
|
data: &[u8],
|
||||||
|
self_signat: [u8; 4],
|
||||||
|
remote_signat: [u8; 4],
|
||||||
|
) -> Self::Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ async fn start_proxy<T: Crypto>(param: ProxyStartupParam) {
|
||||||
let mut crypto = Arc::new(T::new());
|
let mut crypto = Arc::new(T::new());
|
||||||
info!("binding to socket");
|
info!("binding to socket");
|
||||||
|
|
||||||
let server: Arc<Server<T>> = Arc::new(Server::new().await);
|
let server: Arc<Server<T>> = Arc::new(Server::new(param).await);
|
||||||
|
|
||||||
info!("waiting on packets");
|
info!("waiting on packets");
|
||||||
server.run_task().await;
|
server.run_task().await;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable, try_from_bytes, try_from_bytes_mut};
|
use bytemuck::{Pod, Zeroable, try_from_bytes, try_from_bytes_mut};
|
||||||
use log::error;
|
use log::{error, info};
|
||||||
use rnex_core::prudp::{
|
use rnex_core::prudp::{
|
||||||
types_flags::{
|
types_flags::{
|
||||||
TypesFlags,
|
self, TypesFlags,
|
||||||
flags::{HAS_SIZE, NEED_ACK},
|
flags::{HAS_SIZE, NEED_ACK},
|
||||||
types::{CONNECT, DATA, SYN},
|
types::{CONNECT, DATA, SYN},
|
||||||
},
|
},
|
||||||
|
|
@ -65,6 +65,40 @@ impl<T: AsRef<[u8]>> PRUDPV0Packet<T> {
|
||||||
.ok()?,
|
.ok()?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn size_mut(&mut self) -> Option<&mut u16>
|
||||||
|
where
|
||||||
|
T: AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
if self.header()?.type_flags.get_flags() & HAS_SIZE == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let offset = size_of::<PRUDPV0Header>() + get_type_specific_size(self.header()?.type_flags);
|
||||||
|
Some(bytemuck::from_bytes_mut(
|
||||||
|
self.0.as_mut().get_mut(offset..offset + 2)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn fragment_id_mut(&mut self) -> Option<&mut u8>
|
||||||
|
where
|
||||||
|
T: AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
if self.header()?.type_flags.get_types() != DATA {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let offset = size_of::<PRUDPV0Header>();
|
||||||
|
Some(self.0.as_mut().get_mut(offset)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn fragment_id(&self) -> Option<&u8> {
|
||||||
|
if self.header()?.type_flags.get_types() != DATA {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let offset = size_of::<PRUDPV0Header>();
|
||||||
|
Some(self.0.as_ref().get(offset)?)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn get_payload_offset(&self) -> Option<usize> {
|
fn get_payload_offset(&self) -> Option<usize> {
|
||||||
|
|
@ -136,7 +170,7 @@ const fn get_size_offset(tf: TypesFlags) -> usize {
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
const fn get_type_specific_size(tf: TypesFlags) -> usize {
|
const fn get_type_specific_size(tf: TypesFlags) -> usize {
|
||||||
if tf.get_types() & (SYN | CONNECT) != 0 {
|
if tf.get_types() == SYN || tf.get_types() == CONNECT {
|
||||||
4
|
4
|
||||||
} else if tf.get_types() & DATA != 0 {
|
} else if tf.get_types() & DATA != 0 {
|
||||||
1
|
1
|
||||||
|
|
@ -185,3 +219,94 @@ pub fn new_syn_packet(
|
||||||
|
|
||||||
packet.0
|
packet.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_connect_packet(
|
||||||
|
flags: u16,
|
||||||
|
source: VirtualPort,
|
||||||
|
destination: VirtualPort,
|
||||||
|
signat: [u8; 4],
|
||||||
|
crypto: &impl Crypto,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let type_flags = TypesFlags::default().types(CONNECT).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
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_data_packet(
|
||||||
|
flags: u16,
|
||||||
|
source: VirtualPort,
|
||||||
|
destination: VirtualPort,
|
||||||
|
data: &[u8],
|
||||||
|
sequence_id: u16,
|
||||||
|
session_id: u8,
|
||||||
|
frag_id: u8,
|
||||||
|
crypto_instance: &mut impl CryptoInstance,
|
||||||
|
crypto: &impl Crypto,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let type_flags = TypesFlags::default().types(DATA).flags(flags);
|
||||||
|
|
||||||
|
let vec = vec![0; precalc_size(type_flags, data.len())];
|
||||||
|
let mut packet = PRUDPV0Packet::new(vec);
|
||||||
|
packet
|
||||||
|
.header_mut()
|
||||||
|
.expect("packet malformed in creation")
|
||||||
|
.type_flags = type_flags;
|
||||||
|
packet
|
||||||
|
.payload_mut()
|
||||||
|
.expect("packet malformed in creation")
|
||||||
|
.copy_from_slice(data);
|
||||||
|
|
||||||
|
if let Some(size) = packet.size_mut() {
|
||||||
|
*size = data.len() as u16;
|
||||||
|
}
|
||||||
|
*packet
|
||||||
|
.fragment_id_mut()
|
||||||
|
.expect("packet malformed in creation") = frag_id;
|
||||||
|
let packet_signature = crypto_instance.generate_signature(
|
||||||
|
type_flags,
|
||||||
|
packet.payload().expect("packet malformed in creation"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let header = packet.header_mut().expect("packet malformed in creation");
|
||||||
|
|
||||||
|
*header = PRUDPV0Header {
|
||||||
|
destination,
|
||||||
|
source,
|
||||||
|
packet_signature,
|
||||||
|
sequence_id,
|
||||||
|
session_id,
|
||||||
|
type_flags,
|
||||||
|
};
|
||||||
|
|
||||||
|
*packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum(
|
||||||
|
packet
|
||||||
|
.checksummed_data()
|
||||||
|
.expect("packet malformed in creation"),
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("header: {:?}", packet.header());
|
||||||
|
|
||||||
|
packet.0
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ use std::{
|
||||||
Arc, LazyLock,
|
Arc, LazyLock,
|
||||||
atomic::{AtomicBool, AtomicU32},
|
atomic::{AtomicBool, AtomicU32},
|
||||||
},
|
},
|
||||||
|
thread::sleep,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
|
@ -16,7 +18,7 @@ use rnex_core::{
|
||||||
socket_addr::PRUDPSockAddr,
|
socket_addr::PRUDPSockAddr,
|
||||||
types_flags::{
|
types_flags::{
|
||||||
TypesFlags,
|
TypesFlags,
|
||||||
flags::{ACK, HAS_SIZE, NEED_ACK},
|
flags::{ACK, HAS_SIZE, NEED_ACK, RELIABLE},
|
||||||
types::{CONNECT, DATA, SYN},
|
types::{CONNECT, DATA, SYN},
|
||||||
},
|
},
|
||||||
virtual_port::VirtualPort,
|
virtual_port::VirtualPort,
|
||||||
|
|
@ -33,7 +35,10 @@ use tokio::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
crypto::{Crypto, CryptoInstance},
|
crypto::{Crypto, CryptoInstance},
|
||||||
packet::{PRUDPV0Header, PRUDPV0Packet, new_syn_packet, precalc_size},
|
packet::{
|
||||||
|
PRUDPV0Header, PRUDPV0Packet, new_connect_packet, new_data_packet, new_syn_packet,
|
||||||
|
precalc_size,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct InternalConnection<C: CryptoInstance> {
|
pub struct InternalConnection<C: CryptoInstance> {
|
||||||
|
|
@ -42,6 +47,7 @@ pub struct InternalConnection<C: CryptoInstance> {
|
||||||
server_packet_counter: u16,
|
server_packet_counter: u16,
|
||||||
client_packet_counter: u16,
|
client_packet_counter: u16,
|
||||||
unacknowledged_packets: HashMap<u16, Arc<Vec<u8>>>,
|
unacknowledged_packets: HashMap<u16, Arc<Vec<u8>>>,
|
||||||
|
packet_queue: HashMap<u16, (Instant, PRUDPV0Packet<Vec<u8>>)>,
|
||||||
}
|
}
|
||||||
pub struct Connection<C: CryptoInstance> {
|
pub struct Connection<C: CryptoInstance> {
|
||||||
alive: AtomicBool,
|
alive: AtomicBool,
|
||||||
|
|
@ -71,8 +77,8 @@ pub struct Server<C: Crypto> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Crypto> Server<C> {
|
impl<C: Crypto> Server<C> {
|
||||||
async fn send_data_packet(&self, conn: &Connection<C::Instance>, data: &[u8]) {
|
async fn send_data_packet(self: Arc<Self>, conn: Arc<Connection<C::Instance>>, data: &[u8]) {
|
||||||
let type_flags = TypesFlags::default().types(DATA).flags(HAS_SIZE | NEED_ACK);
|
/*let type_flags = TypesFlags::default().types(DATA).flags(HAS_SIZE | NEED_ACK);
|
||||||
let vec = vec![0; precalc_size(type_flags, data.len())];
|
let vec = vec![0; precalc_size(type_flags, data.len())];
|
||||||
let mut packet = PRUDPV0Packet::new(vec);
|
let mut packet = PRUDPV0Packet::new(vec);
|
||||||
|
|
||||||
|
|
@ -99,13 +105,26 @@ impl<C: Crypto> Server<C> {
|
||||||
packet
|
packet
|
||||||
.checksummed_data()
|
.checksummed_data()
|
||||||
.expect("packet malformed in creation"),
|
.expect("packet malformed in creation"),
|
||||||
|
);*/
|
||||||
|
let mut inner = conn.inner.lock().await;
|
||||||
|
let seq = inner.server_packet_counter;
|
||||||
|
let packet = new_data_packet(
|
||||||
|
HAS_SIZE | NEED_ACK | RELIABLE,
|
||||||
|
self.param.virtual_port,
|
||||||
|
conn.addr.virtual_port,
|
||||||
|
data,
|
||||||
|
inner.server_packet_counter,
|
||||||
|
conn.session_id,
|
||||||
|
0,
|
||||||
|
&mut inner.crypto_instance,
|
||||||
|
&self.crypto,
|
||||||
);
|
);
|
||||||
|
inner.server_packet_counter += 1;
|
||||||
|
|
||||||
let packet_raw = packet.0;
|
let packet = Arc::new(packet);
|
||||||
|
|
||||||
let packet = Arc::new(packet_raw);
|
|
||||||
|
|
||||||
let packet_ref = Arc::downgrade(&packet);
|
let packet_ref = Arc::downgrade(&packet);
|
||||||
|
let conn = Arc::downgrade(&conn);
|
||||||
|
let this = Arc::downgrade(&self);
|
||||||
|
|
||||||
inner.unacknowledged_packets.insert(seq, packet);
|
inner.unacknowledged_packets.insert(seq, packet);
|
||||||
|
|
||||||
|
|
@ -116,7 +135,19 @@ impl<C: Crypto> Server<C> {
|
||||||
let Some(data) = packet_ref.upgrade() else {
|
let Some(data) = packet_ref.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let Some(conn) = conn.upgrade() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(this) = this.upgrade() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
info!("send attempt {}", n);
|
info!("send attempt {}", n);
|
||||||
|
|
||||||
|
self.socket
|
||||||
|
.send_to(&data, conn.addr.regular_socket_addr)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -125,14 +156,21 @@ impl<C: Crypto> Server<C> {
|
||||||
conn: Arc<Connection<C::Instance>>,
|
conn: Arc<Connection<C::Instance>>,
|
||||||
mut recv: SplittableBufferConnection,
|
mut recv: SplittableBufferConnection,
|
||||||
) {
|
) {
|
||||||
while let Some(data) = recv.recv().await {}
|
while let Some(data) = recv.recv().await {
|
||||||
|
if &data[..] == &[0, 0, 0, 0, 0] {
|
||||||
|
info!("got keepalive");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info!("got data from server: {:?}", data);
|
||||||
|
self.clone().send_data_packet(conn.clone(), &data).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async fn timeout_thread(self: Arc<Self>, conn: Arc<Connection<C::Instance>>) {
|
async fn timeout_thread(self: Arc<Self>, conn: Arc<Connection<C::Instance>>) {
|
||||||
loop {
|
loop {
|
||||||
conn
|
sleep(Duration::from_secs(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn handle_syn(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: PRUDPSockAddr) {
|
async fn handle_syn(self: Arc<Self>, packet: PRUDPV0Packet<Vec<u8>>, addr: PRUDPSockAddr) {
|
||||||
info!("got syn");
|
info!("got syn");
|
||||||
let header = packet.header().unwrap();
|
let header = packet.header().unwrap();
|
||||||
|
|
||||||
|
|
@ -142,8 +180,7 @@ impl<C: Crypto> Server<C> {
|
||||||
let packet = new_syn_packet(ACK, header.destination, header.source, signat, &self.crypto);
|
let packet = new_syn_packet(ACK, header.destination, header.source, signat, &self.crypto);
|
||||||
self.socket.send_to(&packet, addr.regular_socket_addr).await;
|
self.socket.send_to(&packet, addr.regular_socket_addr).await;
|
||||||
}
|
}
|
||||||
async fn handle_connect(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: PRUDPSockAddr) {
|
async fn handle_connect(self: Arc<Self>, packet: PRUDPV0Packet<Vec<u8>>, addr: PRUDPSockAddr) {
|
||||||
let conn = self.connections.write().await;
|
|
||||||
let Some(data) = packet.payload() else {
|
let Some(data) = packet.payload() else {
|
||||||
warn!("malformed packet from: {:?}", addr.regular_socket_addr);
|
warn!("malformed packet from: {:?}", addr.regular_socket_addr);
|
||||||
return;
|
return;
|
||||||
|
|
@ -155,16 +192,6 @@ impl<C: Crypto> Server<C> {
|
||||||
);
|
);
|
||||||
return;
|
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 = addr.calculate_connection_signature();
|
||||||
let remote_signat = [
|
let remote_signat = [
|
||||||
remote_signat[0],
|
remote_signat[0],
|
||||||
|
|
@ -173,10 +200,19 @@ impl<C: Crypto> Server<C> {
|
||||||
remote_signat[3],
|
remote_signat[3],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let ci = self.crypto.instantiate(data, self_signat, remote_signat);
|
||||||
|
|
||||||
|
let pid = ci.get_user_id();
|
||||||
|
let buf_conn = new_backend_connection(&self.param, addr, pid).await;
|
||||||
|
let Some(buf_conn) = buf_conn else {
|
||||||
|
error!("unable to connect to backend");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let header = packet.header().expect("header should be validated by now");
|
let header = packet.header().expect("header should be validated by now");
|
||||||
|
|
||||||
let conn = Arc::new(Connection {
|
let conn = Arc::new(Connection {
|
||||||
target: conn.duplicate_sender(),
|
target: buf_conn.duplicate_sender(),
|
||||||
remote_signat,
|
remote_signat,
|
||||||
self_signat,
|
self_signat,
|
||||||
addr,
|
addr,
|
||||||
|
|
@ -188,10 +224,95 @@ impl<C: Crypto> Server<C> {
|
||||||
client_packet_counter: 2,
|
client_packet_counter: 2,
|
||||||
server_packet_counter: 1,
|
server_packet_counter: 1,
|
||||||
unacknowledged_packets: HashMap::new(),
|
unacknowledged_packets: HashMap::new(),
|
||||||
|
packet_queue: HashMap::new(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut conns = self.connections.write().await;
|
||||||
|
conns.insert(addr, conn.clone());
|
||||||
|
drop(conns);
|
||||||
|
|
||||||
|
spawn({
|
||||||
|
let this = self.clone();
|
||||||
|
let conn = conn.clone();
|
||||||
|
this.connection_thread(conn, buf_conn)
|
||||||
|
});
|
||||||
|
spawn({
|
||||||
|
let this = self.clone();
|
||||||
|
let conn = conn.clone();
|
||||||
|
this.timeout_thread(conn)
|
||||||
|
});
|
||||||
|
|
||||||
|
let packet = new_connect_packet(
|
||||||
|
ACK,
|
||||||
|
header.destination,
|
||||||
|
header.source,
|
||||||
|
remote_signat,
|
||||||
|
&self.crypto,
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("sending back connection accept");
|
||||||
|
self.socket.send_to(&packet, addr.regular_socket_addr).await;
|
||||||
}
|
}
|
||||||
async fn process_packet<'a>(self: Arc<Self>, packet: PRUDPV0Packet<&[u8]>, addr: SocketAddrV4) {
|
async fn handle_data(self: Arc<Self>, mut packet: PRUDPV0Packet<Vec<u8>>, addr: PRUDPSockAddr) {
|
||||||
|
let Some(frag_id) = packet.fragment_id() else {
|
||||||
|
warn!("invalid packet from: {:?}", addr);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(header) = packet.header() else {
|
||||||
|
warn!("invalid packet from: {:?}", addr);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let rd = self.connections.read().await;
|
||||||
|
let res = rd.get(&addr).cloned();
|
||||||
|
drop(rd);
|
||||||
|
let Some(res) = res else {
|
||||||
|
warn!("data packet on inactive connection from: {:?}", addr);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
info!("frag: {}", frag_id);
|
||||||
|
let mut conn = res.inner.lock().await;
|
||||||
|
let ack = new_data_packet(
|
||||||
|
ACK | HAS_SIZE,
|
||||||
|
self.param.virtual_port,
|
||||||
|
res.addr.virtual_port,
|
||||||
|
&[],
|
||||||
|
header.sequence_id,
|
||||||
|
header.session_id,
|
||||||
|
*frag_id,
|
||||||
|
&mut conn.crypto_instance,
|
||||||
|
&self.crypto,
|
||||||
|
);
|
||||||
|
self.socket.send_to(&ack, addr.regular_socket_addr).await;
|
||||||
|
conn.last_action = Instant::now();
|
||||||
|
conn.packet_queue.insert(
|
||||||
|
packet.header().unwrap().sequence_id,
|
||||||
|
(Instant::now(), packet),
|
||||||
|
);
|
||||||
|
while let Some((_, mut packet)) = {
|
||||||
|
let ctr = conn.client_packet_counter;
|
||||||
|
conn.packet_queue.remove(&ctr)
|
||||||
|
} {
|
||||||
|
info!("processing packet: {}", conn.client_packet_counter);
|
||||||
|
let Some(payload) = packet.payload_mut() else {
|
||||||
|
//todo: at this point the stream would have been broken, we should probably disconnect the client
|
||||||
|
warn!("invalid packet from: {:?}", addr);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
conn.crypto_instance.decrypt_incoming(payload);
|
||||||
|
|
||||||
|
res.target.send(payload.to_owned()).await;
|
||||||
|
conn.client_packet_counter += 1;
|
||||||
|
}
|
||||||
|
drop(conn);
|
||||||
|
}
|
||||||
|
async fn process_packet<'a>(
|
||||||
|
self: Arc<Self>,
|
||||||
|
packet: PRUDPV0Packet<Vec<u8>>,
|
||||||
|
addr: SocketAddrV4,
|
||||||
|
) {
|
||||||
if !packet.check_checksum(&self.crypto) {
|
if !packet.check_checksum(&self.crypto) {
|
||||||
warn!("invalid checksum from: {}", addr);
|
warn!("invalid checksum from: {}", addr);
|
||||||
return;
|
return;
|
||||||
|
|
@ -211,6 +332,9 @@ impl<C: Crypto> Server<C> {
|
||||||
CONNECT => {
|
CONNECT => {
|
||||||
self.handle_connect(packet, addr).await;
|
self.handle_connect(packet, addr).await;
|
||||||
}
|
}
|
||||||
|
DATA => {
|
||||||
|
self.handle_data(packet, addr).await;
|
||||||
|
}
|
||||||
v => {
|
v => {
|
||||||
println!("unimplemented packed type: {}", v);
|
println!("unimplemented packed type: {}", v);
|
||||||
}
|
}
|
||||||
|
|
@ -231,8 +355,8 @@ impl<C: Crypto> Server<C> {
|
||||||
};
|
};
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let data = vec;
|
let mut data = vec;
|
||||||
let packet = PRUDPV0Packet::new(&data[..]);
|
let packet = PRUDPV0Packet::new(data);
|
||||||
|
|
||||||
let SocketAddr::V4(addr) = addr else {
|
let SocketAddr::V4(addr) = addr else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
use rnex_core::reggie::RemoteEdgeNodeHolder;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rnex_core::common::setup;
|
use rnex_core::common::setup;
|
||||||
|
use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend};
|
||||||
|
use rnex_core::nex::auth_handler::AuthHandler;
|
||||||
|
use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister;
|
||||||
|
use rnex_core::reggie::RemoteEdgeNodeHolder;
|
||||||
|
use rnex_core::rmc::protocols::{OnlyRemote, new_rmc_gateway_connection};
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
use rnex_core::rmc::structures::RmcSerialize;
|
||||||
|
use rnex_core::util::SplittableBufferConnection;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::net::SocketAddrV4;
|
use std::net::SocketAddrV4;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend};
|
|
||||||
use rnex_core::nex::auth_handler::AuthHandler;
|
|
||||||
use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister;
|
|
||||||
use rnex_core::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
|
|
||||||
use rnex_core::util::SplittableBufferConnection;
|
|
||||||
|
|
||||||
|
|
||||||
pub static FORWARD_EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(|| {
|
pub static FORWARD_EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(|| {
|
||||||
env::var("FORWARD_EDGE_NODE_HOLDER")
|
env::var("FORWARD_EDGE_NODE_HOLDER")
|
||||||
|
|
@ -20,26 +19,29 @@ pub static FORWARD_EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(||{
|
||||||
.expect("FORWARD_EDGE_NODE_HOLDER not set")
|
.expect("FORWARD_EDGE_NODE_HOLDER not set")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER).await.unwrap();
|
let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let conn: SplittableBufferConnection = conn.into();
|
let conn: SplittableBufferConnection = conn.into();
|
||||||
|
|
||||||
conn.send(DontRegister.to_data().unwrap()).await;
|
conn.send(DontRegister.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))
|
||||||
|
});
|
||||||
|
|
||||||
new_simple_backend(move |_, _| {
|
new_simple_backend(move |_, _| {
|
||||||
let controller = conn.clone();
|
let controller = conn.clone();
|
||||||
Arc::new(AuthHandler {
|
Arc::new(AuthHandler {
|
||||||
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
||||||
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
|
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
|
||||||
control_server: controller
|
control_server: controller,
|
||||||
})
|
})
|
||||||
}).await;
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,14 +69,9 @@ fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Auth for AuthHandler {
|
impl Auth for AuthHandler {
|
||||||
async fn login(&self, _name: String) -> Result<(), ErrorCode> {
|
async fn login(
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn login_ex(
|
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
_extra_data: Any,
|
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||||
let Ok(pid) = name.parse() else {
|
let Ok(pid) = name.parse() else {
|
||||||
return Err(ErrorCode::Core_InvalidArgument);
|
return Err(ErrorCode::Core_InvalidArgument);
|
||||||
|
|
@ -122,6 +117,14 @@ impl Auth for AuthHandler {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn login_ex(
|
||||||
|
&self,
|
||||||
|
name: String,
|
||||||
|
_extra_data: Any,
|
||||||
|
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||||
|
self.login(name).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn request_ticket(
|
async fn request_ticket(
|
||||||
&self,
|
&self,
|
||||||
source_pid: u32,
|
source_pid: u32,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
|
use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
|
use macros::{method_id, rmc_proto};
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
use rnex_core::rmc::response::ErrorCode;
|
||||||
use rnex_core::rmc::structures::any::Any;
|
use rnex_core::rmc::structures::any::Any;
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
use rnex_core::rmc::structures::qresult::QResult;
|
||||||
use macros::{method_id, rmc_proto};
|
|
||||||
|
|
||||||
|
|
||||||
/// This is the representation for `Ticket Granting`(for details see the
|
/// This is the representation for `Ticket Granting`(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
|
|
@ -12,7 +11,10 @@ pub trait Auth {
|
||||||
/// representation of the `Login` method(for details see the
|
/// representation of the `Login` method(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(1)]
|
#[method_id(1)]
|
||||||
async fn login(&self, name: String) -> Result<(), ErrorCode>;
|
async fn login(
|
||||||
|
&self,
|
||||||
|
name: String,
|
||||||
|
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
||||||
|
|
||||||
/// representation of the `LoginEx` method(for details see the
|
/// representation of the `LoginEx` method(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue