fix DDoS when no data received from remote, better logging
This commit is contained in:
parent
fc34b1e328
commit
9426d23913
2 changed files with 48 additions and 29 deletions
|
|
@ -136,7 +136,10 @@ env!("CARGO_PKG_VERSION"));
|
||||||
let address = addrs_iter.next().unwrap();
|
let address = addrs_iter.next().unwrap();
|
||||||
|
|
||||||
match MinecraftStatus::fetch(address) {
|
match MinecraftStatus::fetch(address) {
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
|
println!(
|
||||||
|
"Failed to connect to {} ({}): {}",
|
||||||
|
query_address, address, e);
|
||||||
response.status(StatusCode::InternalServerError);
|
response.status(StatusCode::InternalServerError);
|
||||||
query_response = format!(
|
query_response = format!(
|
||||||
"<hr/>
|
"<hr/>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::io::{Error, ErrorKind, Read, Write, Result};
|
use std::io::{Error, ErrorKind, Read, Write, Result};
|
||||||
use std::net::{SocketAddr, TcpStream};
|
use std::net::{SocketAddr, TcpStream};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::leb128::{read_leb128, write_leb128};
|
use crate::leb128::{read_leb128, write_leb128};
|
||||||
|
|
||||||
|
|
@ -58,24 +59,32 @@ impl MinecraftStatus {
|
||||||
pub fn fetch(address: SocketAddr) -> Result<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()); }
|
if stream.is_err() { return Err(stream.unwrap_err()); }
|
||||||
|
|
||||||
//println!("Connected!");
|
//println!("Connected!");
|
||||||
|
|
||||||
let mut stream = stream.unwrap();
|
let mut stream = stream.unwrap();
|
||||||
|
|
||||||
let mut send_buffer: Vec<u8> = Vec::new();
|
let mut send_buffer: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
//println!("Sending payload...");
|
//println!("Sending payload...");
|
||||||
send_buffer.push(0x00);
|
|
||||||
write_leb128(&mut send_buffer, 769); // 1.21.4
|
send_buffer.push(0x00); // packet ID
|
||||||
write_leb128(&mut send_buffer, address.ip().to_string().len().try_into().unwrap());
|
write_leb128(&mut send_buffer, 769); // "i am 1.21.4"
|
||||||
send_buffer.extend_from_slice(address.ip().to_string().as_bytes());
|
write_leb128(&mut send_buffer, // upcoming address length
|
||||||
send_buffer.extend_from_slice(&address.port().to_be_bytes());
|
address.ip().to_string().len().try_into().unwrap());
|
||||||
write_leb128(&mut send_buffer, 1);
|
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, &send_buffer).unwrap();
|
||||||
|
|
||||||
send_packet(&mut stream, &[0x00]).unwrap();
|
send_packet(&mut stream, &[0x00]).unwrap();
|
||||||
|
|
||||||
|
//println!("Payload sent, receiving...\n");
|
||||||
|
|
||||||
let mut data: Vec<u8> = Vec::new();
|
let mut data: Vec<u8> = Vec::new();
|
||||||
let mut len: usize = 0;
|
let mut len: usize = 0;
|
||||||
let mut msg_len: usize = 0;
|
let mut msg_len: usize = 0;
|
||||||
|
|
@ -84,9 +93,17 @@ impl MinecraftStatus {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut recv_buffer: [u8; 10240] = [0; 10240];
|
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 {
|
if msg_len == 0 {
|
||||||
let mut val: u32;
|
let mut val: u32;
|
||||||
(val, offset) = read_leb128(&recv_buffer);
|
(val, offset) = read_leb128(&recv_buffer);
|
||||||
|
|
@ -107,7 +124,6 @@ impl MinecraftStatus {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let msg = std::str::from_utf8(&data[offset..]).unwrap().trim();
|
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 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();
|
let status: MinecraftStatus = serde_json::from_slice(sanitised.as_bytes()).unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue