feat(secure server): start working on secure server
This commit is contained in:
parent
28004f7b4d
commit
b097c298e7
3 changed files with 155 additions and 28 deletions
94
src/main.rs
94
src/main.rs
|
|
@ -3,12 +3,14 @@
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
use std::sync::Arc;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use log::info;
|
use log::info;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rc4::{KeyInit, Rc4, StreamCipher};
|
use rc4::{KeyInit, Rc4, StreamCipher};
|
||||||
use rc4::consts::U5;
|
use rc4::consts::U5;
|
||||||
use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger};
|
use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger};
|
||||||
|
use tokio::task::JoinHandle;
|
||||||
use crate::nex::account::Account;
|
use crate::nex::account::Account;
|
||||||
use crate::protocols::auth;
|
use crate::protocols::auth;
|
||||||
use crate::protocols::auth::AuthProtocolConfig;
|
use crate::protocols::auth::AuthProtocolConfig;
|
||||||
|
|
@ -43,6 +45,12 @@ static AUTH_SERVER_PORT: Lazy<u16> = Lazy::new(||{
|
||||||
.and_then(|s| s.parse().ok())
|
.and_then(|s| s.parse().ok())
|
||||||
.unwrap_or(10000)
|
.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(||{
|
static OWN_IP: Lazy<Ipv4Addr> = Lazy::new(||{
|
||||||
env::var("SERVER_IP")
|
env::var("SERVER_IP")
|
||||||
|
|
@ -51,6 +59,10 @@ static OWN_IP: Lazy<Ipv4Addr> = Lazy::new(||{
|
||||||
.expect("no public ip specified")
|
.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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
CombinedLogger::init(
|
CombinedLogger::init(
|
||||||
|
|
@ -68,14 +80,16 @@ async fn main() {
|
||||||
start_servers().await;
|
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);
|
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
|
Router::new(SocketAddrV4::new(*OWN_IP, *AUTH_SERVER_PORT)).await
|
||||||
.expect("unable to startauth server");
|
.expect("unable to startauth server");
|
||||||
|
|
||||||
|
|
@ -86,16 +100,16 @@ async fn start_servers(){
|
||||||
let auth_protocol_config = AuthProtocolConfig{
|
let auth_protocol_config = AuthProtocolConfig{
|
||||||
secure_server_account: &SECURE_SERVER_ACCOUNT,
|
secure_server_account: &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",
|
||||||
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([
|
let rmcserver = RMCProtocolServer::new(Box::new([
|
||||||
Box::new(auth::bound_protocol(auth_protocol_config))
|
Box::new(auth::bound_protocol(auth_protocol_config))
|
||||||
]));
|
]));
|
||||||
|
|
||||||
let mut _socket =
|
let mut socket =
|
||||||
Socket::new(
|
Socket::new(
|
||||||
auth_server_router.clone(),
|
router.clone(),
|
||||||
VirtualPort::new(1,10),
|
VirtualPort::new(1,10),
|
||||||
"6f599f81",
|
"6f599f81",
|
||||||
Box::new(|_|{
|
Box::new(|_|{
|
||||||
|
|
@ -109,7 +123,7 @@ async fn start_servers(){
|
||||||
let cypher = Box::new(rc4);
|
let cypher = Box::new(rc4);
|
||||||
let client_cypher: Box<dyn StreamCipher + Send> = cypher;
|
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");
|
).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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
use crate::rmc::structures::qresult::QResult;
|
use crate::rmc::structures::qresult::QResult;
|
||||||
|
|
||||||
pub async fn login_ex(rmcmessage: &RMCMessage, proto_data: AuthProtocolConfig, pid: u32) -> RMCResponseResult{
|
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
|
// todo: figure out how the AuthenticationInfo struct works, parse it and validate login info
|
||||||
|
|
||||||
let Ok(mut client) = account::Client::new().await else {
|
let Ok(mut client) = account::Client::new().await else {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use rc4::StreamCipher;
|
||||||
use crate::prudp::packet::{PacketOption, PRUDPPacket, VirtualPort};
|
use crate::prudp::packet::{PacketOption, PRUDPPacket, VirtualPort};
|
||||||
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
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::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::router::{Error, Router};
|
||||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
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>;
|
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 {
|
pub struct SocketData {
|
||||||
virtual_port: VirtualPort,
|
virtual_port: VirtualPort,
|
||||||
pub socket: Arc<UdpSocket>,
|
pub socket: Arc<UdpSocket>,
|
||||||
|
|
@ -45,6 +50,7 @@ pub struct ActiveConnectionData {
|
||||||
server_encryption: Box<dyn StreamCipher + Send>,
|
server_encryption: Box<dyn StreamCipher + Send>,
|
||||||
client_decryption: Box<dyn StreamCipher + Send>,
|
client_decryption: Box<dyn StreamCipher + Send>,
|
||||||
pub server_session_id: u8,
|
pub server_session_id: u8,
|
||||||
|
pub active_secure_connection_data: Option<ActiveSecureConnectionData>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -212,6 +218,25 @@ impl SocketData {
|
||||||
CONNECT => {
|
CONNECT => {
|
||||||
info!("got 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();
|
let mut response_packet = packet.base_response_packet();
|
||||||
|
|
||||||
response_packet.header.types_and_flags.set_types(CONNECT);
|
response_packet.header.types_and_flags.set_types(CONNECT);
|
||||||
|
|
@ -253,29 +278,21 @@ impl SocketData {
|
||||||
|
|
||||||
response_packet.set_sizes();
|
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();
|
let mut vec = Vec::new();
|
||||||
response_packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes");
|
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");
|
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 => {
|
DATA => {
|
||||||
if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 {
|
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");
|
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())
|
_ => unimplemented!("unimplemented packet type: {}", packet.header.types_and_flags.get_types())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -370,6 +417,8 @@ impl SocketData {
|
||||||
|
|
||||||
impl ConnectionData{
|
impl ConnectionData{
|
||||||
pub async fn finish_and_send_packet_to(&mut self, socket: &SocketData, mut packet: PRUDPPacket){
|
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{
|
if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0{
|
||||||
let Some(active_connection) = self.active_connection_data.as_mut() else {
|
let Some(active_connection) = self.active_connection_data.as_mut() else {
|
||||||
error!("tried to send a secure packet to an inactive connection");
|
error!("tried to send a secure packet to an inactive connection");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue