From b3424a13a43b6945f3ec4893df5aa92d70407ced Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Wed, 30 Jul 2025 01:32:29 +0200 Subject: [PATCH] Introduce limit for the maximum number of connected clients per address --- .../geyser/network/UpstreamPacketHandler.java | 20 +++++++++++++++++-- .../geyser/session/SessionManager.java | 13 +++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 3a36dc064..c0c2362dc 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -89,6 +89,7 @@ import java.util.concurrent.TimeUnit; public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean networkSettingsRequested = false; + private boolean receivedLoginPacket = false; private final Deque packsToSend = new ArrayDeque<>(); private final CompressionStrategy compressionStrategy; @@ -188,11 +189,23 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { return PacketSignal.HANDLED; } + if (receivedLoginPacket) { + GeyserImpl.getInstance().getLogger().warning("Received duplicate login packet from " + session.name()); + session.disconnect("Received duplicate login packet!"); + return PacketSignal.HANDLED; + } + receivedLoginPacket = true; + if (!networkSettingsRequested) { session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.outdated.client", GameProtocol.getAllSupportedBedrockVersions())); return PacketSignal.HANDLED; } + if (!geyser.getSessionManager().addPendingSession(session)) { + session.disconnect("Too many connections are originating from this location!"); + return PacketSignal.HANDLED; + } + // Set the block translation based off of version session.setBlockMappings(BlockRegistries.BLOCKS.forVersion(loginPacket.getProtocolVersion())); session.setItemMappings(Registries.ITEMS.forVersion(loginPacket.getProtocolVersion())); @@ -204,6 +217,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { return PacketSignal.HANDLED; } + if (GeyserImpl.getInstance().connectionByXuid(session.xuid()) != null) { + session.disconnect(GeyserLocale.getLocaleStringLog("geyser.auth.already_loggedin", session.name())); + return PacketSignal.HANDLED; + } + // Fire SessionInitializeEvent here as we now know the client data geyser.eventBus().fire(new SessionInitializeEvent(session)); @@ -211,8 +229,6 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS); session.sendUpstreamPacket(playStatus); - geyser.getSessionManager().addPendingSession(session); - this.resourcePackLoadEvent = new SessionLoadResourcePacksEventImpl(session); this.geyser.eventBus().fire(this.resourcePackLoadEvent); diff --git a/core/src/main/java/org/geysermc/geyser/session/SessionManager.java b/core/src/main/java/org/geysermc/geyser/session/SessionManager.java index 14d2a2eff..ef156bc18 100644 --- a/core/src/main/java/org/geysermc/geyser/session/SessionManager.java +++ b/core/src/main/java/org/geysermc/geyser/session/SessionManager.java @@ -61,10 +61,19 @@ public final class SessionManager { @Getter(AccessLevel.PACKAGE) private final Map connectedClients = new ConcurrentHashMap<>(); + /** + * Specifies the maximum amount of connections per address + */ + private final static int MAX_CONNECTIONS_PER_ADDRESS = Integer.getInteger("Geyser.MaxConnectionsPerAddress", 10); + /** * Called once the player has successfully authenticated to the Geyser server. */ - public void addPendingSession(GeyserSession session) { + public boolean addPendingSession(GeyserSession session) { + if (getAddressMultiplier(session.getSocketAddress().getAddress()) > MAX_CONNECTIONS_PER_ADDRESS) { + return false; + } + pendingSessions.add(session); connectedClients.compute(session.getSocketAddress().getAddress(), (key, count) -> { if (count == null) { @@ -74,6 +83,8 @@ public final class SessionManager { count.incrementAndGet(); return count; }); + + return true; } /**