Hijack login start packet to disconnect payer if server is sleeping

This commit is contained in:
timvisee 2021-11-07 18:07:24 +01:00
parent 645ea892cb
commit d742eca632
No known key found for this signature in database
GPG Key ID: B8DB720BC383E172
3 changed files with 34 additions and 4 deletions

View File

@ -5,7 +5,11 @@ pub const ADDRESS_PUBLIC: &str = "127.0.0.1:9090";
pub const ADDRESS_PROXY: &str = "127.0.0.1:9091"; pub const ADDRESS_PROXY: &str = "127.0.0.1:9091";
/// Server description shown when server is starting. /// Server description shown when server is starting.
pub const LABEL_SERVER_SLEEPING: &str = "Server sleeping...\nJoin to start it up §c♥"; pub const LABEL_SERVER_SLEEPING: &str = "Server is sleeping...\n§2☻ Join to start it up";
/// Server description shown when server is starting. /// Server description shown when server is starting.
pub const LABEL_SERVER_STARTING: &str = "Server starting...\nPlease wait §c♥"; pub const LABEL_SERVER_STARTING: &str = "§2☻ Server is starting...\n§7⌛ Please wait...";
/// Kick message shown when user tries to connect to starting server.
pub const LABEL_SERVER_STARTING_MESSAGE: &str =
"Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute.";

View File

@ -9,6 +9,7 @@ use minecraft_protocol::data::server_status::*;
use minecraft_protocol::decoder::Decoder; use minecraft_protocol::decoder::Decoder;
use minecraft_protocol::encoder::Encoder; use minecraft_protocol::encoder::Encoder;
use minecraft_protocol::version::v1_14_4::handshake::Handshake; use minecraft_protocol::version::v1_14_4::handshake::Handshake;
use minecraft_protocol::version::v1_14_4::login::LoginDisconnect;
use minecraft_protocol::version::v1_14_4::status::StatusResponse; use minecraft_protocol::version::v1_14_4::status::StatusResponse;
use tokio::io; use tokio::io;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
@ -34,12 +35,15 @@ async fn main() -> Result<(), ()> {
// Proxy all incomming connections // Proxy all incomming connections
while let Ok((inbound, _)) = listener.accept().await { while let Ok((inbound, _)) = listener.accept().await {
let client = Client::default(); let client = Client::default();
eprintln!("New client"); eprintln!("Client connected");
let transfer = proxy(client, inbound, ADDRESS_PROXY.to_string()).map(|r| { let transfer = proxy(client, inbound, ADDRESS_PROXY.to_string()).map(|r| {
if let Err(e) = r { if let Err(e) = r {
println!("Failed to proxy: {:?}", e); println!("Failed to proxy: {:?}", e);
} }
// TODO: proxy isn't closed for disconnected clients!
eprintln!("Client disconnected");
}); });
tokio::spawn(transfer); tokio::spawn(transfer);
@ -109,13 +113,15 @@ async fn proxy(client: Client, mut inbound: TcpStream, addr_target: String) -> R
let (client_send_queue, mut client_to_send) = unbounded_channel::<Vec<u8>>(); let (client_send_queue, mut client_to_send) = unbounded_channel::<Vec<u8>>();
let server_available = false;
let client_to_server = async { let client_to_server = async {
// Incoming buffer // Incoming buffer
let mut buf = BytesMut::new(); let mut buf = BytesMut::new();
loop { loop {
// In login state, proxy raw data // In login state, proxy raw data
if client.state() == ClientState::Login { if server_available && client.state() == ClientState::Login {
eprintln!("STARTED FULL PROXY"); eprintln!("STARTED FULL PROXY");
wo.writable().await.map_err(|_| ())?; wo.writable().await.map_err(|_| ())?;
@ -149,6 +155,25 @@ async fn proxy(client: Client, mut inbound: TcpStream, addr_target: String) -> R
eprintln!("PACKET ID: {}", packet.id); eprintln!("PACKET ID: {}", packet.id);
eprintln!("PACKET DATA: {:?}", packet.data); eprintln!("PACKET DATA: {:?}", packet.data);
// Hijack login start
if client.state() == ClientState::Login
&& packet.id == protocol::LOGIN_PACKET_ID_LOGIN_START
{
let packet = LoginDisconnect {
reason: Message::new(Payload::text(LABEL_SERVER_STARTING_MESSAGE)),
};
let mut data = Vec::new();
packet.encode(&mut data).map_err(|_| ())?;
let response = RawPacket::new(0, data).encode()?;
client_send_queue
.send(response)
.expect("failed to queue logout response");
break;
}
// Hijack handshake // Hijack handshake
if client.state() == ClientState::Handshake if client.state() == ClientState::Handshake
&& packet.id == protocol::STATUS_PACKET_ID_STATUS && packet.id == protocol::STATUS_PACKET_ID_STATUS

View File

@ -4,6 +4,7 @@ use crate::types;
pub const STATUS_PACKET_ID_STATUS: i32 = 0; pub const STATUS_PACKET_ID_STATUS: i32 = 0;
pub const STATUS_PACKET_ID_PING: i32 = 1; pub const STATUS_PACKET_ID_PING: i32 = 1;
pub const LOGIN_PACKET_ID_LOGIN_START: i32 = 0;
/// Client state. /// Client state.
// TODO: add encryption/compression state // TODO: add encryption/compression state