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::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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue