Update IP forwarding to ignore FML and other null character delimited tokens (for now)

For Forge 1.8, a new \0FML\0 token is included in the handshake packet host field. Whilst from a Forge <-> Bungee standpoint, this is good in the long run (we can detect Forge/FML clients right from the off, allowing us to expose a reliable API for detecting modded 1.8+ clients), it plays havoc with IP forwarding on Spigot servers, as they expect a very specific format.

Until we can look at improving this situation (probably by creating an updated IP forwarding protocol on the server side), this removes the FML marker from the handshake whenever IP forwarding is on. If you have a FML 1.8 network, IP forwarding MUST be off.

With thanks to @geNAZt for finding the issue.
This commit is contained in:
Daniel Naylor 2014-12-21 10:31:07 +00:00 committed by md_5
parent ae12554316
commit 4809f1f80a
5 changed files with 46 additions and 1 deletions

View File

@ -92,6 +92,13 @@ public class ServerConnector extends PacketHandler
}
copiedHandshake.setHost( newHost );
}
else if ( !user.getExtraDataInHandshake().isEmpty() )
{
// Only restore the extra data if IP forwarding is off.
// TODO: Add support for this data with IP forwarding.
copiedHandshake.setHost( copiedHandshake.getHost() + user.getExtraDataInHandshake() );
}
channel.write( copiedHandshake );
channel.setProtocol( Protocol.LOGIN );

View File

@ -38,6 +38,7 @@ import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.entitymap.EntityMap;
import net.md_5.bungee.forge.ForgeClientHandler;
import net.md_5.bungee.forge.ForgeConstants;
import net.md_5.bungee.forge.ForgeServerHandler;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss;
@ -166,6 +167,9 @@ public final class UserConnection implements ProxiedPlayer
}
forgeClientHandler = new ForgeClientHandler( this );
// Set whether the connection has a 1.8 FML marker in the handshake.
forgeClientHandler.setFmlTokenInHandshake( this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN ) );
}
public void sendPacket(PacketWrapper packet)
@ -567,6 +571,11 @@ public final class UserConnection implements ProxiedPlayer
title.send( this );
}
public String getExtraDataInHandshake()
{
return this.getPendingConnection().getExtraDataInHandshake();
}
public void setCompressionThreshold(int compressionThreshold)
{
if ( this.compressionThreshold == -1 )

View File

@ -94,6 +94,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
private LoginResult loginProfile;
@Getter
private boolean legacy;
@Getter
private String extraDataInHandshake = "";
private enum State
{
@ -250,6 +252,18 @@ public class InitialHandler extends PacketHandler implements PendingConnection
this.handshake = handshake;
ch.setVersion( handshake.getProtocolVersion() );
// Starting with FML 1.8, a "\0FML\0" token is appended to the handshake. This interferes
// with Bungee's IP forwarding, so we detect it, and remove it from the host string, for now.
// We know FML appends \00FML\00. However, we need to also consider that other systems might
// add their own data to the end of the string. So, we just take everything from the \0 character
// and save it for later.
if ( handshake.getHost().contains( "\0" ) )
{
String[] split = handshake.getHost().split( "\0", 2 );
handshake.setHost( split[0] );
extraDataInHandshake = "\0" + split[1];
}
// SRV records can end with a . depending on DNS / client.
if ( handshake.getHost().endsWith( "." ) )
{

View File

@ -41,6 +41,14 @@ public class ForgeClientHandler
private PluginMessage serverModList = null;
private PluginMessage serverIdList = null;
/**
* Gets or sets a value indicating whether the '\00FML\00' token was found in
* the handshake.
*/
@Getter
@Setter
private boolean fmlTokenInHandshake = false;
/**
* Handles the Forge packet.
*
@ -143,12 +151,14 @@ public class ForgeClientHandler
/**
* Returns whether we know if the user is a forge user.
* In FML 1.8, a "FML" token is included in the initial handshake.
* We can use that to determine if the user is a Forge 1.8 user.
*
* @return <code>true</code> if the user is a forge user.
*/
public boolean isForgeUser()
{
return clientModList != null;
return fmlTokenInHandshake || clientModList != null;
}
/**

View File

@ -14,6 +14,11 @@ public class ForgeConstants
public static final String FML_HANDSHAKE_TAG = "FML|HS";
public static final String FML_REGISTER = "REGISTER";
/**
* The FML 1.8 handshake token.
*/
public static final String FML_HANDSHAKE_TOKEN = "\0FML\0";
public static final PluginMessage FML_RESET_HANDSHAKE = new PluginMessage( FML_HANDSHAKE_TAG, new byte[]
{
-2, 0