mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-22 18:45:54 +01:00
dc684c60d1
The new behavior of disconnect to block the current thread until the disconnect succeeded is better than throwing it off to happen at some point
109 lines
6.1 KiB
Diff
109 lines
6.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
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 2b86415e4ea197c5c44c23072c9a1cda595544a8..4d9f1fc884050993287adfa4578a87da710623fb 100644
|
|
--- a/src/main/java/net/minecraft/network/Connection.java
|
|
+++ b/src/main/java/net/minecraft/network/Connection.java
|
|
@@ -137,6 +137,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;
|
|
@@ -215,6 +231,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);
|