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 3b83c4380..3522d1523 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -65,18 +65,21 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi @Comment({ "Should we forward IP addresses and other data to backend servers?", "Available options:", - "- \"none\": No forwarding will be done. All players will appear to be connecting from the", - " 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.", - "- \"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." + "- \"none\": No forwarding will be done. All players will appear to be connecting", + " from the 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." }) @ConfigKey("player-info-forwarding-mode") private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE; @StringAsBytes - @Comment("If you are using modern IP forwarding, configure an unique secret here.") + @Comment("If you are using modern or BungeeGuard IP forwarding, configure an unique secret here.") @ConfigKey("forwarding-secret") private byte[] forwardingSecret = generateRandomString(12).getBytes(StandardCharsets.UTF_8); @@ -193,6 +196,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 8d0b72455..86a17870d 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 @@ -5,10 +5,12 @@ import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConst import static com.velocitypowered.proxy.network.Connections.HANDLER; 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; @@ -24,7 +26,10 @@ import com.velocitypowered.proxy.server.VelocityRegisteredServer; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; +import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.function.UnaryOperator; import org.checkerframework.checker.nullness.qual.Nullable; public class VelocityServerConnection implements MinecraftConnectionAssociation, ServerConnection { @@ -88,7 +93,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). @@ -99,10 +104,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(); @@ -114,6 +133,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 {