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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
							 | 
						||
| 
								 | 
							
								--- a/src/main/java/net/minecraft/network/Connection.java
							 | 
						||
| 
								 | 
							
								+++ b/src/main/java/net/minecraft/network/Connection.java
							 | 
						||
| 
								 | 
							
								@@ -0,0 +0,0 @@ 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;
							 | 
						||
| 
								 | 
							
								@@ -0,0 +0,0 @@ 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);
							 |