#3733: Add incoming packet configuration options
This commit is contained in:
parent
774a6fd68c
commit
556a15a6f8
@ -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" ) ) );
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() );
|
||||
|
45
proxy/src/main/java/net/md_5/bungee/util/PacketLimiter.java
Normal file
45
proxy/src/main/java/net/md_5/bungee/util/PacketLimiter.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user