diff --git a/build.gradle b/build.gradle index 1389967..1f0b611 100644 --- a/build.gradle +++ b/build.gradle @@ -75,6 +75,9 @@ repositories { maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } + maven { + url = 'https://repo.codemc.io/repository/maven-public/' + } maven { url = 'https://repo.dmulloy2.net/nexus/repository/public/' } diff --git a/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityHandshakeHandler.java b/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityHandshakeHandler.java index 63c8a1d..3766b69 100644 --- a/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityHandshakeHandler.java +++ b/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityHandshakeHandler.java @@ -14,70 +14,74 @@ */ public class VelocityHandshakeHandler { - private final TCPShieldPlugin plugin; - - - private static Class CONNECTED_PLAYER_CONNECTION_CLASS; - - static { - try { - CONNECTED_PLAYER_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.ConnectedPlayer"); - } catch (Exception e) { - // ignore for old velocity versions - } - } - - public VelocityHandshakeHandler(TCPShieldPlugin plugin) { - this.plugin = plugin; - } - - // Turns out this event sometimes passes erroneous hostnames - // which have the null bytes terminated as FML data which causes - // issues with the verification process. - @Subscribe(order = PostOrder.FIRST) - public void onPreLogin(PreLoginEvent e) { - if (!this.plugin.getConfigProvider().handlePreLoginEvent()) { - return; - } - - InboundConnection connection = e.getConnection(); - handleEvent(connection, "onPreLogin"); - } - - @Subscribe(order = PostOrder.FIRST) - public void onHandshake(ConnectionHandshakeEvent e) { - InboundConnection connection = e.getConnection(); - handleEvent(connection, "onHandshake"); - } - - @Subscribe(order = PostOrder.FIRST) - public void onProxyPing(ProxyPingEvent e) { - InboundConnection connection = e.getConnection(); - - if (connection.getClass() == CONNECTED_PLAYER_CONNECTION_CLASS) { - // new ServerData (0x42) packet on connect, we don't care about it - return; - } - - handleEvent(connection, "onProxyPing"); - } - - private void handleEvent(InboundConnection connection, String debugSource) { - VelocityPlayer player = new VelocityPlayer(connection); - if (player.getConnectionType() == VelocityPlayer.ConnectionType.LEGACY) { - player.disconnect(); - return; - } - - VelocityPacket packet = new VelocityPacket(connection); - - this.plugin.getDebugger().warn("Velocity: " + debugSource + " Raw player hostname: " + packet.getPayloadString()); - - try { - plugin.getPacketHandler().handleHandshake(packet, player); - } catch (HandshakeException exception) { - plugin.getDebugger().exception(exception); - } - } + private final TCPShieldPlugin plugin; + + + private static Class CONNECTED_PLAYER_CONNECTION_CLASS; + + static { + try { + CONNECTED_PLAYER_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.ConnectedPlayer"); + } catch (Exception e) { + // ignore for old velocity versions + } + } + + public VelocityHandshakeHandler(TCPShieldPlugin plugin) { + this.plugin = plugin; + } + + @Subscribe(order = PostOrder.FIRST) + public void onPreLogin(PreLoginEvent e) { + if (!this.plugin.getConfigProvider().handlePreLoginEvent()) { + return; + } + + InboundConnection connection = e.getConnection(); + handleEvent(connection, "onPreLogin"); + } + + @Subscribe(order = PostOrder.FIRST) + public void onHandshake(ConnectionHandshakeEvent e) { + InboundConnection connection = e.getConnection(); + handleEvent(connection, "onHandshake"); + } + + @Subscribe(order = PostOrder.FIRST) + public void onProxyPing(ProxyPingEvent e) { + InboundConnection connection = e.getConnection(); + + if (connection.getClass() == CONNECTED_PLAYER_CONNECTION_CLASS) { + // new ServerData (0x42) packet on connect, we don't care about it + return; + } + + handleEvent(connection, "onProxyPing"); + } + + private void handleEvent(InboundConnection connection, String debugSource) { + VelocityPlayer player = new VelocityPlayer(connection); + + // Unrecognized connection types (e.g. Geyser's ping passthrough connection) + // aren't real player connections we can manipulate, so ignore them silently. + if (player.getConnectionType() == VelocityPlayer.ConnectionType.UNKNOWN) { + return; + } + + if (player.getConnectionType() == VelocityPlayer.ConnectionType.LEGACY) { + player.disconnect(); + return; + } + + VelocityPacket packet = new VelocityPacket(connection); + + this.plugin.getDebugger().warn("Velocity: " + debugSource + " Raw player hostname: " + packet.getPayloadString()); + + try { + plugin.getPacketHandler().handleHandshake(packet, player); + } catch (HandshakeException exception) { + plugin.getDebugger().exception(exception); + } + } } diff --git a/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityPlayer.java b/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityPlayer.java index 58e0ec5..ce060af 100644 --- a/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityPlayer.java +++ b/src/main/java/net/tcpshield/tcpshield/velocity/handler/VelocityPlayer.java @@ -16,140 +16,123 @@ */ public class VelocityPlayer implements PlayerProvider { - /* - * Reflection objects needed for manipulation - */ - private static final Class INITIAL_INBOUND_CONNECTION_CLASS; - private static final Field MINECRAFT_CONNECTION_FIELD; - private static final Field LEGACY_MINECRAFT_CONNECTION_FIELD; - private static final Field REMOTE_ADDRESS_FIELD; - private static final Method CLOSE_CHANNEL_METHOD; - - // new velocity support - - private static Class LOGIN_INBOUND_CONNECTION_CLASS; - private static Field LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD; - - static { - try { - INITIAL_INBOUND_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.InitialInboundConnection"); - MINECRAFT_CONNECTION_FIELD = ReflectionUtil.getPrivateField(INITIAL_INBOUND_CONNECTION_CLASS, "connection"); - LEGACY_MINECRAFT_CONNECTION_FIELD = ReflectionUtil.getPrivateField(Class.forName("com.velocitypowered.proxy.connection.client.HandshakeSessionHandler$LegacyInboundConnection"), "connection"); - - Class minecraftConnection = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection"); - REMOTE_ADDRESS_FIELD = ReflectionUtil.getPrivateField(minecraftConnection, "remoteAddress"); - CLOSE_CHANNEL_METHOD = minecraftConnection.getMethod("close"); - } catch (Exception e) { - throw new InitializationException(new ReflectionException(e)); - } - - // LoginInboundConnection support - try { - LOGIN_INBOUND_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.LoginInboundConnection"); - LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD = ReflectionUtil.getPrivateField(LOGIN_INBOUND_CONNECTION_CLASS, "delegate"); - } catch (Exception e) { - // ignore for old versions of velocity - } - } - - - private final InboundConnection inboundConnection; - // private final boolean legacy; - private final ConnectionType connectionType; - private String ip; - - public VelocityPlayer(InboundConnection inboundConnection) { - this.inboundConnection = inboundConnection; -// this.legacy = inboundConnection.getClass() != INITIAL_INBOUND_CONNECTION_CLASS && inboundConnection.getClass() != LOGIN_INBOUND_CONNECTION_CLASS; - this.ip = inboundConnection.getRemoteAddress().getAddress().getHostAddress(); - - if (this.inboundConnection.getClass() == INITIAL_INBOUND_CONNECTION_CLASS) { - this.connectionType = ConnectionType.INITIAL_INBOUND; - } else if (this.inboundConnection.getClass() == LOGIN_INBOUND_CONNECTION_CLASS) { - this.connectionType = ConnectionType.LOGIN_INBOUND; - } else { - this.connectionType = ConnectionType.LEGACY; - } - } - - /** - * Unsupported with Velocity handshakes - * - * @return unknown - */ - @Override - public String getUUID() { - return "unknown"; - } - - /** - * Unsupported with Velocity handshakes - * - * @return unknown - */ - @Override - public String getName() { - return "unknown"; - } - - @Override - public String getIP() { - return ip; - } - - @Override - public void setIP(InetSocketAddress ip) throws PlayerManipulationException { - try { - this.ip = ip.getAddress().getHostAddress(); - - Object minecraftConnection = this.getMinecraftConnection(); - REMOTE_ADDRESS_FIELD.set(minecraftConnection, ip); - } catch (Exception e) { - throw new PlayerManipulationException(e); - } - } - -// public boolean isLegacy() { -// return legacy; -// } - - @Override - public void disconnect() { - try { - Object minecraftConnection = this.getMinecraftConnection(); - - CLOSE_CHANNEL_METHOD.invoke(minecraftConnection); - } catch (Exception e) { - throw new PlayerManipulationException(e); - } - } - - private Object getMinecraftConnection() { - try { - switch (this.connectionType) { - case LEGACY: - return LEGACY_MINECRAFT_CONNECTION_FIELD.get(inboundConnection); - case INITIAL_INBOUND: - return MINECRAFT_CONNECTION_FIELD.get(inboundConnection); - case LOGIN_INBOUND: { - // starts as login_inbound, get delegate initial_inbound - Object initialInboundConnection = LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD.get(this.inboundConnection); - return MINECRAFT_CONNECTION_FIELD.get(initialInboundConnection); - } - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - return null; - } - - public ConnectionType getConnectionType() { - return connectionType; - } - - enum ConnectionType { - LOGIN_INBOUND, INITIAL_INBOUND, LEGACY - } + private static final Class INITIAL_INBOUND_CONNECTION_CLASS; + private static final Class LEGACY_INBOUND_CONNECTION_CLASS; + private static final Field MINECRAFT_CONNECTION_FIELD; + private static final Field LEGACY_MINECRAFT_CONNECTION_FIELD; + private static final Field REMOTE_ADDRESS_FIELD; + private static final Method CLOSE_CHANNEL_METHOD; + + private static Class LOGIN_INBOUND_CONNECTION_CLASS; + private static Field LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD; + + static { + try { + INITIAL_INBOUND_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.InitialInboundConnection"); + MINECRAFT_CONNECTION_FIELD = ReflectionUtil.getPrivateField(INITIAL_INBOUND_CONNECTION_CLASS, "connection"); + LEGACY_INBOUND_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.HandshakeSessionHandler$LegacyInboundConnection"); + LEGACY_MINECRAFT_CONNECTION_FIELD = ReflectionUtil.getPrivateField(LEGACY_INBOUND_CONNECTION_CLASS, "connection"); + + Class minecraftConnection = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection"); + REMOTE_ADDRESS_FIELD = ReflectionUtil.getPrivateField(minecraftConnection, "remoteAddress"); + CLOSE_CHANNEL_METHOD = minecraftConnection.getMethod("close"); + } catch (Exception e) { + throw new InitializationException(new ReflectionException(e)); + } + + try { + LOGIN_INBOUND_CONNECTION_CLASS = Class.forName("com.velocitypowered.proxy.connection.client.LoginInboundConnection"); + LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD = ReflectionUtil.getPrivateField(LOGIN_INBOUND_CONNECTION_CLASS, "delegate"); + } catch (Exception e) { + // ignore for old versions of velocity + } + } + + private final InboundConnection inboundConnection; + private final ConnectionType connectionType; + private String ip; + + public VelocityPlayer(InboundConnection inboundConnection) { + this.inboundConnection = inboundConnection; + this.ip = inboundConnection.getRemoteAddress().getAddress().getHostAddress(); + + if (this.inboundConnection.getClass() == INITIAL_INBOUND_CONNECTION_CLASS) { + this.connectionType = ConnectionType.INITIAL_INBOUND; + } else if (this.inboundConnection.getClass() == LOGIN_INBOUND_CONNECTION_CLASS) { + this.connectionType = ConnectionType.LOGIN_INBOUND; + } else if (this.inboundConnection.getClass() == LEGACY_INBOUND_CONNECTION_CLASS) { + this.connectionType = ConnectionType.LEGACY; + } else { + // Unrecognized InboundConnection implementation (e.g. Geyser's + // GeyserVelocityPingPassthrough$GeyserInboundConnection). These are not + // real player connections we can manipulate, so they're ignored. + this.connectionType = ConnectionType.UNKNOWN; + } + } + + @Override + public String getUUID() { + return "unknown"; + } + + @Override + public String getName() { + return "unknown"; + } + + @Override + public String getIP() { + return ip; + } + + @Override + public void setIP(InetSocketAddress ip) throws PlayerManipulationException { + try { + this.ip = ip.getAddress().getHostAddress(); + + Object minecraftConnection = this.getMinecraftConnection(); + REMOTE_ADDRESS_FIELD.set(minecraftConnection, ip); + } catch (Exception e) { + throw new PlayerManipulationException(e); + } + } + + @Override + public void disconnect() { + try { + Object minecraftConnection = this.getMinecraftConnection(); + + CLOSE_CHANNEL_METHOD.invoke(minecraftConnection); + } catch (Exception e) { + throw new PlayerManipulationException(e); + } + } + + private Object getMinecraftConnection() { + try { + switch (this.connectionType) { + case LEGACY: + return LEGACY_MINECRAFT_CONNECTION_FIELD.get(inboundConnection); + case INITIAL_INBOUND: + return MINECRAFT_CONNECTION_FIELD.get(inboundConnection); + case LOGIN_INBOUND: { + Object initialInboundConnection = LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD.get(this.inboundConnection); + return MINECRAFT_CONNECTION_FIELD.get(initialInboundConnection); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return null; + } + + public ConnectionType getConnectionType() { + return connectionType; + } + + enum ConnectionType { + LOGIN_INBOUND, INITIAL_INBOUND, LEGACY, UNKNOWN + } } diff --git a/src/main/resources/velocity-plugin.json b/src/main/resources/velocity-plugin.json index 67837b4..de420ca 100644 --- a/src/main/resources/velocity-plugin.json +++ b/src/main/resources/velocity-plugin.json @@ -1,16 +1 @@ -{ - "id": "tcpshield", - "name": "TCPShield", - "version": "2.8.1", - "description": "TCPShield IP parsing capabilities for Velocity", - "authors": [ - "TCPShield" - ], - "dependencies": [ - { - "id": "floodgate", - "optional": true - } - ], - "main": "net.tcpshield.tcpshield.velocity.TCPShieldVelocity" -} \ No newline at end of file +{"id":"tcpshield","name":"TCPShield","version":"2.8.1","description":"TCPShield IP parsing capabilities for Velocity","authors":["TCPShield"],"dependencies":[{"id":"floodgate","optional":true}],"main":"net.tcpshield.tcpshield.velocity.TCPShieldVelocity"} \ No newline at end of file