mirror of
https://github.com/PaperMC/Waterfall.git
synced 2024-12-27 11:07:39 +01:00
431 lines
20 KiB
Diff
431 lines
20 KiB
Diff
From d1d73f437bc7e61be80eed98c4d8485f53b38a02 Mon Sep 17 00:00:00 2001
|
|
From: linsaftw <25271111+linsaftw@users.noreply.github.com>
|
|
Date: Fri, 30 Apr 2021 22:54:44 -0300
|
|
Subject: [PATCH] Firewall System
|
|
|
|
|
|
diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java
|
|
index 8957c79a..fd889644 100644
|
|
--- a/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java
|
|
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java
|
|
@@ -6,6 +6,7 @@ import java.util.logging.Logger;
|
|
import dev._2lstudios.flamecord.configuration.FlameCordConfiguration;
|
|
import dev._2lstudios.flamecord.configuration.MessagesConfiguration;
|
|
import dev._2lstudios.flamecord.configuration.ModulesConfiguration;
|
|
+import dev._2lstudios.flamecord.firewall.FirewallManager;
|
|
import lombok.Getter;
|
|
import net.md_5.bungee.config.ConfigurationProvider;
|
|
import net.md_5.bungee.config.YamlConfiguration;
|
|
@@ -14,12 +15,15 @@ public class FlameCord {
|
|
@Getter
|
|
private static FlameCord instance;
|
|
@Getter
|
|
+ private final FirewallManager firewallManager;
|
|
+ @Getter
|
|
private final FlameCordConfiguration flameCordConfiguration;
|
|
@Getter
|
|
private final ModulesConfiguration modulesConfiguration;
|
|
@Getter
|
|
private final MessagesConfiguration messagesConfiguration;
|
|
@Getter
|
|
+ private final Thread thread;
|
|
private boolean running = true;
|
|
|
|
public static void renew(final Logger logger, final Collection<String> whitelistedAddresses) {
|
|
@@ -36,7 +40,29 @@ public class FlameCord {
|
|
final ConfigurationProvider configurationProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
|
|
|
|
this.flameCordConfiguration = new FlameCordConfiguration(configurationProvider);
|
|
+ this.firewallManager = new FirewallManager(logger, whitelistedAddresses,
|
|
+ flameCordConfiguration.getFirewallSeconds());
|
|
this.modulesConfiguration = new ModulesConfiguration(configurationProvider);
|
|
this.messagesConfiguration = new MessagesConfiguration(logger, configurationProvider);
|
|
+ this.thread = new Thread() {
|
|
+ @Override
|
|
+ public void run() {
|
|
+ while (running) {
|
|
+ try {
|
|
+ sleep(1000L);
|
|
+
|
|
+ if (!running) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ firewallManager.tick();
|
|
+ } catch (final Exception e) {
|
|
+ // Ignored
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ this.thread.start();
|
|
}
|
|
}
|
|
\ No newline at end of file
|
|
diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java
|
|
index 81ded224..8bb61ac1 100644
|
|
--- a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java
|
|
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java
|
|
@@ -12,6 +12,15 @@ import net.md_5.bungee.config.Configuration;
|
|
import net.md_5.bungee.config.ConfigurationProvider;
|
|
|
|
public class FlameCordConfiguration {
|
|
+ @Getter
|
|
+ private boolean firewallNotify = true;
|
|
+ @Getter
|
|
+ private boolean firewallEnabled = true;
|
|
+ @Getter
|
|
+ private int firewallSeconds = 60;
|
|
+ @Getter
|
|
+ private Collection<String> firewallNames = new HashSet<>(Arrays.asList(new String[] { "mcspam" }));
|
|
+
|
|
public FlameCordConfiguration(final ConfigurationProvider configurationProvider) {
|
|
try {
|
|
final String fileName = "./flamecord.yml";
|
|
@@ -25,6 +34,11 @@ public class FlameCordConfiguration {
|
|
configuration = configurationProvider.load(configurationFile);
|
|
}
|
|
|
|
+ this.firewallEnabled = setIfUnexistant("firewall.enabled", this.firewallEnabled, configuration);
|
|
+ this.firewallNotify = setIfUnexistant("firewall.notify", this.firewallNotify, configuration);
|
|
+ this.firewallSeconds = setIfUnexistant("firewall.seconds", this.firewallSeconds, configuration);
|
|
+ this.firewallNames = setIfUnexistant("firewall.names", this.firewallNames, configuration);
|
|
+
|
|
if (!configurationExists) {
|
|
configurationProvider.save(configuration, configurationFile);
|
|
}
|
|
diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java
|
|
index ebfaa761..c88077ad 100644
|
|
--- a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java
|
|
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java
|
|
@@ -82,9 +82,17 @@ public class MessagesConfiguration {
|
|
setIfUnexistant("command_ip", "&9IP of {0} is {1}", configuration);
|
|
|
|
// FlameCord
|
|
+ setIfUnexistant("firewall_added", "&e{0}&c had been firewalled from the proxy!", configuration);
|
|
+ setIfUnexistant("firewall_blocked", "&e{0}&c is firewalled from the proxy, request blocked!",
|
|
+ configuration);
|
|
+ setIfUnexistant("firewall_info",
|
|
+ "&aThere are&b {0} &aaddresses firewalled!\n&aThe firewall will clear in &b{1} &aseconds!",
|
|
+ configuration);
|
|
+ setIfUnexistant("firewall_cleared", "&b{0}&a addresses had been automatically removed from the firewall!",
|
|
+ configuration);
|
|
setIfUnexistant("flamecord_reload", "&aAll files had been successfully reloaded!", configuration);
|
|
setIfUnexistant("flamecord_help",
|
|
- "&aFlameCord&b {0}&a by&b LinsaFTW&a &&b Sammwy&r\n&e /flamecord reload&7 >&b Reloads FlameCord files!\n&e /flamecord help&7 >&b Shows this message!",
|
|
+ "&aFlameCord&b {0}&a by&b LinsaFTW&a &&b Sammwy&r\n&e /flamecord reload&7 >&b Reloads FlameCord files!\n&e /flamecord firewall&7 >&b Shows information about the Firewall!\n&e /flamecord help&7 >&b Shows this message!",
|
|
configuration);
|
|
setIfUnexistant("flamecord_nopermission", "&cYou don't have permission to do this!", configuration);
|
|
|
|
diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java
|
|
new file mode 100644
|
|
index 00000000..dfb5c6d3
|
|
--- /dev/null
|
|
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java
|
|
@@ -0,0 +1,120 @@
|
|
+package dev._2lstudios.flamecord.firewall;
|
|
+
|
|
+import java.net.InetSocketAddress;
|
|
+import java.net.SocketAddress;
|
|
+import java.util.Collection;
|
|
+import java.util.HashSet;
|
|
+import java.util.logging.Logger;
|
|
+
|
|
+import dev._2lstudios.flamecord.FlameCord;
|
|
+import dev._2lstudios.flamecord.configuration.FlameCordConfiguration;
|
|
+import lombok.Getter;
|
|
+
|
|
+public class FirewallManager {
|
|
+ private final Logger logger;
|
|
+ private final Collection<String> whitelistedAddresses;
|
|
+ private final Collection<String> firewalled;
|
|
+ private final int defaultSeconds;
|
|
+ @Getter
|
|
+ private int seconds;
|
|
+
|
|
+ public FirewallManager(final Logger logger, final Collection<String> whitelistedAddresses,
|
|
+ final int defaultSeconds) {
|
|
+ this.logger = logger;
|
|
+ this.whitelistedAddresses = whitelistedAddresses;
|
|
+ this.firewalled = new HashSet<>();
|
|
+ this.defaultSeconds = defaultSeconds;
|
|
+ this.seconds = defaultSeconds;
|
|
+ }
|
|
+
|
|
+ public boolean isWhitelisted(final SocketAddress address) {
|
|
+ final String addressString = address.toString();
|
|
+
|
|
+ for (final String whitelistedAddressString : whitelistedAddresses) {
|
|
+ if (addressString.endsWith(whitelistedAddressString)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public void addFirewalled(final SocketAddress address) {
|
|
+ if (address == null) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (FlameCord.getInstance().getFlameCordConfiguration().isFirewallEnabled() && !isWhitelisted(address)) {
|
|
+ final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address;
|
|
+ final String hostString = iNetSocketAddress.getHostString();
|
|
+
|
|
+ if (!this.firewalled.contains(hostString)) {
|
|
+ this.firewalled.add(hostString);
|
|
+ logAdded(address);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void logAdded(final SocketAddress address) {
|
|
+ final FlameCord flameCord = FlameCord.getInstance();
|
|
+ final FlameCordConfiguration flameCordConfiguration = flameCord.getFlameCordConfiguration();
|
|
+
|
|
+ if (flameCordConfiguration.isFirewallNotify()) {
|
|
+ final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address;
|
|
+ final String hostString = iNetSocketAddress.getHostString();
|
|
+
|
|
+ this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_added", hostString));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void logBlocked(final SocketAddress address) {
|
|
+ final FlameCord flameCord = FlameCord.getInstance();
|
|
+ final FlameCordConfiguration flameCordConfiguration = flameCord.getFlameCordConfiguration();
|
|
+
|
|
+ if (flameCordConfiguration.isFirewallNotify()) {
|
|
+ final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address;
|
|
+ final String hostString = iNetSocketAddress.getHostString();
|
|
+
|
|
+ this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_blocked", hostString));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public Collection<String> getFirewalled() {
|
|
+ return this.firewalled;
|
|
+ }
|
|
+
|
|
+ public boolean isFirewalled(final SocketAddress address) {
|
|
+ final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address;
|
|
+
|
|
+ return this.firewalled.contains(iNetSocketAddress.getHostString());
|
|
+ }
|
|
+
|
|
+ public boolean isFirewalled(final String name) {
|
|
+ final String nameLowerCase = name.toLowerCase();
|
|
+
|
|
+ for (final String string : FlameCord.getInstance().getFlameCordConfiguration().getFirewallNames()) {
|
|
+ if (nameLowerCase.contains(string)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public void tick() {
|
|
+ if (--seconds <= 0) {
|
|
+ final FlameCord flameCord = FlameCord.getInstance();
|
|
+ final int size = this.firewalled.size();
|
|
+
|
|
+ if (size > 0) {
|
|
+ if (flameCord.getFlameCordConfiguration().isFirewallNotify()) {
|
|
+ this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_cleared", size));
|
|
+ }
|
|
+
|
|
+ this.firewalled.clear();
|
|
+ }
|
|
+
|
|
+ this.seconds = defaultSeconds;
|
|
+ }
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java
|
|
index f0761a4f..31873afc 100644
|
|
--- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java
|
|
+++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java
|
|
@@ -46,8 +46,14 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
|
|
final int capacity = in.capacity();
|
|
|
|
if (readableBytes > 2097152) {
|
|
+ // FlameCord - Firewall system
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ctx.channel().remoteAddress());
|
|
+
|
|
throw new FastDecoderException("Error decoding packet with too many readableBytes: " + readableBytes);
|
|
} else if (capacity > 2097152) {
|
|
+ // FlameCord - Firewall system
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ctx.channel().remoteAddress());
|
|
+
|
|
throw new FastDecoderException("Error decoding packet with too big capacity: " + capacity);
|
|
}
|
|
}
|
|
@@ -108,6 +114,9 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
|
|
} else {
|
|
packetTypeStr = "unknown";
|
|
}
|
|
+
|
|
+ // FlameCord - Firewall system
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ctx.channel().remoteAddress());
|
|
throw new FastDecoderException("Error decoding packet " + packetTypeStr + " with contents:\n" + ByteBufUtil.prettyHexDump(slice), e); // Waterfall
|
|
} finally
|
|
{
|
|
diff --git a/proxy/src/main/java/dev/_2lstudios/flamecord/commands/FlameCordCommand.java b/proxy/src/main/java/dev/_2lstudios/flamecord/commands/FlameCordCommand.java
|
|
index bf6f8538..fa0b59c2 100644
|
|
--- a/proxy/src/main/java/dev/_2lstudios/flamecord/commands/FlameCordCommand.java
|
|
+++ b/proxy/src/main/java/dev/_2lstudios/flamecord/commands/FlameCordCommand.java
|
|
@@ -5,6 +5,7 @@ import java.util.HashSet;
|
|
|
|
import dev._2lstudios.flamecord.FlameCord;
|
|
import dev._2lstudios.flamecord.configuration.MessagesConfiguration;
|
|
+import dev._2lstudios.flamecord.firewall.FirewallManager;
|
|
import net.md_5.bungee.BungeeCord;
|
|
import net.md_5.bungee.api.CommandSender;
|
|
import net.md_5.bungee.api.chat.TextComponent;
|
|
@@ -30,6 +31,15 @@ private final BungeeCord bungeeCord;
|
|
final String arg0 = args[0];
|
|
|
|
switch (arg0) {
|
|
+ case "firewall": {
|
|
+ final FirewallManager firewallManager = flameCord.getFirewallManager();
|
|
+ final int amount = firewallManager.getFirewalled().size(),
|
|
+ seconds = firewallManager.getSeconds();
|
|
+
|
|
+ sender.sendMessage(TextComponent.fromLegacyText(
|
|
+ messagesConfiguration.getTranslation("firewall_info", amount, seconds)));
|
|
+ break;
|
|
+ }
|
|
case "reload": {
|
|
// FlameCord - Collect ips from servers
|
|
final Collection<String> whitelistedAddresses = new HashSet<>();
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
|
|
index 494375cd..aedfece3 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
|
|
@@ -165,6 +165,9 @@ public class ServerConnector extends PacketHandler
|
|
{
|
|
if ( packet.packet == null )
|
|
{
|
|
+ // FlameCord - Firewall on unexpected packet
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ch.getRemoteAddress());
|
|
+
|
|
throw new QuietException( "Unexpected packet received during server connector process!\n" + BufUtil.dump(packet.buf, 16) );
|
|
}
|
|
}
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
|
|
index deee607d..3720825a 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
|
|
@@ -154,6 +154,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
|
{
|
|
if ( packet.packet == null )
|
|
{
|
|
+ // FlameCord - Firewall on unexpected packet
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ch.getRemoteAddress());
|
|
+
|
|
throw new QuietException( "Unexpected packet received during server login process!\n" + BufUtil.dump(packet.buf, 16) );
|
|
}
|
|
}
|
|
@@ -396,6 +399,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
|
}
|
|
break;
|
|
default:
|
|
+ // FlameCord - Firewall on unexpected packet
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ch.getRemoteAddress());
|
|
+
|
|
throw new QuietException( "Cannot request protocol " + handshake.getRequestedProtocol() );
|
|
}
|
|
}
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java
|
|
index 423af854..70917b0b 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java
|
|
@@ -2,6 +2,7 @@ package net.md_5.bungee.connection;
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
+import dev._2lstudios.flamecord.FlameCord;
|
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|
import lombok.RequiredArgsConstructor;
|
|
import net.md_5.bungee.BungeeCord;
|
|
@@ -59,6 +60,9 @@ public class PingHandler extends PacketHandler
|
|
{
|
|
if ( packet.packet == null )
|
|
{
|
|
+ // FlameCord - Firewall on unexpected packet
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(channel.getRemoteAddress());
|
|
+
|
|
throw new QuietException( "Unexpected packet received during ping process! " + BufUtil.dump( packet.buf, 16 ) );
|
|
}
|
|
}
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java
|
|
index 7f18b564..616651ba 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java
|
|
@@ -11,6 +11,7 @@ import io.netty.handler.codec.haproxy.HAProxyMessage;
|
|
import io.netty.handler.timeout.ReadTimeoutException;
|
|
import java.io.IOException;
|
|
import java.net.InetSocketAddress;
|
|
+import java.net.SocketAddress;
|
|
import java.util.logging.Level;
|
|
import net.md_5.bungee.api.ProxyServer;
|
|
import net.md_5.bungee.connection.CancelSendSignal;
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java
|
|
index 1d86aa63..915c162f 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java
|
|
@@ -63,6 +63,13 @@ public class PipelineUtils
|
|
{
|
|
SocketAddress remoteAddress = ( ch.remoteAddress() == null ) ? ch.parent().localAddress() : ch.remoteAddress();
|
|
|
|
+ // FlameCord - Firewall system
|
|
+ if ( FlameCord.getInstance().getFirewallManager().isFirewalled( remoteAddress ) ) {
|
|
+ FlameCord.getInstance().getFirewallManager().logBlocked( remoteAddress );
|
|
+ ch.close();
|
|
+ return;
|
|
+ }
|
|
+
|
|
if ( BungeeCord.getInstance().getConnectionThrottle() != null && BungeeCord.getInstance().getConnectionThrottle().throttle( remoteAddress ) )
|
|
{
|
|
ch.close();
|
|
diff --git a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
|
|
index b3bdfd05..49d53f17 100644
|
|
--- a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
|
|
+++ b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
|
|
@@ -2,6 +2,8 @@ package net.md_5.bungee.query;
|
|
|
|
import com.google.common.cache.Cache;
|
|
import com.google.common.cache.CacheBuilder;
|
|
+
|
|
+import dev._2lstudios.flamecord.FlameCord;
|
|
import io.github.waterfallmc.waterfall.QueryResult;
|
|
import io.github.waterfallmc.waterfall.event.ProxyQueryEvent;
|
|
import io.netty.buffer.ByteBuf;
|
|
@@ -70,6 +72,9 @@ public class QueryHandler extends SimpleChannelInboundHandler<DatagramPacket>
|
|
ByteBuf in = msg.content();
|
|
if ( in.readUnsignedByte() != 0xFE || in.readUnsignedByte() != 0xFD )
|
|
{
|
|
+ // FlameCord - Firewall system
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ctx.channel().remoteAddress());
|
|
+
|
|
bungee.getLogger().log( Level.WARNING, "Query - Incorrect magic!: {0}", msg.sender() );
|
|
// FlameCord - Close on incorrect magic
|
|
ctx.close();
|
|
@@ -164,6 +169,9 @@ public class QueryHandler extends SimpleChannelInboundHandler<DatagramPacket>
|
|
out.writeByte( 0x00 ); // Null
|
|
} else
|
|
{
|
|
+ // FlameCord - Firewall system
|
|
+ FlameCord.getInstance().getFirewallManager().addFirewalled(ctx.channel().remoteAddress());
|
|
+
|
|
// Error!
|
|
throw new IllegalStateException( "Invalid data request packet" );
|
|
}
|
|
--
|
|
2.31.1
|
|
|