aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0698-Add-packet-limiter-config.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0698-Add-packet-limiter-config.patch')
-rw-r--r--patches/server/0698-Add-packet-limiter-config.patch108
1 files changed, 108 insertions, 0 deletions
diff --git a/patches/server/0698-Add-packet-limiter-config.patch b/patches/server/0698-Add-packet-limiter-config.patch
new file mode 100644
index 0000000000..6b454b34dd
--- /dev/null
+++ b/patches/server/0698-Add-packet-limiter-config.patch
@@ -0,0 +1,108 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+Date: Fri, 30 Oct 2020 22:37:16 -0700
+Subject: [PATCH] Add packet limiter config
+
+Example config:
+packet-limiter:
+ kick-message: '&cSent too many packets'
+ limits:
+ all:
+ interval: 7.0
+ max-packet-rate: 500.0
+ ServerboundPlaceRecipePacket:
+ interval: 4.0
+ max-packet-rate: 5.0
+ action: DROP
+
+all section refers to all incoming packets, the action for all is
+hard coded to KICK.
+
+For specific limits, the section name is the class's name,
+and an action can be defined: DROP or KICK
+
+If interval or rate are less-than 0, the limit is ignored
+
+diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
+index 78e540af673c47f77b5efec4719d5e140da744c2..c0ea20dcee8bb293df96bc6ee019e50ad6b383fd 100644
+--- a/src/main/java/net/minecraft/network/Connection.java
++++ b/src/main/java/net/minecraft/network/Connection.java
+@@ -132,6 +132,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+ return null;
+ }
+ // Paper end - add utility methods
++ // Paper start - packet limiter
++ protected final Object PACKET_LIMIT_LOCK = new Object();
++ protected final @Nullable io.papermc.paper.util.IntervalledCounter allPacketCounts = io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.isEnabled() ? new io.papermc.paper.util.IntervalledCounter(
++ (long)(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.interval() * 1.0e9)
++ ) : null;
++ protected final java.util.Map<Class<? extends net.minecraft.network.protocol.Packet<?>>, io.papermc.paper.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>();
++
++ private boolean stopReadingPackets;
++ private void killForPacketSpam() {
++ this.sendPacket(new ClientboundDisconnectPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage)), PacketSendListener.thenRun(() -> {
++ this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage));
++ }), true);
++ this.setReadOnly();
++ this.stopReadingPackets = true;
++ }
++ // Paper end - packet limiter
+
+ public Connection(PacketFlow side) {
+ this.receiving = side;
+@@ -224,6 +240,55 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+ if (packetlistener == null) {
+ throw new IllegalStateException("Received a packet before the packet listener was initialized");
+ } else {
++ // Paper start - packet limiter
++ if (this.stopReadingPackets) {
++ return;
++ }
++ if (this.allPacketCounts != null ||
++ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
++ long time = System.nanoTime();
++ synchronized (PACKET_LIMIT_LOCK) {
++ if (this.allPacketCounts != null) {
++ this.allPacketCounts.updateAndAdd(1, time);
++ if (this.allPacketCounts.getRate() >= io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.maxPacketRate()) {
++ this.killForPacketSpam();
++ return;
++ }
++ }
++
++ for (Class<?> check = packet.getClass(); check != Object.class; check = check.getSuperclass()) {
++ io.papermc.paper.configuration.GlobalConfiguration.PacketLimiter.PacketLimit packetSpecificLimit =
++ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.get(check);
++ if (packetSpecificLimit == null || !packetSpecificLimit.isEnabled()) {
++ continue;
++ }
++ io.papermc.paper.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> {
++ return new io.papermc.paper.util.IntervalledCounter((long)(packetSpecificLimit.interval() * 1.0e9));
++ });
++ counter.updateAndAdd(1, time);
++ if (counter.getRate() >= packetSpecificLimit.maxPacketRate()) {
++ switch (packetSpecificLimit.action()) {
++ case DROP:
++ return;
++ case KICK:
++ String deobfedPacketName = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(check.getName());
++
++ String playerName;
++ if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
++ playerName = impl.getOwner().getName();
++ } else {
++ playerName = this.getLoggableAddress(net.minecraft.server.MinecraftServer.getServer().logIPs());
++ }
++
++ Connection.LOGGER.warn("{} kicked for packet spamming: {}", playerName, deobfedPacketName.substring(deobfedPacketName.lastIndexOf(".") + 1));
++ this.killForPacketSpam();
++ return;
++ }
++ }
++ }
++ }
++ }
++ // Paper end - packet limiter
+ if (packetlistener.shouldHandleMessage(packet)) {
+ try {
+ Connection.genericsFtw(packet, packetlistener);