fix DDoS when no data received from remote, better logging

This commit is contained in:
ari melody 2026-04-17 15:58:03 +01:00
parent fc34b1e328
commit 9426d23913
Signed by: ari
GPG key ID: CF99829C92678188
2 changed files with 48 additions and 29 deletions

View file

@ -136,7 +136,10 @@ env!("CARGO_PKG_VERSION"));
let address = addrs_iter.next().unwrap();
match MinecraftStatus::fetch(address) {
Err(_) => {
Err(e) => {
println!(
"Failed to connect to {} ({}): {}",
query_address, address, e);
response.status(StatusCode::InternalServerError);
query_response = format!(
"<hr/>

View file

@ -1,5 +1,6 @@
use std::io::{Error, ErrorKind, Read, Write, Result};
use std::net::{SocketAddr, TcpStream};
use std::time::Duration;
use crate::leb128::{read_leb128, write_leb128};
@ -56,26 +57,34 @@ pub struct MinecraftStatus {
impl MinecraftStatus {
pub fn fetch(address: SocketAddr) -> Result<MinecraftStatus> {
// println!("Connecting to {address}...");
//println!("Connecting to {address}...");
let stream = TcpStream::connect(address.to_string());
let stream = TcpStream::connect_timeout(&address, Duration::new(5, 0));
if stream.is_err() { return Err(stream.unwrap_err()); }
// println!("Connected!");
//println!("Connected!");
let mut stream = stream.unwrap();
let mut send_buffer: Vec<u8> = Vec::new();
// println!("Sending payload...");
send_buffer.push(0x00);
write_leb128(&mut send_buffer, 769); // 1.21.4
write_leb128(&mut send_buffer, address.ip().to_string().len().try_into().unwrap());
send_buffer.extend_from_slice(address.ip().to_string().as_bytes());
send_buffer.extend_from_slice(&address.port().to_be_bytes());
write_leb128(&mut send_buffer, 1);
//println!("Sending payload...");
send_buffer.push(0x00); // packet ID
write_leb128(&mut send_buffer, 769); // "i am 1.21.4"
write_leb128(&mut send_buffer, // upcoming address length
address.ip().to_string().len().try_into().unwrap());
send_buffer.extend_from_slice( // the address
address.ip().to_string().as_bytes());
send_buffer.extend_from_slice( // the port
&address.port().to_be_bytes());
write_leb128(&mut send_buffer, 1); // give me status please <3
send_packet(&mut stream, &send_buffer).unwrap();
send_packet(&mut stream, &[0x00]).unwrap();
//println!("Payload sent, receiving...\n");
let mut data: Vec<u8> = Vec::new();
let mut len: usize = 0;
let mut msg_len: usize = 0;
@ -84,9 +93,17 @@ impl MinecraftStatus {
loop {
let mut recv_buffer: [u8; 10240] = [0; 10240];
len += stream.read(&mut recv_buffer)?;
match stream.read(&mut recv_buffer) {
Ok(_len) => len += _len,
Err(e) => return Err(e)
};
if len == 0 {
return Err(Error::new(ErrorKind::HostUnreachable, format!("No data received from remote")));
}
//println!("< {} bytes\n", len);
if len > 0 {
if msg_len == 0 {
let mut val: u32;
(val, offset) = read_leb128(&recv_buffer);
@ -107,7 +124,6 @@ impl MinecraftStatus {
break;
}
}
}
let msg = std::str::from_utf8(&data[offset..]).unwrap().trim();
let sanitised: String = msg.chars().filter(|&c| c >= '\u{20}' || c == '\n' || c == '\r' || c == '\t').collect();
let status: MinecraftStatus = serde_json::from_slice(sanitised.as_bytes()).unwrap();