#3733: Add incoming packet configuration options

This commit is contained in:
Outfluencer 2025-02-15 17:26:15 +11:00 committed by md_5
parent 774a6fd68c
commit 556a15a6f8
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
5 changed files with 96 additions and 15 deletions

View File

@ -69,6 +69,8 @@ public class Configuration implements ProxyConfig
private boolean preventProxyConnections;
private boolean forgeSupport;
private boolean rejectTransfers;
private int maxPacketsPerSecond = 1 << 12;
private int maxPacketDataPerSecond = 1 << 25;
public void load()
{
@ -105,6 +107,8 @@ public class Configuration implements ProxyConfig
preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections );
forgeSupport = adapter.getBoolean( "forge_support", forgeSupport );
rejectTransfers = adapter.getBoolean( "reject_transfers", rejectTransfers );
maxPacketsPerSecond = adapter.getInt( "max_packets_per_second", maxPacketsPerSecond );
maxPacketDataPerSecond = adapter.getInt( "max_packets_data_per_second", maxPacketDataPerSecond );
disabledCommands = new CaseInsensitiveSet( (Collection<String>) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) );

View File

@ -10,14 +10,19 @@ import io.netty.handler.timeout.ReadTimeoutException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.logging.Level;
import lombok.Setter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.connection.CancelSendSignal;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.PingHandler;
import net.md_5.bungee.connection.UpstreamBridge;
import net.md_5.bungee.protocol.BadPacketException;
import net.md_5.bungee.protocol.OverflowPacketException;
import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.util.PacketLimiter;
import net.md_5.bungee.util.QuietException;
/**
@ -28,6 +33,8 @@ import net.md_5.bungee.util.QuietException;
public class HandlerBoss extends ChannelInboundHandlerAdapter
{
@Setter
private PacketLimiter limiter;
private ChannelWrapper channel;
private PacketHandler handler;
private boolean healthCheck;
@ -107,20 +114,35 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
}
PacketWrapper packet = (PacketWrapper) msg;
if ( packet.packet != null )
{
Protocol nextProtocol = packet.packet.nextProtocol();
if ( nextProtocol != null )
{
channel.setDecodeProtocol( nextProtocol );
}
}
if ( handler != null )
try
{
boolean sendPacket = handler.shouldHandle( packet );
try
// check if the player exceeds packet limits, put inside try final, so we always release.
if ( limiter != null && !limiter.incrementAndCheck( packet.buf.readableBytes() ) )
{
// we shouldn't tell the player what limits he exceeds by default
// but if someone applies custom message we should allow them to display counter and bytes
channel.close( handler instanceof UpstreamBridge ? new Kick( TextComponent.fromLegacy( ProxyServer.getInstance().getTranslation( "packet_limit_kick", limiter.getCounter(), limiter.getDataCounter() ) ) ) : null );
// but the server admin should know
ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} exceeded packet limit ({1} packets and {2} bytes per second)", new Object[]
{
handler, limiter.getCounter(), limiter.getDataCounter()
} );
return;
}
if ( packet.packet != null )
{
Protocol nextProtocol = packet.packet.nextProtocol();
if ( nextProtocol != null )
{
channel.setDecodeProtocol( nextProtocol );
}
}
if ( handler != null )
{
boolean sendPacket = handler.shouldHandle( packet );
if ( sendPacket && packet.packet != null )
{
try
@ -135,10 +157,10 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
{
handler.handle( packet );
}
} finally
{
packet.trySingleRelease();
}
} finally
{
packet.trySingleRelease();
}
}

View File

@ -50,6 +50,7 @@ import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.Varint21FrameDecoder;
import net.md_5.bungee.protocol.channel.BungeeChannelInitializer;
import net.md_5.bungee.protocol.channel.ChannelAcceptor;
import net.md_5.bungee.util.PacketLimiter;
public class PipelineUtils
{
@ -79,8 +80,16 @@ public class PipelineUtils
ch.pipeline().addAfter( FRAME_DECODER, PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) );
ch.pipeline().addAfter( FRAME_PREPENDER_AND_COMPRESS, PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) );
ch.pipeline().addBefore( FRAME_PREPENDER_AND_COMPRESS, LEGACY_KICKER, legacyKicker );
ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( BungeeCord.getInstance(), listener ) );
HandlerBoss handlerBoss = ch.pipeline().get( HandlerBoss.class );
handlerBoss.setHandler( new InitialHandler( BungeeCord.getInstance(), listener ) );
int packetLimit = BungeeCord.getInstance().getConfig().getMaxPacketsPerSecond();
int packetDataLimit = BungeeCord.getInstance().getConfig().getMaxPacketDataPerSecond();
if ( packetLimit > 0 || packetDataLimit > 0 )
{
handlerBoss.setLimiter( new PacketLimiter( packetLimit, packetDataLimit ) );
}
if ( listener.isProxyProtocol() )
{
ch.pipeline().addFirst( new HAProxyMessageDecoder() );

View File

@ -0,0 +1,45 @@
package net.md_5.bungee.util;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class PacketLimiter
{
// max amount of packets allowed per second
private final int limit;
// max amount of data allowed per second
private final int dataLimit;
@Getter
private int counter;
@Getter
private int dataCounter;
private long nextSecond;
/**
* Counts the received packet amount and size.
*
* @param size size of the packet
* @return return false if the player should be kicked
*/
public boolean incrementAndCheck(int size)
{
counter++;
dataCounter += size;
if ( ( limit > 0 && counter > limit ) || ( dataLimit > 0 && dataCounter > dataLimit ) )
{
long now = System.currentTimeMillis();
if ( nextSecond > now )
{
return false;
}
nextSecond = now + 1000;
counter = 0;
dataCounter = 0;
}
return true;
}
}

View File

@ -41,3 +41,4 @@ command_ip=\u00a79IP of {0} is {1}
illegal_chat_characters=\u00a7cIllegal characters in chat ({0})
kick_message=\u00a7cYou have been kicked off the proxy.
reject_transfer=\u00a7cYour transfer was rejected.
packet_limit_kick=\u00a7cYou have sent too many packets