Added encryption
This commit is contained in:
parent
95bbd71bae
commit
149a3acc1d
|
@ -8,10 +8,11 @@ license = "MIT"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
purple_cello_mc_protocol = { git = "https://github.com/PurpleCelloServer/purple_cello_mc_protocol.git", rev = "505adfb92c44db44a89effa4d38ebb863c2c60d0" }
|
purple_cello_mc_protocol = { git = "https://github.com/PurpleCelloServer/purple_cello_mc_protocol.git", rev = "9ff2e95c66b1d773362936733273350e4bdd399a" }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
base64 = "0.21.5"
|
base64 = "0.21.5"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
rsa = "0.6"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Yeahbut May 2024
|
// Yeahbut May 2024
|
||||||
|
|
||||||
use std::error::Error;
|
use std::mem;
|
||||||
use tokio::net::{TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}};
|
use tokio::net::{TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}};
|
||||||
|
|
||||||
use purple_cello_mc_protocol::{
|
use purple_cello_mc_protocol::{
|
||||||
|
@ -64,6 +64,7 @@ pub async fn handle_client(
|
||||||
match server_conn {
|
match server_conn {
|
||||||
Some(mut server_conn) => {
|
Some(mut server_conn) => {
|
||||||
if login_handle::respond_login(
|
if login_handle::respond_login(
|
||||||
|
&proxy_info,
|
||||||
&mut client_conn,
|
&mut client_conn,
|
||||||
&mut server_conn,
|
&mut server_conn,
|
||||||
).await.expect(
|
).await.expect(
|
||||||
|
@ -79,7 +80,9 @@ pub async fn handle_client(
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
login::clientbound::Disconnect {
|
login::clientbound::Disconnect {
|
||||||
reason: "\"Server Error (Server may be starting)\""
|
reason: "\"Server Error (Server is down or \
|
||||||
|
restarting)\nPlease contact the admins if the issue persists:\n\
|
||||||
|
purplecelloserver@gmail.com\""
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
.write(&mut client_conn)
|
.write(&mut client_conn)
|
||||||
|
@ -122,24 +125,34 @@ Failed to connect to the backend server");
|
||||||
println!("Connection Closed");
|
println!("Connection Closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_play(
|
async fn handle_play<'a>(
|
||||||
mut client_conn: ProtocolConnection<'_>,
|
mut client_conn: ProtocolConnection<'a>,
|
||||||
mut server_conn: ProtocolConnection<'_>,
|
mut server_conn: ProtocolConnection<'a>,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) {
|
||||||
|
let client_conn: &mut ProtocolConnection<'static> =
|
||||||
|
unsafe { mem::transmute(&mut client_conn) };
|
||||||
|
let server_conn: &mut ProtocolConnection<'static> =
|
||||||
|
unsafe { mem::transmute(&mut server_conn) };
|
||||||
|
|
||||||
|
let (mut client_write_conn, mut client_read_conn) =
|
||||||
|
client_conn.split_conn().expect(
|
||||||
|
"Error copying from client to backend");
|
||||||
|
let (mut server_write_conn, mut server_read_conn) =
|
||||||
|
server_conn.split_conn().expect(
|
||||||
|
"Error copying from backend to client");
|
||||||
|
|
||||||
// Forward from client to backend
|
// Forward from client to backend
|
||||||
let to_backend = tokio::spawn(client_conn.forward_play(&mut server_conn));
|
let to_backend = tokio::spawn(async move {
|
||||||
|
client_read_conn.forward_play(&mut server_write_conn).await.expect(
|
||||||
|
"Error copying from client to backend");
|
||||||
|
});
|
||||||
|
|
||||||
// Forward from backend to client
|
// Forward from backend to client
|
||||||
// let to_client = tokio::spawn(async move {
|
let to_client = tokio::spawn(async move {
|
||||||
// io::copy(
|
server_read_conn.forward_play(&mut client_write_conn).await.expect(
|
||||||
// &mut server_conn.stream_read,
|
"Error copying from backend to client");
|
||||||
// &mut client_conn.stream_write,
|
});
|
||||||
// ).await.expect(
|
|
||||||
// "Error copying from backend to client");
|
|
||||||
// });
|
|
||||||
let to_client = tokio::spawn(server_conn.forward_play(&mut client_conn));
|
|
||||||
|
|
||||||
tokio::try_join!(to_backend, to_client)?;
|
tokio::try_join!(to_backend, to_client).expect(
|
||||||
|
"Error copying between the client and backend");
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use rsa::RsaPrivateKey;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum OnlineStatus {
|
pub enum OnlineStatus {
|
||||||
|
@ -16,6 +17,7 @@ pub struct ProxyInfo {
|
||||||
pub online_status: OnlineStatus,
|
pub online_status: OnlineStatus,
|
||||||
pub backend_addr: String,
|
pub backend_addr: String,
|
||||||
pub backend_port: u16,
|
pub backend_port: u16,
|
||||||
|
pub private_key: RsaPrivateKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyInfo {
|
impl ProxyInfo {
|
||||||
|
|
|
@ -13,6 +13,8 @@ use purple_cello_mc_protocol::{
|
||||||
login,
|
login,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::listener;
|
||||||
|
|
||||||
const EXPIRATION_DURATION: Duration = Duration::from_secs(3600);
|
const EXPIRATION_DURATION: Duration = Duration::from_secs(3600);
|
||||||
|
|
||||||
struct CachedWhitelist {
|
struct CachedWhitelist {
|
||||||
|
@ -150,27 +152,46 @@ fn check_player_whitelist(player: Player) -> PlayerAllowed {
|
||||||
PlayerAllowed::False("Invalid UUID".to_string())
|
PlayerAllowed::False("Invalid UUID".to_string())
|
||||||
} else if invalid_username {
|
} else if invalid_username {
|
||||||
PlayerAllowed::False(
|
PlayerAllowed::False(
|
||||||
"Invalid Username, please contact the server admin to update your \
|
"Invalid Username!\nPlease contact the admins to update your \
|
||||||
username: purplecelloserver@gmail.com".to_string()
|
username:\npurplecelloserver@gmail.com".to_string()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PlayerAllowed::False("Not whitelisted on this server".to_string())
|
PlayerAllowed::False("Not whitelisted on this server.\n\
|
||||||
|
Please direct whitelist requests to the admins:\n\
|
||||||
|
purplecelloserver@gmail.com".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_player(player: Player) -> Result<PlayerAllowed> {
|
async fn check_player_online(
|
||||||
|
proxy_info: &listener::ProxyInfo,
|
||||||
|
player: Player,
|
||||||
|
client_conn: &mut ProtocolConnection<'_>,
|
||||||
|
) -> Result<PlayerAllowed> {
|
||||||
|
let encryption_request = client_conn.create_encryption_request(
|
||||||
|
proxy_info.private_key.clone())?;
|
||||||
|
encryption_request.write(client_conn).await?;
|
||||||
|
let encryption_response =
|
||||||
|
login::serverbound::EncryptionResponse::read(client_conn).await?;
|
||||||
|
client_conn.handle_encryption_response(encryption_response)?;
|
||||||
|
// TODO: Make authentication verification request
|
||||||
|
Ok(check_player_whitelist(player))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_player_offline(player: Player) -> Result<PlayerAllowed> {
|
||||||
Ok(check_player_whitelist(player))
|
Ok(check_player_whitelist(player))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn respond_login(
|
pub async fn respond_login(
|
||||||
|
proxy_info: &listener::ProxyInfo,
|
||||||
client_conn: &mut ProtocolConnection<'_>,
|
client_conn: &mut ProtocolConnection<'_>,
|
||||||
server_conn: &mut ProtocolConnection<'_>,
|
server_conn: &mut ProtocolConnection<'_>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let proxy_login = login_to_proxy(client_conn).await?;
|
let proxy_login = login_to_proxy(proxy_info, client_conn).await?;
|
||||||
match proxy_login {
|
match proxy_login {
|
||||||
PlayerAllowed::True(player) => {
|
PlayerAllowed::True(player) => {
|
||||||
println!("Player allowed");
|
println!("Player allowed");
|
||||||
login_to_backend(
|
login_to_backend(
|
||||||
|
proxy_info,
|
||||||
player,
|
player,
|
||||||
client_conn,
|
client_conn,
|
||||||
server_conn,
|
server_conn,
|
||||||
|
@ -188,6 +209,7 @@ pub async fn respond_login(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login_to_proxy(
|
async fn login_to_proxy(
|
||||||
|
proxy_info: &listener::ProxyInfo,
|
||||||
client_conn: &mut ProtocolConnection<'_>,
|
client_conn: &mut ProtocolConnection<'_>,
|
||||||
) -> Result<PlayerAllowed> {
|
) -> Result<PlayerAllowed> {
|
||||||
println!("Logging into proxy");
|
println!("Logging into proxy");
|
||||||
|
@ -200,10 +222,16 @@ async fn login_to_proxy(
|
||||||
player_uuid: start_packet.player_uuid,
|
player_uuid: start_packet.player_uuid,
|
||||||
};
|
};
|
||||||
|
|
||||||
check_player(player)
|
match proxy_info.online_status {
|
||||||
|
listener::OnlineStatus::Online =>
|
||||||
|
check_player_online(proxy_info, player, client_conn).await,
|
||||||
|
listener::OnlineStatus::Offline =>
|
||||||
|
check_player_offline(player),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login_to_backend(
|
async fn login_to_backend(
|
||||||
|
proxy_info: &listener::ProxyInfo,
|
||||||
player: Player,
|
player: Player,
|
||||||
client_conn: &mut ProtocolConnection<'_>,
|
client_conn: &mut ProtocolConnection<'_>,
|
||||||
server_conn: &mut ProtocolConnection<'_>,
|
server_conn: &mut ProtocolConnection<'_>,
|
||||||
|
@ -211,8 +239,8 @@ async fn login_to_backend(
|
||||||
println!("Logging into backend");
|
println!("Logging into backend");
|
||||||
handshake::serverbound::Handshake {
|
handshake::serverbound::Handshake {
|
||||||
protocol_version: mc_types::VERSION_PROTOCOL,
|
protocol_version: mc_types::VERSION_PROTOCOL,
|
||||||
server_address: "localhost".to_string(),
|
server_address: proxy_info.backend_addr.clone(),
|
||||||
server_port: 25565,
|
server_port: proxy_info.backend_port,
|
||||||
next_state: 2,
|
next_state: 2,
|
||||||
}.write(server_conn).await?;
|
}.write(server_conn).await?;
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,23 @@
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
use purple_cello_mc_protocol::encrypt;
|
||||||
|
|
||||||
mod status_handle;
|
mod status_handle;
|
||||||
mod login_handle;
|
mod login_handle;
|
||||||
mod client;
|
mod client;
|
||||||
mod listener;
|
mod listener;
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let private_key = encrypt::generate_rsa_keys()?;
|
||||||
let offline_info = listener::ProxyInfo{
|
let offline_info = listener::ProxyInfo{
|
||||||
proxy_addr: "127.0.0.1".to_string(),
|
proxy_addr: "127.0.0.1".to_string(),
|
||||||
proxy_port: 25565,
|
proxy_port: 25565,
|
||||||
online_status: listener::OnlineStatus::Offline,
|
online_status: listener::OnlineStatus::Offline,
|
||||||
backend_addr: "127.0.0.1".to_string(),
|
backend_addr: "127.0.0.1".to_string(),
|
||||||
backend_port: 25564,
|
backend_port: 25564,
|
||||||
|
private_key: private_key.clone(),
|
||||||
};
|
};
|
||||||
let online_info = listener::ProxyInfo{
|
let online_info = listener::ProxyInfo{
|
||||||
proxy_addr: "127.0.0.1".to_string(),
|
proxy_addr: "127.0.0.1".to_string(),
|
||||||
|
@ -23,6 +26,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
online_status: listener::OnlineStatus::Online,
|
online_status: listener::OnlineStatus::Online,
|
||||||
backend_addr: "127.0.0.1".to_string(),
|
backend_addr: "127.0.0.1".to_string(),
|
||||||
backend_port: 25564,
|
backend_port: 25564,
|
||||||
|
private_key: private_key.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let listener_offline: listener::TcpListenerWrapper =
|
let listener_offline: listener::TcpListenerWrapper =
|
||||||
|
|
Loading…
Reference in New Issue