From ef642961590a88c33081c5e44471fcdb2189d79d Mon Sep 17 00:00:00 2001 From: Terminator Date: Sat, 1 Oct 2022 19:42:43 +0200 Subject: [PATCH] Implement prevent-proxy-connections This adds the `prevent-proxy-connections` server property and implements it into valence. Note that if the server is in offline mode, this changes nothing. By default, proxy connections are allowed. Fixes #95 --- src/config.rs | 20 +++++++++++++++++++- src/server.rs | 17 ++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/config.rs b/src/config.rs index 1dd29b3..15dffc1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -95,6 +95,20 @@ pub trait Config: Sized + Send + Sync + UnwindSafe + RefUnwindSafe + 'static { true } + /// Called once at startup to get the "prevent-proxy-connections" option, + /// which determines if client IP validation should take place. + /// + /// When prevent_proxy_connections is enabled, clients can no longer log-in + /// if they connected to the yggdrasil server using a different IP. + /// + /// # Default Implementation + /// Proxy connections are allowed. + /// + /// Returns `false`. + fn prevent_proxy_connections(&self) -> bool { + false + } + /// Called once at startup to get the capacity of the buffer used to /// hold incoming packets. /// @@ -225,7 +239,11 @@ pub trait Config: Sized + Send + Sync + UnwindSafe + RefUnwindSafe + 'static { auth_digest: &str, player_ip: &IpAddr, ) -> String { - format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}&ip={player_ip}") + if self.prevent_proxy_connections() { + format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}&ip={player_ip}") + } else { + format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}") + } } /// Called after the server is created, but prior to accepting connections diff --git a/src/server.rs b/src/server.rs index 64e4a34..acbb2e7 100644 --- a/src/server.rs +++ b/src/server.rs @@ -46,6 +46,7 @@ use crate::protocol::packets::s2c::play::S2cPlayPacket; use crate::protocol::packets::s2c::status::{PingResponse, StatusResponse}; use crate::protocol::packets::Property; use crate::protocol::{BoundedArray, BoundedString, VarInt}; +use crate::text::Text; use crate::util::valid_username; use crate::world::Worlds; use crate::{ident, Ticks, PROTOCOL_VERSION, VERSION_NAME}; @@ -716,11 +717,17 @@ async fn handle_login( ); let resp = server.0.http_client.get(url).send().await?; - let status = resp.status(); - ensure!( - status.is_success(), - "session server GET request failed: {status}" - ); + match resp.status().as_u16() { + 200 => (), + 204 => { + let reason = Text::translate("multiplayer.disconnect.unverified_username"); + c.enc.write_packet(&DisconnectLogin { reason }).await?; + bail!("Could not verify username"); + } + status => { + bail!("session server GET request failed: {status}"); + } + } let data: AuthResponse = resp.json().await?;