feat(secure server): start working on secure server

This commit is contained in:
DJMrTV 2025-02-03 20:43:24 +01:00
commit b097c298e7
3 changed files with 155 additions and 28 deletions

View file

@ -3,12 +3,14 @@
use std::{env, fs};
use std::fs::File;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use chrono::Local;
use log::info;
use once_cell::sync::Lazy;
use rc4::{KeyInit, Rc4, StreamCipher};
use rc4::consts::U5;
use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger};
use tokio::task::JoinHandle;
use crate::nex::account::Account;
use crate::protocols::auth;
use crate::protocols::auth::AuthProtocolConfig;
@ -43,6 +45,12 @@ static AUTH_SERVER_PORT: Lazy<u16> = Lazy::new(||{
.and_then(|s| s.parse().ok())
.unwrap_or(10000)
});
static SECURE_SERVER_PORT: Lazy<u16> = Lazy::new(||{
env::var("SECURE_SERVER_PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10001)
});
static OWN_IP: Lazy<Ipv4Addr> = Lazy::new(||{
env::var("SERVER_IP")
@ -51,6 +59,10 @@ static OWN_IP: Lazy<Ipv4Addr> = Lazy::new(||{
.expect("no public ip specified")
});
static SECURE_STATION_URL: Lazy<String> = Lazy::new(||
format!("prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1", *OWN_IP, *SECURE_SERVER_PORT)
);
#[tokio::main]
async fn main() {
CombinedLogger::init(
@ -68,14 +80,16 @@ async fn main() {
start_servers().await;
}
async fn auth_server_handle_rmc(_packet: PRUDPPacket, _rmc_message: RMCMessage){
struct AuthServer{
router: Arc<Router>,
join_handle: JoinHandle<()>,
socket: Socket
}
async fn start_servers(){
async fn start_auth_server() -> AuthServer{
info!("starting auth server on {}:{}", *OWN_IP, *AUTH_SERVER_PORT);
let (auth_server_router, auth_router_join) =
let (router, join_handle) =
Router::new(SocketAddrV4::new(*OWN_IP, *AUTH_SERVER_PORT)).await
.expect("unable to startauth server");
@ -86,16 +100,16 @@ async fn start_servers(){
let auth_protocol_config = AuthProtocolConfig{
secure_server_account: &SECURE_SERVER_ACCOUNT,
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
station_url: "prudps:/PID=2;sid=1;stream=10;type=2;address=31.220.75.208;port=10001;CID=1"
station_url: &SECURE_STATION_URL
};
let rmcserver = RMCProtocolServer::new(Box::new([
Box::new(auth::bound_protocol(auth_protocol_config))
]));
let mut _socket =
let mut socket =
Socket::new(
auth_server_router.clone(),
router.clone(),
VirtualPort::new(1,10),
"6f599f81",
Box::new(|_|{
@ -109,7 +123,7 @@ async fn start_servers(){
let cypher = Box::new(rc4);
let client_cypher: Box<dyn StreamCipher + Send> = cypher;
(true, (server_cypher, client_cypher))
Some((Vec::new(), (server_cypher, client_cypher), None))
}
)
}),
@ -119,7 +133,69 @@ async fn start_servers(){
})
).await.expect("unable to create socket");
auth_router_join.await.expect("auth server crashed")
AuthServer{
join_handle,
router,
socket,
}
}
struct SecureServer{
router: Arc<Router>,
join_handle: JoinHandle<()>,
socket: Socket
}
async fn start_secure_server() -> SecureServer{
info!("starting secure server on {}:{}", *OWN_IP, *SECURE_SERVER_PORT);
let (router, join_handle) =
Router::new(SocketAddrV4::new(*OWN_IP, *SECURE_SERVER_PORT)).await
.expect("unable to startauth server");
info!("setting up endpoints");
let rmcserver = RMCProtocolServer::new(Box::new([]));
let mut socket =
Socket::new(
router.clone(),
VirtualPort::new(1,10),
"6f599f81",
Box::new(|p|{
Box::pin(
async move {
let rc4: Rc4<U5> = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap();
let cypher = Box::new(rc4);
let server_cypher: Box<dyn StreamCipher + Send> = cypher;
let rc4: Rc4<U5> = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap();
let cypher = Box::new(rc4);
let client_cypher: Box<dyn StreamCipher + Send> = cypher;
Some((Vec::new(), (server_cypher, client_cypher), None))
}
)
}),
Box::new(move |packet, socket, connection|{
let rmcserver = rmcserver.clone();
Box::pin(async move { rmcserver.process_message(packet, &socket, connection).await; })
})
).await.expect("unable to create socket");
SecureServer{
join_handle,
router,
socket,
}
}
async fn start_servers(){
let auth_server = start_auth_server().await;
let secure_server = start_secure_server().await;
auth_server.join_handle.await.expect("auth server crashed");
secure_server.join_handle.await.expect("auth server crashed");
}

View file

@ -15,6 +15,8 @@ use crate::rmc::structures::connection_data::ConnectionData;
use crate::rmc::structures::qresult::QResult;
pub async fn login_ex(rmcmessage: &RMCMessage, proto_data: AuthProtocolConfig, pid: u32) -> RMCResponseResult{
return rmcmessage.error_result_with_code(ErrorCode::Authentication_OutOfService);
// todo: figure out how the AuthenticationInfo struct works, parse it and validate login info
let Ok(mut client) = account::Client::new().await else {

View file

@ -11,7 +11,7 @@ use rc4::StreamCipher;
use crate::prudp::packet::{PacketOption, PRUDPPacket, VirtualPort};
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
use crate::prudp::packet::PacketOption::{ConnectionSignature, MaximumSubstreamId, SupportedFunctions};
use crate::prudp::packet::types::{CONNECT, DATA, PING, SYN};
use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
use crate::prudp::router::{Error, Router};
use crate::prudp::sockaddr::PRUDPSockAddr;
@ -26,9 +26,14 @@ pub struct Socket {
}
type OnConnectHandlerFn = Box<dyn Fn(PRUDPPacket) -> Pin<Box<dyn Future<Output=(bool, (Box<dyn StreamCipher + Send>, Box<dyn StreamCipher + Send>))> + Send>> + Send + Sync>;
type OnConnectHandlerFn = Box<dyn Fn(PRUDPPacket) -> Pin<Box<dyn Future<Output=Option<(Vec<u8>, (Box<dyn StreamCipher + Send>, Box<dyn StreamCipher + Send>), Option<ActiveSecureConnectionData>)>> + Send>> + Send + Sync>;
type OnDataHandlerFn = Box<dyn for<'a> Fn(PRUDPPacket, Arc<SocketData>, &'a mut MutexGuard<'_, ConnectionData>) -> Pin<Box<dyn Future<Output=()> + 'a + Send>> + Send + Sync>;
pub struct ActiveSecureConnectionData {
pid: u32,
session_key: [u8; 32],
}
pub struct SocketData {
virtual_port: VirtualPort,
pub socket: Arc<UdpSocket>,
@ -45,6 +50,7 @@ pub struct ActiveConnectionData {
server_encryption: Box<dyn StreamCipher + Send>,
client_decryption: Box<dyn StreamCipher + Send>,
pub server_session_id: u8,
pub active_secure_connection_data: Option<ActiveSecureConnectionData>
}
@ -212,6 +218,25 @@ impl SocketData {
CONNECT => {
info!("got connect");
let Some((
accepted,
(client_decryption, server_encryption),
active_secure_connection_data
)) = (self.on_connect_handler)(packet.clone()).await else {
error!("invalid connection request");
return;
};
connection.active_connection_data = Some(ActiveConnectionData {
client_decryption,
server_encryption,
reliable_client_queue: VecDeque::new(),
reliable_client_counter: 2,
reliable_server_counter: 1,
server_session_id: packet.header.session_id,
active_secure_connection_data
});
let mut response_packet = packet.base_response_packet();
response_packet.header.types_and_flags.set_types(CONNECT);
@ -253,29 +278,21 @@ impl SocketData {
response_packet.set_sizes();
response_packet.calculate_and_assign_signature(self.access_key, None, Some(connection.server_signature));
let potential_session_key = connection
.active_connection_data
.as_ref()
.unwrap().active_secure_connection_data
.as_ref()
.map(|s| s.session_key);
response_packet.calculate_and_assign_signature(self.access_key, potential_session_key, Some(connection.server_signature));
let mut vec = Vec::new();
response_packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes");
self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back");
let (accepted, (client_decryption, server_encryption))
= (self.on_connect_handler)(packet.clone()).await;
if !accepted {
// rejected
return;
}
connection.active_connection_data = Some(ActiveConnectionData {
client_decryption,
server_encryption,
reliable_client_queue: VecDeque::new(),
reliable_client_counter: 2,
reliable_server_counter: 1,
server_session_id: packet.header.session_id,
});
}
DATA => {
if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 {
@ -362,7 +379,37 @@ impl SocketData {
self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back");
}
}
3 => {}
DISCONNECT => {
let ConnectionData{
server_signature,
active_connection_data,
..
} = &*connection;
let Some(active_connection) = active_connection_data.as_ref() else {
return;
};
let mut ack = packet.base_acknowledgement_packet();
ack.set_sizes();
let potential_session_key = active_connection_data
.as_ref()
.unwrap().active_secure_connection_data
.as_ref()
.map(|s| s.session_key);
ack.calculate_and_assign_signature(self.access_key, potential_session_key, Some(*server_signature));
let mut vec = Vec::new();
ack.write_to(&mut vec).expect("somehow failed to convert backet to bytes");
self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back");
self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back");
self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back");
}
_ => unimplemented!("unimplemented packet type: {}", packet.header.types_and_flags.get_types())
}
}
@ -370,6 +417,8 @@ impl SocketData {
impl ConnectionData{
pub async fn finish_and_send_packet_to(&mut self, socket: &SocketData, mut packet: PRUDPPacket){
println!("{}", hex::encode(&packet.payload));
if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0{
let Some(active_connection) = self.active_connection_data.as_mut() else {
error!("tried to send a secure packet to an inactive connection");