This commit is contained in:
Ismael 2023-07-09 13:00:30 +00:00 committed by GitHub
commit 530b1811c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 396 additions and 0 deletions

View File

@ -0,0 +1,396 @@
From 2b48760148e5ef1812f4e6b6fb5f9cdaef1bc560 Mon Sep 17 00:00:00 2001
From: Ismael Hanbel <soportexism4@gmail.com>
Date: Sat, 8 Jul 2023 20:36:35 +0200
Subject: [PATCH] Rework-information-forwarding.patch
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/forwarding/ForwardingMode.java b/api/src/main/java/io/github/waterfallmc/waterfall/forwarding/ForwardingMode.java
new file mode 100644
index 00000000..d6c17460
--- /dev/null
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/forwarding/ForwardingMode.java
@@ -0,0 +1,12 @@
+package io.github.waterfallmc.waterfall.forwarding;
+
+/**
+ * + * This enum represents the forwarding modes supported by Waterfall.
+ * +
+ */
+
+public enum ForwardingMode {
+ BUNGEECORD_LEGACY,
+ BUNGEEGUARD,
+ VELOCITY_MODERN
+}
\ No newline at end of file
diff --git a/api/src/main/java/net/md_5/bungee/Util.java b/api/src/main/java/net/md_5/bungee/Util.java
index 91efc0a6..8d83f41c 100644
--- a/api/src/main/java/net/md_5/bungee/Util.java
+++ b/api/src/main/java/net/md_5/bungee/Util.java
@@ -8,7 +8,9 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
+import java.security.SecureRandom;
import java.util.Locale;
+import java.util.Random;
import java.util.UUID;
import io.github.waterfallmc.waterfall.utils.Hex;
@@ -141,4 +143,22 @@ public class Util
{
return new UUID( UnsignedLongs.parseUnsignedLong( uuid.substring( 0, 16 ), 16 ), UnsignedLongs.parseUnsignedLong( uuid.substring( 16 ), 16 ) );
}
+
+ // Waterfall start: Forwarding rework
+ /**
+ * Generates an alphanumeric A-Z,a-z,0-9 byte-sequence.
+ *
+ * @param len the length of the sequence
+ * @return a UTF/ASCII compatible alphanumeric byte-sequence
+ */
+ public static byte[] randomAlphanumericSequence(int len) {
+ Random random = new SecureRandom();
+ byte[] ret = new byte[len];
+ for (int i = 0; i < len; i++) {
+ int seq = random.nextInt(62);
+ ret[i] = (byte) (seq < 10 ? seq + 48 : seq < 36 ? seq + 55 : seq + 61);
+ }
+ return ret;
+ }
+ // Waterfall end: Forwarding rework
}
diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
index 469fe0e1..b78c0d5f 100644
--- a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
+++ b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
@@ -2,6 +2,8 @@ package net.md_5.bungee.api;
import java.util.Collection;
import java.util.Map;
+
+import io.github.waterfallmc.waterfall.forwarding.ForwardingMode;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo;
@@ -275,4 +277,11 @@ public interface ProxyConfig
* @return the configured limit
*/
int getPluginChannelNameLimit();
+
+ /**
+ * Represents the forwarding mode as configured.
+ *
+ * @return the mode set in the config
+ */
+ ForwardingMode getForwardingMode();
}
diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
index 1ba5b249..c0797a4a 100644
--- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
+++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
@@ -49,7 +49,7 @@ import org.yaml.snakeyaml.introspector.PropertyUtils;
* example event handling and plugin management.
*/
@RequiredArgsConstructor
-public final class PluginManager
+public final class PluginManager
{
/*========================================================================*/
@@ -440,6 +440,14 @@ public final class PluginManager
Preconditions.checkNotNull( desc.getName(), "Plugin from %s has no name", file );
Preconditions.checkNotNull( desc.getMain(), "Plugin from %s has no main", file );
+ // Waterfall start: Forwarding rework
+ if (desc.getName().equals("BungeeGuard")) {
+ proxy.getLogger().warning("Detected the plugin BungeeGuard. " +
+ "Waterfall now supports the functionality this plugin provides natively. " +
+ "Please refer to the Waterfall documentation for more information.");
+ }
+ // Waterfall end: Forwarding rework
+
desc.setFile( file );
toLoad.put( desc.getName(), desc );
}
diff --git a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java
index da0efa36..03c628f4 100644
--- a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java
+++ b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java
@@ -1,11 +1,16 @@
package io.github.waterfallmc.waterfall.conf;
import com.google.common.base.Joiner;
+import io.github.waterfallmc.waterfall.forwarding.ForwardingMode;
+import net.md_5.bungee.BungeeCord;
+import net.md_5.bungee.Util;
import net.md_5.bungee.conf.Configuration;
import net.md_5.bungee.conf.YamlConfig;
import net.md_5.bungee.protocol.ProtocolConstants;
import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.logging.Logger;
public class WaterfallConfiguration extends Configuration {
@@ -45,6 +50,9 @@ public class WaterfallConfiguration extends Configuration {
private boolean disableEntityMetadataRewrite = false;
private boolean disableTabListRewrite = true;
+ private ForwardingMode forwardingMode = ForwardingMode.BUNGEECORD_LEGACY;
+ private byte[] forwardingSecret = Util.randomAlphanumericSequence(12);
+
/*
* Plugin Message limiting options
* Allows for more control over server-client communication
@@ -77,6 +85,25 @@ public class WaterfallConfiguration extends Configuration {
disableTabListRewrite = config.getBoolean("disable_tab_list_rewrite", disableTabListRewrite);
pluginChannelLimit = config.getInt("registered_plugin_channels_limit", pluginChannelLimit);
pluginChannelNameLimit = config.getInt("plugin_channel_name_limit", pluginChannelNameLimit);
+ // Forwarding options
+ forwardingMode = ForwardingMode.valueOf(config.getString("forwarding_mode", ForwardingMode.BUNGEECORD_LEGACY.toString()).toUpperCase());
+ Logger logger = BungeeCord.getInstance().getLogger();
+ if (super.isIpForward()) {
+ if ((forwardingMode) == ForwardingMode.BUNGEECORD_LEGACY) {
+ logger.warning("The forwarding mode is set as BungeeCord legacy, it is recommended that you use another mode to avoid spoofing information attacks.");
+ }
+
+ } else {
+ logger.warning("Information forwarding (ip-forwarding) is disabled. " +
+ "Player UUIDs may not be consistent across the servers. " +
+ "For the optimal experience please enable ip_forward in the config.yml and " +
+ "configure forwarding and on your servers.");
+ }
+
+ if (config.getString("forwarding_secret", "").isEmpty()) {
+ config.regenerateForwardingSecret();
+ logger.warning("A new forwarding secret has been generated. If this was the " +
+ "first start of the proxy please configure forwarding for your network.");
+ }
+ forwardingSecret = config.getString("forwarding_secret", "").getBytes(StandardCharsets.UTF_8);
+ }
@Override
@@ -123,4 +150,13 @@ public class WaterfallConfiguration extends Configuration {
public int getPluginChannelNameLimit() {
return pluginChannelNameLimit;
}
+
+ @Override
+ public ForwardingMode getForwardingMode() {
+ return forwardingMode;
+ }
+
+ public byte[] getForwardingSecret() {
+ return forwardingSecret;
+ }
}
diff --git a/proxy/src/main/java/io/github/waterfallmc/waterfall/forwarding/VelocityForwardingUtil.java b/proxy/src/main/java/io/github/waterfallmc/waterfall/forwarding/VelocityForwardingUtil.java
new file mode 100644
index 00000000..b9990f92
--- /dev/null
+++ b/proxy/src/main/java/io/github/waterfallmc/waterfall/forwarding/VelocityForwardingUtil.java
@@ -0,0 +1,69 @@
+package io.github.waterfallmc.waterfall.forwarding;
+
+import io.github.waterfallmc.waterfall.conf.WaterfallConfiguration;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import lombok.experimental.UtilityClass;
+import net.md_5.bungee.BungeeCord;
+import net.md_5.bungee.protocol.DefinedPacket;
+import net.md_5.bungee.protocol.Property;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+@UtilityClass
+public class VelocityForwardingUtil {
+
+ public static final String VELOCITY_IP_FORWARDING_CHANNEL = "velocity:player_info";
+ public static final int FORWARDING_VERSION = 1;
+
+ public static final String MODERN_IP_FORWARDING_FAILURE = "Your server did not send a forwarding request to the proxy. Is it set up correctly?";
+
+ public static byte[] writeForwardingData(String address, String name, UUID playerUUID, Property[] properties) {
+
+ ByteBuf buf = Unpooled.buffer(2048);
+
+ try {
+ DefinedPacket.writeVarInt(FORWARDING_VERSION, buf);
+ DefinedPacket.writeString(address, buf);
+ DefinedPacket.writeUUID(playerUUID, buf);
+ DefinedPacket.writeString(name, buf);
+ DefinedPacket.writeVarInt(properties.length, buf);
+ for (Property property : properties) {
+ DefinedPacket.writeString(property.getName(), buf);
+ DefinedPacket.writeString(property.getValue(), buf);
+ String signature = property.getSignature();
+ if (signature != null && !signature.isEmpty()) {
+ buf.writeBoolean(true);
+ DefinedPacket.writeString(signature, buf);
+ } else {
+ buf.writeBoolean(false);
+ }
+ }
+
+ byte[] forwardingSecret = ((WaterfallConfiguration) BungeeCord.getInstance().config).getForwardingSecret();
+ SecretKey key = new SecretKeySpec(forwardingSecret, "HmacSHA256");
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(key);
+ mac.update(buf.array(), buf.arrayOffset(), buf.readableBytes());
+ byte[] sig = mac.doFinal();
+
+ ByteBuf finished = Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(sig), buf);
+ byte[] encoded = ByteBufUtil.getBytes(finished);
+ finished.release();
+ return encoded;
+ } catch (InvalidKeyException e) {
+ buf.release();
+ throw new RuntimeException("Unable to authenticate data", e);
+ } catch (NoSuchAlgorithmException e) {
+ // Should never happen
+ buf.release();
+ throw new AssertionError(e);
+ }
+ }
+}
\ No newline at end of file
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 60232e52..dfde3535 100644
--- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
+++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
@@ -2,15 +2,15 @@ package net.md_5.bungee;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
+import io.github.waterfallmc.waterfall.conf.WaterfallConfiguration;
+import io.github.waterfallmc.waterfall.forwarding.ForwardingMode;
+import io.github.waterfallmc.waterfall.forwarding.VelocityForwardingUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-import java.util.Arrays; // Waterfall
-import java.util.Queue;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
+
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor;
@@ -35,11 +35,7 @@ import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.netty.PipelineUtils;
-import net.md_5.bungee.protocol.DefinedPacket;
-import net.md_5.bungee.protocol.MinecraftDecoder;
-import net.md_5.bungee.protocol.PacketWrapper;
-import net.md_5.bungee.protocol.Protocol;
-import net.md_5.bungee.protocol.ProtocolConstants;
+import net.md_5.bungee.protocol.*;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EntityStatus;
import net.md_5.bungee.protocol.packet.GameState;
@@ -73,6 +69,8 @@ public class ServerConnector extends PacketHandler
private ForgeServerHandler handshakeHandler;
private boolean obsolete;
+ private boolean didForwardInformation = false; // Waterfall: Forwarding rework
+
private enum State
{
@@ -106,6 +104,8 @@ public class ServerConnector extends PacketHandler
Handshake originalHandshake = user.getPendingConnection().getHandshake();
Handshake copiedHandshake = new Handshake( originalHandshake.getProtocolVersion(), originalHandshake.getHost(), originalHandshake.getPort(), 2 );
+ if(BungeeCord.getInstance().config.getForwardingMode() != ForwardingMode.VELOCITY_MODERN) // Waterfall: Forwarding rework
+
if ( BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress )
{
String newHost = copiedHandshake.getHost() + "\00" + AddressUtil.sanitizeAddress( user.getAddress() ) + "\00" + user.getUUID();
@@ -120,6 +120,15 @@ public class ServerConnector extends PacketHandler
properties = profile.getProperties();
}
+ // Waterfall start: Forwarding rework
+ if (BungeeCord.getInstance().config.getForwardingMode() == ForwardingMode.BUNGEEGUARD) {
+ List<Property> temp = new ArrayList<>(Arrays.asList(properties));
+ String token = new String(((WaterfallConfiguration) BungeeCord.getInstance().config).getForwardingSecret(), StandardCharsets.UTF_8);
+ temp.add(new Property("bungeeguard-token", token, null));
+ properties = temp.toArray(new Property[0]);
+ }
+ // Waterfall end: Forwarding rework
+
if ( user.getForgeClientHandler().isFmlTokenInHandshake() )
{
// Get the current properties and copy them into a slightly bigger array.
@@ -171,6 +180,12 @@ public class ServerConnector extends PacketHandler
@Override
public void handle(LoginSuccess loginSuccess) throws Exception
{
+ // Waterfall start: Forwarding rework
+ if (!didForwardInformation && BungeeCord.getInstance().config.isIpForward()
+ && BungeeCord.getInstance().config.getForwardingMode() == ForwardingMode.VELOCITY_MODERN) {
+ throw new QuietException(VelocityForwardingUtil.MODERN_IP_FORWARDING_FAILURE);
+ }
+ // Waterfall end: Forwarding rework
Preconditions.checkState( thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS" );
ch.setProtocol( Protocol.GAME );
thisState = State.LOGIN;
@@ -480,6 +495,20 @@ public class ServerConnector extends PacketHandler
@Override
public void handle(LoginPayloadRequest loginPayloadRequest)
{
+ // Waterfall start: Forwarding rework
+ if (!didForwardInformation && BungeeCord.getInstance().config.isIpForward()
+ && BungeeCord.getInstance().config.getForwardingMode() == ForwardingMode.VELOCITY_MODERN
+ && loginPayloadRequest.getChannel().equals(VelocityForwardingUtil.VELOCITY_IP_FORWARDING_CHANNEL)) {
+
+ byte[] forwardingData = VelocityForwardingUtil
+ .writeForwardingData(user.getAddress().getAddress().getHostAddress(),
+ user.getName(), user.getUniqueId(),
+ user.getPendingConnection().getLoginProfile().getProperties());
+ ch.write(new LoginPayloadResponse(loginPayloadRequest.getId(), forwardingData));
+ didForwardInformation = true;
+ return;
+ }
+ // Waterfall end: Forwarding rework
ch.write( new LoginPayloadResponse( loginPayloadRequest.getId(), null ) );
}
diff --git a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java
index 0dd69778..e3220e08 100644
--- a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java
+++ b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java
@@ -10,6 +10,7 @@ import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -332,4 +333,10 @@ public class YamlConfig implements ConfigurationAdapter
Collection<String> permissions = get( "permissions." + group, null );
return ( permissions == null ) ? Collections.EMPTY_SET : permissions;
}
+
+ // Waterfall start: Forwarding rework
+ public void regenerateForwardingSecret() {
+ set("forwarding_secret", new String(Util.randomAlphanumericSequence(12), StandardCharsets.UTF_8));
+ }
+ // Waterfall end: Forwarding rework
}
--
2.41.0.windows.1