Waterfall/Waterfall-Proxy-Patches/0024-Firewall-System.patch
2022-02-14 19:57:35 -03:00

408 lines
18 KiB
Diff

From f879e684f4870dec0814a5353e82d1fd512f6933 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..374ff1b6 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","mcbot","mcstorm","dropbot","theresabot" }));
+
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 a32522fe..72d48d66 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("illegal_chat_characters", "&cIllegal characters in chat ({0})", 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 3992f521..7860d265 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
@@ -108,6 +108,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
} else {
packetTypeStr = "unknown";
}
+
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/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
index d637999f..d2ca464d 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
@@ -413,6 +413,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection
disconnect( bungee.getTranslation( "name_invalid" ) );
return;
}
+
+ // FlameCord - Firewall and close if username is blocked
+ if ( FlameCord.getInstance().getFirewallManager().isFirewalled( loginRequest.getData() ) )
+ {
+ FlameCord.getInstance().getFirewallManager().addFirewalled( ch.getRemoteAddress() );
+ ch.close();
+ return;
+ }
+
this.loginRequest = loginRequest;
int limit = BungeeCord.getInstance().config.getPlayerLimit();
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 3503c089..283b3134 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 89a6d14a..d46d255b 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;
@@ -146,6 +147,18 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
{
boolean logExceptions = !( handler instanceof PingHandler );
+<<<<<<< Updated upstream
+=======
+ // FlameCord - Option to log exceptions
+ logExceptions = FlameCord.getInstance().getFlameCordConfiguration().isLoggerExceptions() ? logExceptions : false;
+
+ // Flamecord - Firewall system
+ if (!(cause instanceof ReadTimeoutException))
+ {
+ FlameCord.getInstance().getFirewallManager().addFirewalled( ctx.channel().remoteAddress() );
+ }
+
+>>>>>>> Stashed changes
if ( logExceptions )
{
if ( cause instanceof ReadTimeoutException )
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 a840bc70..f7455a7e 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,8 +63,16 @@ 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 ) )
{
+ FlameCord.getInstance().getFirewallManager().addFirewalled( remoteAddress ); // FlameCord - Firewall throttled connections
ch.close();
return;
}
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 b1ecb7ef..06dcefa2 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();
--
2.32.0