Waterfall/Waterfall-Proxy-Patches/0026-Firewall-System.patch
2021-04-30 22:59:29 -03:00

377 lines
17 KiB
Diff

From 9e823cf6478f0b35c293a90ca846f00ba51142da 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 650cb302..b7268e1d 100644
--- a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java
@@ -13,7 +13,12 @@ import net.md_5.bungee.config.ConfigurationProvider;
public class FlameCordConfiguration {
@Getter
- private boolean loggerInitialhandler = false, loggerExceptions = false, loggerDump = false;
+ private boolean loggerInitialhandler = false, loggerExceptions = false, loggerDump = false, firewallNotify = true,
+ 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 {
@@ -32,6 +37,10 @@ public class FlameCordConfiguration {
configuration);
this.loggerExceptions = setIfUnexistant("logger.exceptions", this.loggerExceptions, configuration);
this.loggerDump = setIfUnexistant("logger.dump", this.loggerDump, configuration);
+ 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/FirewallException.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallException.java
new file mode 100644
index 00000000..6a661898
--- /dev/null
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallException.java
@@ -0,0 +1,30 @@
+package dev._2lstudios.flamecord.firewall;
+
+import java.net.SocketAddress;
+
+public class FirewallException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public FirewallException(final SocketAddress address) {
+ super("The address " + address + " is blocked from the server!");
+ }
+
+ public FirewallException(final String string) {
+ super(string);
+ }
+
+ public FirewallException(final String string, final Throwable throwable) {
+ super(string, throwable);
+ }
+
+ @Override
+ public synchronized Throwable initCause(final Throwable cause)
+ {
+ return this;
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
\ No newline at end of file
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..8a474758
--- /dev/null
+++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java
@@ -0,0 +1,116 @@
+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 (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/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/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java
index e4208b59..3b5bb7db 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
@@ -3,6 +3,7 @@ package net.md_5.bungee.netty;
import com.google.common.base.Preconditions;
import dev._2lstudios.flamecord.FlameCord;
+import dev._2lstudios.flamecord.firewall.FirewallException;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.CorruptedFrameException;
@@ -11,6 +12,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;
@@ -148,6 +150,23 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
// FlameCord - Log exceptions based on FlameCord
logExceptions = flameCord.getFlameCordConfiguration().isLoggerExceptions();
+ // FlameCord - Don't log firewall exceptions
+ logExceptions = cause instanceof FirewallException ? false : logExceptions;
+
+ // FlameCord - Firewall system
+ if (cause instanceof DecoderException || cause instanceof IllegalStateException || cause instanceof BadPacketException) {
+ final SocketAddress remoteAddress = ctx.channel().remoteAddress();
+
+ if (remoteAddress != null) {
+ flameCord.getFirewallManager().addFirewalled(remoteAddress);
+ }
+ }
+
+ // FlameCord - Handle firewall exceptions
+ if (cause instanceof FirewallException) {
+ flameCord.getFirewallManager().logBlocked(ctx.channel().remoteAddress());
+ }
+
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 d9d00fa5..fa6ab3e9 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
@@ -3,6 +3,7 @@ package net.md_5.bungee.netty;
import com.google.common.base.Preconditions;
import dev._2lstudios.flamecord.FlameCord;
+import dev._2lstudios.flamecord.firewall.FirewallException;
import io.github.waterfallmc.waterfall.event.ConnectionInitEvent;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
@@ -63,6 +64,11 @@ public class PipelineUtils
{
SocketAddress remoteAddress = ( ch.remoteAddress() == null ) ? ch.parent().localAddress() : ch.remoteAddress();
+ // FlameCord - Firewall system
+ if (remoteAddress != null && FlameCord.getInstance().getFirewallManager().isFirewalled(remoteAddress)) {
+ throw new FirewallException(remoteAddress);
+ }
+
if ( BungeeCord.getInstance().getConnectionThrottle() != null && BungeeCord.getInstance().getConnectionThrottle().throttle( remoteAddress ) )
{
ch.close();
--
2.31.1