diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java index 0a12ab5d8..a3f4056b9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.connection.backend; +import com.google.common.base.Preconditions; import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.crypto.IdentifiedKey; @@ -79,9 +80,19 @@ public class LoginSessionHandler implements MinecraftSessionHandler { VelocityConfiguration configuration = server.getConfiguration(); if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && packet.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) { + + int proposedForwardingVersion = VelocityConstants.MODERN_FORWARDING_DEFAULT; + // Check version + if (packet.content().readableBytes() == 1) { + int requested = packet.content().readByte(); + Preconditions.checkArgument(requested >= VelocityConstants.MODERN_FORWARDING_DEFAULT, + "Invalid modern forwarding version"); + proposedForwardingVersion = Math.min(requested, VelocityConstants.MODERN_FORWARDING_WITH_KEY); + } ByteBuf forwardingData = createForwardingData(configuration.getForwardingSecret(), - serverConn.getPlayerRemoteAddressAsString(), - serverConn.getPlayer().getGameProfile(), mc.getProtocolVersion(), serverConn.getPlayer().getIdentifiedKey()); + serverConn.getPlayerRemoteAddressAsString(), serverConn.getPlayer().getGameProfile(), + serverConn.getPlayer().getIdentifiedKey(), proposedForwardingVersion); + LoginPluginResponse response = new LoginPluginResponse(packet.getId(), true, forwardingData); mc.write(response); informationForwarded = true; @@ -166,20 +177,22 @@ public class LoginSessionHandler implements MinecraftSessionHandler { } private static ByteBuf createForwardingData(byte[] hmacSecret, String address, - GameProfile profile, ProtocolVersion version, - @Nullable IdentifiedKey playerKey) { + GameProfile profile, @Nullable IdentifiedKey playerKey, + int requestedVersion) { ByteBuf forwarded = Unpooled.buffer(2048); try { - int forwardingVersion = version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0 && playerKey != null - ? VelocityConstants.MODERN_FORWARDING_DEFAULT : VelocityConstants.MODERN_FORWARDING_DEFAULT; + int actualVersion = requestedVersion >= VelocityConstants.MODERN_FORWARDING_WITH_KEY + ? (playerKey != null ? requestedVersion : VelocityConstants.MODERN_FORWARDING_DEFAULT) : requestedVersion; - ProtocolUtils.writeVarInt(forwarded, forwardingVersion); + ProtocolUtils.writeVarInt(forwarded, actualVersion); ProtocolUtils.writeString(forwarded, address); ProtocolUtils.writeUuid(forwarded, profile.getId()); ProtocolUtils.writeString(forwarded, profile.getName()); ProtocolUtils.writeProperties(forwarded, profile.getProperties()); - if (forwardingVersion >= VelocityConstants.MODERN_FORWARDING_WITH_KEY) { + // 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) { ProtocolUtils.writePlayerKey(forwarded, playerKey); }