geforkt von Mirrors/Velocity
Extract player data forwarding to separate class (#1210)
* Extract player data forwarding to separate class * Use modern switch statement
Dieser Commit ist enthalten in:
Ursprung
b9b11665b9
Commit
4080ee2eaa
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018-2023 Velocity Contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.velocitypowered.proxy.connection;
|
||||||
|
|
||||||
|
import static com.velocitypowered.proxy.VelocityServer.GENERAL_GSON;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
|
import com.velocitypowered.api.proxy.crypto.IdentifiedKey;
|
||||||
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
@SuppressWarnings({"MissingJavadocMethod", "MissingJavadocType"})
|
||||||
|
public final class PlayerDataForwarding {
|
||||||
|
private static final String ALGORITHM = "HmacSHA256";
|
||||||
|
|
||||||
|
public static final String CHANNEL = "velocity:player_info";
|
||||||
|
|
||||||
|
public static final int MODERN_DEFAULT = 1;
|
||||||
|
public static final int MODERN_WITH_KEY = 2;
|
||||||
|
public static final int MODERN_WITH_KEY_V2 = 3;
|
||||||
|
public static final int MODERN_LAZY_SESSION = 4;
|
||||||
|
public static final int MODERN_MAX_VERSION = MODERN_LAZY_SESSION;
|
||||||
|
|
||||||
|
private static final char LEGACY_SEPARATOR = '\0';
|
||||||
|
|
||||||
|
private static final String BUNGEE_GUARD_TOKEN_PROPERTY_NAME = "bungeeguard-token";
|
||||||
|
|
||||||
|
private PlayerDataForwarding() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuf createForwardingData(
|
||||||
|
final byte[] secret,
|
||||||
|
final String address,
|
||||||
|
final ProtocolVersion protocol,
|
||||||
|
final GameProfile profile,
|
||||||
|
final @Nullable IdentifiedKey key,
|
||||||
|
final int requestedVersion
|
||||||
|
) {
|
||||||
|
final ByteBuf forwarded = Unpooled.buffer(2048);
|
||||||
|
try {
|
||||||
|
final int actualVersion = findForwardingVersion(requestedVersion, protocol, key);
|
||||||
|
|
||||||
|
ProtocolUtils.writeVarInt(forwarded, actualVersion);
|
||||||
|
ProtocolUtils.writeString(forwarded, address);
|
||||||
|
ProtocolUtils.writeUuid(forwarded, profile.getId());
|
||||||
|
ProtocolUtils.writeString(forwarded, profile.getName());
|
||||||
|
ProtocolUtils.writeProperties(forwarded, profile.getProperties());
|
||||||
|
|
||||||
|
// This serves as additional redundancy. The key normally is stored in the
|
||||||
|
// login start to the server, but some setups require this.
|
||||||
|
if (actualVersion >= MODERN_WITH_KEY
|
||||||
|
&& actualVersion < MODERN_LAZY_SESSION) {
|
||||||
|
assert key != null;
|
||||||
|
ProtocolUtils.writePlayerKey(forwarded, key);
|
||||||
|
|
||||||
|
// Provide the signer UUID since the UUID may differ from the
|
||||||
|
// assigned UUID. Doing that breaks the signatures anyway but the server
|
||||||
|
// should be able to verify the key independently.
|
||||||
|
if (actualVersion >= MODERN_WITH_KEY_V2) {
|
||||||
|
if (key.getSignatureHolder() != null) {
|
||||||
|
forwarded.writeBoolean(true);
|
||||||
|
ProtocolUtils.writeUuid(forwarded, key.getSignatureHolder());
|
||||||
|
} else {
|
||||||
|
// Should only not be provided if the player was connected
|
||||||
|
// as offline-mode and the signer UUID was not backfilled
|
||||||
|
forwarded.writeBoolean(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Mac mac = Mac.getInstance(ALGORITHM);
|
||||||
|
mac.init(new SecretKeySpec(secret, ALGORITHM));
|
||||||
|
mac.update(forwarded.array(), forwarded.arrayOffset(), forwarded.readableBytes());
|
||||||
|
final byte[] sig = mac.doFinal();
|
||||||
|
|
||||||
|
return Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(sig), forwarded);
|
||||||
|
} catch (final InvalidKeyException e) {
|
||||||
|
forwarded.release();
|
||||||
|
throw new RuntimeException("Unable to authenticate data", e);
|
||||||
|
} catch (final NoSuchAlgorithmException e) {
|
||||||
|
// Should never happen
|
||||||
|
forwarded.release();
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findForwardingVersion(
|
||||||
|
int requested,
|
||||||
|
final ProtocolVersion protocol,
|
||||||
|
final @Nullable IdentifiedKey key
|
||||||
|
) {
|
||||||
|
// Ensure we are in range
|
||||||
|
requested = Math.min(requested, MODERN_MAX_VERSION);
|
||||||
|
if (requested > MODERN_DEFAULT) {
|
||||||
|
if (protocol.noLessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
|
||||||
|
return requested >= MODERN_LAZY_SESSION
|
||||||
|
? MODERN_LAZY_SESSION
|
||||||
|
: MODERN_DEFAULT;
|
||||||
|
}
|
||||||
|
if (key != null) {
|
||||||
|
return switch (key.getKeyRevision()) {
|
||||||
|
case GENERIC_V1 -> MODERN_WITH_KEY;
|
||||||
|
// Since V2 is not backwards compatible we have to throw the key if v2 and requested is v1
|
||||||
|
case LINKED_V2 -> requested >= MODERN_WITH_KEY_V2
|
||||||
|
? MODERN_WITH_KEY_V2
|
||||||
|
: MODERN_DEFAULT;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return MODERN_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MODERN_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createLegacyForwardingAddress(
|
||||||
|
final String serverAddress,
|
||||||
|
final String playerAddress,
|
||||||
|
final GameProfile profile
|
||||||
|
) {
|
||||||
|
return createLegacyForwardingAddress(
|
||||||
|
serverAddress,
|
||||||
|
playerAddress,
|
||||||
|
profile,
|
||||||
|
UnaryOperator.identity()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createLegacyForwardingAddress(
|
||||||
|
final String serverAddress,
|
||||||
|
final String playerAddress,
|
||||||
|
final GameProfile profile,
|
||||||
|
final UnaryOperator<List<GameProfile.Property>> 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).
|
||||||
|
final StringBuilder data = new StringBuilder()
|
||||||
|
.append(serverAddress)
|
||||||
|
.append(LEGACY_SEPARATOR)
|
||||||
|
.append(playerAddress)
|
||||||
|
.append(LEGACY_SEPARATOR)
|
||||||
|
.append(profile.getUndashedId())
|
||||||
|
.append(LEGACY_SEPARATOR);
|
||||||
|
GENERAL_GSON
|
||||||
|
.toJson(propertiesTransform.apply(profile.getProperties()), data);
|
||||||
|
return data.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createBungeeGuardForwardingAddress(
|
||||||
|
final String serverAddress,
|
||||||
|
final String playerAddress,
|
||||||
|
final GameProfile profile,
|
||||||
|
final byte[] forwardingSecret
|
||||||
|
) {
|
||||||
|
// Append forwarding secret as a BungeeGuard token.
|
||||||
|
final GameProfile.Property property = new GameProfile.Property(
|
||||||
|
BUNGEE_GUARD_TOKEN_PROPERTY_NAME,
|
||||||
|
new String(forwardingSecret, StandardCharsets.UTF_8),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
return createLegacyForwardingAddress(
|
||||||
|
serverAddress,
|
||||||
|
playerAddress,
|
||||||
|
profile,
|
||||||
|
properties -> ImmutableList.<GameProfile.Property>builder()
|
||||||
|
.addAll(properties)
|
||||||
|
.add(property)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -26,12 +26,5 @@ public class VelocityConstants {
|
|||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String VELOCITY_IP_FORWARDING_CHANNEL = "velocity:player_info";
|
|
||||||
public static final int MODERN_FORWARDING_DEFAULT = 1;
|
|
||||||
public static final int MODERN_FORWARDING_WITH_KEY = 2;
|
|
||||||
public static final int MODERN_FORWARDING_WITH_KEY_V2 = 3;
|
|
||||||
public static final int MODERN_LAZY_SESSION = 4;
|
|
||||||
public static final int MODERN_FORWARDING_MAX_VERSION = MODERN_LAZY_SESSION;
|
|
||||||
|
|
||||||
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,17 @@ package com.velocitypowered.proxy.connection.backend;
|
|||||||
|
|
||||||
import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent;
|
import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.api.proxy.crypto.IdentifiedKey;
|
|
||||||
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||||
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.connection.VelocityConstants;
|
import com.velocitypowered.proxy.connection.PlayerDataForwarding;
|
||||||
import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler;
|
import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler;
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
|
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
|
||||||
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
|
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
|
||||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||||
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
|
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
|
||||||
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
|
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
|
||||||
@ -44,12 +42,7 @@ import com.velocitypowered.proxy.util.except.QuietRuntimeException;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import javax.crypto.Mac;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -86,15 +79,20 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
MinecraftConnection mc = serverConn.ensureConnected();
|
MinecraftConnection mc = serverConn.ensureConnected();
|
||||||
VelocityConfiguration configuration = server.getConfiguration();
|
VelocityConfiguration configuration = server.getConfiguration();
|
||||||
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
||||||
&& packet.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) {
|
&& packet.getChannel().equals(PlayerDataForwarding.CHANNEL)) {
|
||||||
|
|
||||||
int requestedForwardingVersion = VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
int requestedForwardingVersion = PlayerDataForwarding.MODERN_DEFAULT;
|
||||||
// Check version
|
// Check version
|
||||||
if (packet.content().readableBytes() == 1) {
|
if (packet.content().readableBytes() == 1) {
|
||||||
requestedForwardingVersion = packet.content().readByte();
|
requestedForwardingVersion = packet.content().readByte();
|
||||||
}
|
}
|
||||||
ByteBuf forwardingData = createForwardingData(configuration.getForwardingSecret(),
|
ConnectedPlayer player = serverConn.getPlayer();
|
||||||
serverConn.getPlayerRemoteAddressAsString(), serverConn.getPlayer(),
|
ByteBuf forwardingData = PlayerDataForwarding.createForwardingData(
|
||||||
|
configuration.getForwardingSecret(),
|
||||||
|
serverConn.getPlayerRemoteAddressAsString(),
|
||||||
|
player.getProtocolVersion(),
|
||||||
|
player.getGameProfile(),
|
||||||
|
player.getIdentifiedKey(),
|
||||||
requestedForwardingVersion);
|
requestedForwardingVersion);
|
||||||
|
|
||||||
LoginPluginResponsePacket response = new LoginPluginResponsePacket(
|
LoginPluginResponsePacket response = new LoginPluginResponsePacket(
|
||||||
@ -197,85 +195,4 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findForwardingVersion(int requested, ConnectedPlayer player) {
|
|
||||||
// Ensure we are in range
|
|
||||||
requested = Math.min(requested, VelocityConstants.MODERN_FORWARDING_MAX_VERSION);
|
|
||||||
if (requested > VelocityConstants.MODERN_FORWARDING_DEFAULT) {
|
|
||||||
if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
|
|
||||||
return requested >= VelocityConstants.MODERN_LAZY_SESSION
|
|
||||||
? VelocityConstants.MODERN_LAZY_SESSION
|
|
||||||
: VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
|
||||||
}
|
|
||||||
if (player.getIdentifiedKey() != null) {
|
|
||||||
// No enhanced switch on java 11
|
|
||||||
switch (player.getIdentifiedKey().getKeyRevision()) {
|
|
||||||
case GENERIC_V1:
|
|
||||||
return VelocityConstants.MODERN_FORWARDING_WITH_KEY;
|
|
||||||
// Since V2 is not backwards compatible we have to throw the key if v2 and requested is v1
|
|
||||||
case LINKED_V2:
|
|
||||||
return requested >= VelocityConstants.MODERN_FORWARDING_WITH_KEY_V2
|
|
||||||
? VelocityConstants.MODERN_FORWARDING_WITH_KEY_V2
|
|
||||||
: VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
|
||||||
default:
|
|
||||||
return VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return VelocityConstants.MODERN_FORWARDING_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ByteBuf createForwardingData(byte[] hmacSecret, String address,
|
|
||||||
ConnectedPlayer player, int requestedVersion) {
|
|
||||||
ByteBuf forwarded = Unpooled.buffer(2048);
|
|
||||||
try {
|
|
||||||
int actualVersion = findForwardingVersion(requestedVersion, player);
|
|
||||||
|
|
||||||
ProtocolUtils.writeVarInt(forwarded, actualVersion);
|
|
||||||
ProtocolUtils.writeString(forwarded, address);
|
|
||||||
ProtocolUtils.writeUuid(forwarded, player.getGameProfile().getId());
|
|
||||||
ProtocolUtils.writeString(forwarded, player.getGameProfile().getName());
|
|
||||||
ProtocolUtils.writeProperties(forwarded, player.getGameProfile().getProperties());
|
|
||||||
|
|
||||||
// This serves as additional redundancy. The key normally is stored in the
|
|
||||||
// login start to the server, but some setups require this.
|
|
||||||
if (actualVersion >= VelocityConstants.MODERN_FORWARDING_WITH_KEY
|
|
||||||
&& actualVersion < VelocityConstants.MODERN_LAZY_SESSION) {
|
|
||||||
IdentifiedKey key = player.getIdentifiedKey();
|
|
||||||
assert key != null;
|
|
||||||
ProtocolUtils.writePlayerKey(forwarded, key);
|
|
||||||
|
|
||||||
// Provide the signer UUID since the UUID may differ from the
|
|
||||||
// assigned UUID. Doing that breaks the signatures anyway but the server
|
|
||||||
// should be able to verify the key independently.
|
|
||||||
if (actualVersion >= VelocityConstants.MODERN_FORWARDING_WITH_KEY_V2) {
|
|
||||||
if (key.getSignatureHolder() != null) {
|
|
||||||
forwarded.writeBoolean(true);
|
|
||||||
ProtocolUtils.writeUuid(forwarded, key.getSignatureHolder());
|
|
||||||
} else {
|
|
||||||
// Should only not be provided if the player was connected
|
|
||||||
// as offline-mode and the signer UUID was not backfilled
|
|
||||||
forwarded.writeBoolean(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SecretKey key = new SecretKeySpec(hmacSecret, "HmacSHA256");
|
|
||||||
Mac mac = Mac.getInstance("HmacSHA256");
|
|
||||||
mac.init(key);
|
|
||||||
mac.update(forwarded.array(), forwarded.arrayOffset(), forwarded.readableBytes());
|
|
||||||
byte[] sig = mac.doFinal();
|
|
||||||
|
|
||||||
return Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(sig), forwarded);
|
|
||||||
} catch (InvalidKeyException e) {
|
|
||||||
forwarded.release();
|
|
||||||
throw new RuntimeException("Unable to authenticate data", e);
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
// Should never happen
|
|
||||||
forwarded.release();
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,24 +17,22 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.connection.backend;
|
package com.velocitypowered.proxy.connection.backend;
|
||||||
|
|
||||||
import static com.velocitypowered.proxy.VelocityServer.GENERAL_GSON;
|
|
||||||
import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN;
|
import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN;
|
||||||
import static com.velocitypowered.proxy.network.Connections.HANDLER;
|
import static com.velocitypowered.proxy.network.Connections.HANDLER;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.api.proxy.ServerConnection;
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
import com.velocitypowered.api.util.GameProfile.Property;
|
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||||
import com.velocitypowered.proxy.connection.ConnectionTypes;
|
import com.velocitypowered.proxy.connection.ConnectionTypes;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
|
import com.velocitypowered.proxy.connection.PlayerDataForwarding;
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
import com.velocitypowered.proxy.connection.forge.modern.ModernForgeConnectionType;
|
import com.velocitypowered.proxy.connection.forge.modern.ModernForgeConnectionType;
|
||||||
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
|
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
|
||||||
@ -47,13 +45,10 @@ import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -142,32 +137,23 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createLegacyForwardingAddress(UnaryOperator<List<Property>> 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).
|
|
||||||
StringBuilder data = new StringBuilder().append(proxyPlayer.getVirtualHost().orElseGet(() ->
|
|
||||||
registeredServer.getServerInfo().getAddress()).getHostString())
|
|
||||||
.append('\0')
|
|
||||||
.append(getPlayerRemoteAddressAsString())
|
|
||||||
.append('\0')
|
|
||||||
.append(proxyPlayer.getGameProfile().getUndashedId())
|
|
||||||
.append('\0');
|
|
||||||
GENERAL_GSON
|
|
||||||
.toJson(propertiesTransform.apply(proxyPlayer.getGameProfile().getProperties()), data);
|
|
||||||
return data.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createLegacyForwardingAddress() {
|
private String createLegacyForwardingAddress() {
|
||||||
return createLegacyForwardingAddress(UnaryOperator.identity());
|
return PlayerDataForwarding.createLegacyForwardingAddress(
|
||||||
|
proxyPlayer.getVirtualHost().orElseGet(() ->
|
||||||
|
registeredServer.getServerInfo().getAddress()).getHostString(),
|
||||||
|
getPlayerRemoteAddressAsString(),
|
||||||
|
proxyPlayer.getGameProfile()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createBungeeGuardForwardingAddress(byte[] forwardingSecret) {
|
private String createBungeeGuardForwardingAddress(byte[] forwardingSecret) {
|
||||||
// Append forwarding secret as a BungeeGuard token.
|
return PlayerDataForwarding.createBungeeGuardForwardingAddress(
|
||||||
Property property =
|
proxyPlayer.getVirtualHost().orElseGet(() ->
|
||||||
new Property("bungeeguard-token", new String(forwardingSecret, StandardCharsets.UTF_8), "");
|
registeredServer.getServerInfo().getAddress()).getHostString(),
|
||||||
return createLegacyForwardingAddress(
|
getPlayerRemoteAddressAsString(),
|
||||||
properties -> ImmutableList.<Property>builder().addAll(properties).add(property).build());
|
proxyPlayer.getGameProfile(),
|
||||||
|
forwardingSecret
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startHandshake() {
|
private void startHandshake() {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren