From 70abda9c5bf4cccd2cf52a58936c1a25cf5cad48 Mon Sep 17 00:00:00 2001 From: Luck Date: Tue, 2 Jun 2020 21:56:50 +0100 Subject: [PATCH] Implement legacy forwarding BungeeGuard handshake support --- .../proxy/config/PlayerInfoForwarding.java | 1 + .../proxy/config/VelocityConfiguration.java | 4 +++ .../backend/VelocityServerConnection.java | 26 +++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/PlayerInfoForwarding.java b/proxy/src/main/java/com/velocitypowered/proxy/config/PlayerInfoForwarding.java index e0c2c3558..908a26a31 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/PlayerInfoForwarding.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/PlayerInfoForwarding.java @@ -3,5 +3,6 @@ package com.velocitypowered.proxy.config; public enum PlayerInfoForwarding { NONE, LEGACY, + BUNGEEGUARD, MODERN } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 806ef44ce..ffe8ea832 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -61,6 +61,9 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi " proxy and will have offline-mode UUIDs.", "- \"legacy\": Forward player IPs and UUIDs in a BungeeCord-compatible format. Use this if", " you run servers using Minecraft 1.12 or lower.", + "- \"bungeeguard\": Forward player IPs and UUIDs in a format supported by the BungeeGuard", + " plugin. Use this if you run servers using Minecraft 1.12 or lower, and are", + " unable to implement network level firewalling (on a shared host).", "- \"modern\": Forward player IPs and UUIDs as part of the login process using Velocity's ", " native forwarding. Only applicable for Minecraft 1.13 or higher." }) @@ -185,6 +188,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi + "from the proxy and will have offline-mode UUIDs."); break; case MODERN: + case BUNGEEGUARD: if (forwardingSecret == null || forwardingSecret.length == 0) { logger.error("You don't have a forwarding secret set. This is required for security."); valid = false; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java index b91522507..5b87b95b9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java @@ -13,10 +13,12 @@ import static com.velocitypowered.proxy.network.Connections.MINECRAFT_ENCODER; import static com.velocitypowered.proxy.network.Connections.READ_TIMEOUT; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.server.ServerInfo; +import com.velocitypowered.api.util.GameProfile.Property; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.config.PlayerInfoForwarding; import com.velocitypowered.proxy.connection.ConnectionTypes; @@ -41,8 +43,11 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; import io.netty.handler.flow.FlowControlHandler; import io.netty.handler.timeout.ReadTimeoutHandler; +import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import java.util.function.UnaryOperator; import org.checkerframework.checker.nullness.qual.Nullable; public class VelocityServerConnection implements MinecraftConnectionAssociation, ServerConnection { @@ -106,7 +111,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, return result; } - private String createLegacyForwardingAddress() { + private String createLegacyForwardingAddress(UnaryOperator> propertiesTransform) { // BungeeCord IP forwarding is simply a special injection after the "address" in the handshake, // separated by \0 (the null byte). In order, you send the original host, the player's IP, their // UUID (undashed), and if you are in online-mode, their login properties (from Mojang). @@ -117,10 +122,24 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, .append('\0') .append(proxyPlayer.getGameProfile().getUndashedId()) .append('\0'); - GSON.toJson(proxyPlayer.getGameProfile().getProperties(), data); + GSON.toJson(propertiesTransform.apply(proxyPlayer.getGameProfile().getProperties()), data); return data.toString(); } + private String createLegacyForwardingAddress() { + return createLegacyForwardingAddress(UnaryOperator.identity()); + } + + private String createBungeeGuardForwardingAddress(byte[] forwardingSecret) { + // Append forwarding secret as a BungeeGuard token. + Property property = new Property("bungeeguard-token", + new String(forwardingSecret, StandardCharsets.UTF_8), ""); + return createLegacyForwardingAddress(properties -> ImmutableList.builder() + .addAll(properties) + .add(property) + .build()); + } + private void startHandshake() { final MinecraftConnection mc = ensureConnected(); PlayerInfoForwarding forwardingMode = server.getConfiguration().getPlayerInfoForwardingMode(); @@ -132,6 +151,9 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, handshake.setProtocolVersion(protocolVersion); if (forwardingMode == PlayerInfoForwarding.LEGACY) { handshake.setServerAddress(createLegacyForwardingAddress()); + } else if (forwardingMode == PlayerInfoForwarding.BUNGEEGUARD) { + byte[] secret = server.getConfiguration().getForwardingSecret(); + handshake.setServerAddress(createBungeeGuardForwardingAddress(secret)); } else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) { handshake.setServerAddress(handshake.getServerAddress() + HANDSHAKE_HOSTNAME_TOKEN); } else {