From 40ecbe82f9f81282b8fcd3cad5e12d98d3a4ef97 Mon Sep 17 00:00:00 2001 From: "Dylan T." Date: Thu, 16 Oct 2025 23:52:23 +0100 Subject: [PATCH] NetworkSession: allow discarding consecutive identical packets without decoding in certain cases (#6715) This allows packet handlers to tell the network session to discard any following packets if their buffers were identical to the current one. This is a very conservative and basic limiter. If we start having problems with multiple packets being spammed at once interleaved, this will become ineffective. However, for now, all the known spam bugs are of single packets, and the buffers of said packets are always identical. Dealing with interleaved packets would be quite a bit more complex. This mechanism is very simple and should avoid any negative side effects. --- src/network/FilterNoisyPacketException.php | 31 ++++++++++++++++ src/network/mcpe/NetworkSession.php | 35 +++++++++++++++++++ .../mcpe/handler/InGamePacketHandler.php | 7 ++-- 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/network/FilterNoisyPacketException.php diff --git a/src/network/FilterNoisyPacketException.php b/src/network/FilterNoisyPacketException.php new file mode 100644 index 000000000..878feebe7 --- /dev/null +++ b/src/network/FilterNoisyPacketException.php @@ -0,0 +1,31 @@ +noisyPacketBuffer){ + $this->noisyPacketsDropped++; + return true; + } + //stop filtering once we see a packet with a different buffer + //this won't be any good for interleaved spammy packets, but we haven't seen any of those so far, and this + //is the simplest and most conservative filter we can do + $this->noisyPacketBuffer = ""; + $this->noisyPacketsDropped = 0; + + return false; + } + /** * @throws PacketHandlingException */ @@ -400,9 +420,21 @@ class NetworkSession{ $decompressed = $payload; } + $count = 0; try{ $stream = new ByteBufferReader($decompressed); foreach(PacketBatch::decodeRaw($stream) as $buffer){ + if(++$count >= self::INCOMING_PACKET_BATCH_HARD_LIMIT){ + //this should be well more than enough; under normal conditions the game packet rate limiter + //will kick in well before this. This is only here to make sure we can't get huge batches of + //noisy packets to bog down the server, since those aren't counted by the regular limiter. + throw new PacketHandlingException("Reached hard limit of " . self::INCOMING_PACKET_BATCH_HARD_LIMIT . " per batch packet"); + } + + if($this->checkRepeatedPacketFilter($buffer)){ + continue; + } + $this->gamePacketLimiter->decrement(); $packet = $this->packetPool->getPacket($buffer); if($packet === null){ @@ -414,6 +446,8 @@ class NetworkSession{ }catch(PacketHandlingException $e){ $this->logger->debug($packet->getName() . ": " . base64_encode($buffer)); throw PacketHandlingException::wrap($e, "Error processing " . $packet->getName()); + }catch(FilterNoisyPacketException){ + $this->noisyPacketBuffer = $buffer; } if(!$this->isConnected()){ //handling this packet may have caused a disconnection @@ -432,6 +466,7 @@ class NetworkSession{ /** * @throws PacketHandlingException + * @throws FilterNoisyPacketException */ public function handleDataPacket(Packet $packet, string $buffer) : void{ if(!($packet instanceof ServerboundPacket)){ diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 0a296173a..35f48f767 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -44,6 +44,7 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\StringTag; +use pocketmine\network\FilterNoisyPacketException; use pocketmine\network\mcpe\InventoryManager; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\ActorEventPacket; @@ -490,7 +491,7 @@ class InGamePacketHandler extends PacketHandler{ $this->lastRightClickData = $data; $this->lastRightClickTime = microtime(true); if($spamBug){ - return true; + throw new FilterNoisyPacketException(); } //TODO: end hack for client spam bug @@ -748,7 +749,9 @@ class InGamePacketHandler extends PacketHandler{ } public function handleAnimate(AnimatePacket $packet) : bool{ - return true; //Not used + //this spams harder than a firehose on left click if "Improved Input Response" is enabled, and we don't even + //use it anyway :< + throw new FilterNoisyPacketException(); } public function handleContainerClose(ContainerClosePacket $packet) : bool{