Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
554d6c300e | ||
|
|
133cef037e | ||
|
|
bb7511d37f | ||
|
|
78666de764 | ||
|
|
0534b8eae8 | ||
|
|
1af7f1efde | ||
|
|
41ff3f412c | ||
|
|
cfbd6ffac5 | ||
|
|
cf97e37632 | ||
|
|
1629334e71 | ||
|
|
8cb66fc87a | ||
|
|
e868bab503 | ||
|
|
2daad65b33 | ||
|
|
846f4d0a6e | ||
|
|
c07b71c5b1 |
No files matched your search
+4
-1
@@ -10,4 +10,7 @@ build/
|
||||
.gradle/
|
||||
gradle/
|
||||
gradlew
|
||||
gradlew.bat
|
||||
gradlew.bat
|
||||
|
||||
libs/
|
||||
|
||||
@@ -28,6 +28,7 @@ See [Contact](https://tcpshield.com/#contact)
|
||||
|
||||
These wonderful contributors have helped TCPShield make this plugin better!
|
||||
|
||||
* [Dylan Keir](https://github.com/DylanKeir)
|
||||
* [Paul Zhang](https://github.com/paulzhng)
|
||||
* [RyanDeLap](https://github.com/RyanDeLap)
|
||||
* [PlumpOrange](https://github.com/xPlumpOrange/)
|
||||
+11
-15
@@ -5,7 +5,6 @@ import org.yaml.snakeyaml.Yaml
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
|
||||
// --
|
||||
// Building
|
||||
// --
|
||||
@@ -24,15 +23,13 @@ plugins {
|
||||
id 'idea'
|
||||
}
|
||||
|
||||
|
||||
// --
|
||||
// Variables
|
||||
// --
|
||||
version = '2.5.2'
|
||||
version = '2.8.0'
|
||||
group = 'net.tcpshield.tcpshield'
|
||||
archivesBaseName = 'TCPShield'
|
||||
|
||||
|
||||
// --
|
||||
// Misc.
|
||||
// --
|
||||
@@ -63,11 +60,11 @@ sourceSets {
|
||||
}
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = '11' // Will switch to Java 16 in a future release
|
||||
sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
|
||||
// --
|
||||
// Dependencies
|
||||
// --
|
||||
@@ -85,31 +82,30 @@ repositories {
|
||||
url = 'https://oss.sonatype.org/content/repositories/snapshots'
|
||||
}
|
||||
maven {
|
||||
url = 'https://papermc.io/repo/repository/maven-public/'
|
||||
url = 'https://repo.papermc.io/repository/maven-public/'
|
||||
}
|
||||
maven {
|
||||
url = 'https://repo.velocitypowered.com/snapshots/'
|
||||
url = "https://repo.opencollab.dev/maven-snapshots/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
// Bukkit
|
||||
compileOnly group: 'org.spigotmc', name: 'spigot-api', version: '1.11-R0.1-SNAPSHOT'
|
||||
compileOnly group: 'com.comphenix.protocol', name: 'ProtocolLib', version: '4.4.0'
|
||||
compileOnly group: 'com.comphenix.protocol', name: 'ProtocolLib', version: '5.1.0'
|
||||
|
||||
// Paper
|
||||
compileOnly group: 'com.destroystokyo.paper', name: 'paper-api', version: '1.15.2-R0.1-SNAPSHOT'
|
||||
// Paper - 1.19.4 so we can bump from JDK 8 -> JDK 17, using 1.20.x as a dependency would require bumping from JDK 8 -> JDK 21
|
||||
compileOnly group: 'io.papermc.paper', name: 'paper-api', version: '1.19.4-R0.1-SNAPSHOT'
|
||||
|
||||
// BungeeCord
|
||||
compileOnly group: 'net.md-5', name: 'bungeecord-api', version: '1.14-SNAPSHOT'
|
||||
|
||||
// Velocity
|
||||
compileOnly group: 'com.velocitypowered', name: 'velocity-api', version: '1.0.0-SNAPSHOT'
|
||||
compileOnly group: 'com.velocitypowered', name: 'velocity-api', version: '3.3.0-SNAPSHOT'
|
||||
|
||||
// Testing
|
||||
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0-M1'
|
||||
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.7.0-M1'
|
||||
compileOnly 'org.geysermc.floodgate:api:2.1.1-SNAPSHOT'
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -175,4 +171,4 @@ void updateJsons() {
|
||||
}
|
||||
}
|
||||
|
||||
build.dependsOn updateVersion
|
||||
build.dependsOn updateVersion
|
||||
@@ -1,22 +1,26 @@
|
||||
package net.tcpshield.tcpshield;
|
||||
|
||||
import net.tcpshield.tcpshield.geyser.GeyserUtils;
|
||||
import net.tcpshield.tcpshield.provider.PacketProvider;
|
||||
import net.tcpshield.tcpshield.provider.PlayerProvider;
|
||||
import net.tcpshield.tcpshield.util.exception.parse.InvalidPayloadException;
|
||||
import net.tcpshield.tcpshield.util.exception.parse.SignatureValidationException;
|
||||
import net.tcpshield.tcpshield.util.exception.parse.TimestampValidationException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.HandshakeException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.InvalidSecretException;
|
||||
import net.tcpshield.tcpshield.util.validation.SignatureValidator;
|
||||
import net.tcpshield.tcpshield.util.validation.cidr.CIDRValidator;
|
||||
import net.tcpshield.tcpshield.util.validation.timestamp.TimestampValidator;
|
||||
import net.tcpshield.tcpshield.util.validation.timestamp.impl.HTPDateTimestampValidator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Packet handler for TCPShield's plugins
|
||||
@@ -31,6 +35,7 @@ public class TCPShieldPacketHandler {
|
||||
|
||||
/**
|
||||
* Creates an instance of the TCPShieldPacketHandler
|
||||
*
|
||||
* @param plugin The TCPShield plugin
|
||||
*/
|
||||
public TCPShieldPacketHandler(TCPShieldPlugin plugin) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
|
||||
@@ -39,12 +44,12 @@ public class TCPShieldPacketHandler {
|
||||
initValidators();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initiates the validators
|
||||
*
|
||||
* @throws NoSuchAlgorithmException SignatureValidator exception
|
||||
* @throws IOException SignatureValidator exception
|
||||
* @throws InvalidKeySpecException SignatureValidator exception
|
||||
* @throws IOException SignatureValidator exception
|
||||
* @throws InvalidKeySpecException SignatureValidator exception
|
||||
*/
|
||||
private void initValidators() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
|
||||
signatureValidator = new SignatureValidator();
|
||||
@@ -78,6 +83,7 @@ public class TCPShieldPacketHandler {
|
||||
* Handles the packet and player manipulation
|
||||
* for the initial handshake from TCPShield
|
||||
* servers
|
||||
*
|
||||
* @param packet The handshake packet
|
||||
* @param player The involved player
|
||||
*/
|
||||
@@ -86,43 +92,57 @@ public class TCPShieldPacketHandler {
|
||||
InetAddress inetAddress = InetAddress.getByName(player.getIP());
|
||||
|
||||
String extraData = null;
|
||||
String cleanedPayload;
|
||||
|
||||
|
||||
int nullIndex;
|
||||
if ((nullIndex = packet.getPayloadString().indexOf('\0')) != -1) { // FML tagged payload
|
||||
cleanedPayload = packet.getPayloadString().substring(0, nullIndex);
|
||||
extraData = packet.getPayloadString().substring(nullIndex);
|
||||
} else // Standard payload
|
||||
cleanedPayload = packet.getPayloadString();
|
||||
|
||||
String[] payload = cleanedPayload.split("///", 4);
|
||||
|
||||
String[] payload = packet.getPayloadString().split("///");
|
||||
|
||||
if (payload.length != 4)
|
||||
if (cidrValidator.validate(inetAddress))
|
||||
return; // Allow connection with no processing
|
||||
else
|
||||
throw new InvalidPayloadException();
|
||||
throw new InvalidPayloadException("length: " + payload.length + ", payload: " + Arrays.toString(payload) + ", raw payload: " + packet.getPayloadString());
|
||||
|
||||
int nullIndex;
|
||||
if ((nullIndex = payload[3].indexOf('\0')) != -1) { // FML tagged payload
|
||||
String originalData = payload[3];
|
||||
payload[3] = originalData.substring(0, nullIndex);
|
||||
extraData = originalData.substring(nullIndex);
|
||||
}
|
||||
|
||||
String hostname = payload[0];
|
||||
String ipData = payload[1];
|
||||
int timestamp = Integer.parseInt(payload[2]);
|
||||
String signature = payload[3];
|
||||
|
||||
if (!timestampValidator.validate(timestamp))
|
||||
throw new TimestampValidationException(timestampValidator, timestamp);
|
||||
String[] ipParts;
|
||||
String host;
|
||||
int port;
|
||||
|
||||
if (timestamp == 0 && GeyserUtils.GEYSER_SUPPORT_ENABLED) {
|
||||
// Remap the altered layout
|
||||
ipData = payload[0];
|
||||
signature = payload[1];
|
||||
hostname = payload[3];
|
||||
|
||||
// This is annoying having to have this in both blocks but w/e
|
||||
ipParts = ipData.split(":");
|
||||
host = ipParts[0];
|
||||
port = Integer.parseInt(ipParts[1]);
|
||||
|
||||
if (!signature.equals(GeyserUtils.SESSION_SECRET)) {
|
||||
throw new InvalidSecretException("Invalid secret: " + signature);
|
||||
}
|
||||
} else {
|
||||
ipParts = ipData.split(":");
|
||||
host = ipParts[0];
|
||||
port = Integer.parseInt(ipParts[1]);
|
||||
String reconstructedPayload = hostname + "///" + host + ":" + port + "///" + timestamp;
|
||||
|
||||
if (!timestampValidator.validate(timestamp))
|
||||
throw new TimestampValidationException(timestampValidator, timestamp);
|
||||
|
||||
|
||||
String[] ipParts = ipData.split(":");
|
||||
String host = ipParts[0];
|
||||
int port = Integer.parseInt(ipParts[1]);
|
||||
|
||||
String reconstructedPayload = hostname + "///" + host + ":" + port + "///" + timestamp;
|
||||
|
||||
if (!signatureValidator.validate(reconstructedPayload, signature))
|
||||
throw new SignatureValidationException();
|
||||
|
||||
if (!signatureValidator.validate(reconstructedPayload, signature))
|
||||
throw new SignatureValidationException();
|
||||
}
|
||||
|
||||
InetSocketAddress newIP = new InetSocketAddress(host, port);
|
||||
player.setIP(newIP);
|
||||
@@ -163,6 +183,14 @@ public class TCPShieldPacketHandler {
|
||||
if (plugin.getConfigProvider().isOnlyProxy())
|
||||
player.disconnect();
|
||||
|
||||
throw new HandshakeException(e);
|
||||
} catch (InvalidSecretException e) {
|
||||
plugin.getDebugger().warn(
|
||||
"%s[%s/%s] provided an invalid session secret when authenticating a geyser connection.",
|
||||
player.getName(), player.getUUID(), player.getIP());
|
||||
if (plugin.getConfigProvider().isOnlyProxy())
|
||||
player.disconnect();
|
||||
|
||||
throw new HandshakeException(e);
|
||||
} catch (Exception e) {
|
||||
if (plugin.getConfigProvider().isOnlyProxy())
|
||||
|
||||
@@ -12,24 +12,28 @@ public interface TCPShieldPlugin {
|
||||
|
||||
/**
|
||||
* Gets the plugin's config provider
|
||||
*
|
||||
* @return The plugin's config provider
|
||||
*/
|
||||
ConfigProvider getConfigProvider();
|
||||
|
||||
/**
|
||||
* Gets the plugin's logger
|
||||
*
|
||||
* @return The plugin's logger
|
||||
*/
|
||||
Logger getLogger();
|
||||
|
||||
/**
|
||||
* Gets the packet handler
|
||||
*
|
||||
* @return The packet handler
|
||||
*/
|
||||
TCPShieldPacketHandler getPacketHandler();
|
||||
|
||||
/**
|
||||
* Gets the plugin's debugger
|
||||
*
|
||||
* @return The plugin's debugger
|
||||
*/
|
||||
Debugger getDebugger();
|
||||
@@ -40,12 +44,15 @@ public interface TCPShieldPlugin {
|
||||
*/
|
||||
default void initialization() {
|
||||
String jvmVersion = System.getProperty("java.version");
|
||||
|
||||
// Java 11 check/warning (Will eventually force Java 16 without warning)
|
||||
String[] versionParts = jvmVersion.split("\\.");
|
||||
int baseVersion = Integer.parseInt(versionParts[0]);
|
||||
if (baseVersion < 11) // Java 8, and below, starts with 1, but since we are using Java 11 we can ignore sub values
|
||||
this.getDebugger().warn("The Java version you are running is outdated for TCPShield and may cause issues. Update to atleast Java 11. Your version: Java %s", jvmVersion);
|
||||
try {
|
||||
// Java 11 check/warning (Will eventually force Java 16 without warning)
|
||||
String[] versionParts = jvmVersion.split("\\.");
|
||||
int baseVersion = Integer.parseInt(versionParts[0]);
|
||||
if (baseVersion < 11) // Java 8, and below, starts with 1, but since we are using Java 11 we can ignore sub values
|
||||
this.getDebugger().warn("The Java version you are running is outdated for TCPShield and may cause issues. Update to atleast Java 11. Your version: Java %s", jvmVersion);
|
||||
} catch (Throwable t) {
|
||||
this.getDebugger().error("Failed to check java version for string: " + jvmVersion);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,6 @@ public class BukkitConfig extends ConfigProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void checkNodes(String... nodes) {
|
||||
for (String node : nodes) {
|
||||
@@ -67,11 +66,13 @@ public class BukkitConfig extends ConfigProvider {
|
||||
try {
|
||||
loadedConfiguration = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
checkNodes("only-allow-proxy-connections", "timestamp-validation", "debug-mode");
|
||||
checkNodes("only-allow-proxy-connections", "timestamp-validation", "debug-mode", "enable-geyser-support", "prefer-protocollib");
|
||||
|
||||
this.onlyProxy = loadedConfiguration.getBoolean("only-allow-proxy-connections");
|
||||
this.timestampValidationMode = loadedConfiguration.getString("timestamp-validation");
|
||||
this.doDebug = loadedConfiguration.getBoolean("debug-mode");
|
||||
this.geyser = loadedConfiguration.getBoolean("enable-geyser-support");
|
||||
this.preferProtocolLib = loadedConfiguration.getBoolean("prefer-protocollib");
|
||||
} catch (Exception e) {
|
||||
throw new ConfigLoadException(e);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package net.tcpshield.tcpshield.bukkit;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import net.tcpshield.tcpshield.TCPShieldPacketHandler;
|
||||
import net.tcpshield.tcpshield.TCPShieldPlugin;
|
||||
import net.tcpshield.tcpshield.bukkit.paper.BukkitPaper;
|
||||
import net.tcpshield.tcpshield.bukkit.protocollib.BukkitProtocolLib;
|
||||
import net.tcpshield.tcpshield.bukkit.provider.BukkitImplProvider;
|
||||
import net.tcpshield.tcpshield.geyser.GeyserUtils;
|
||||
import net.tcpshield.tcpshield.provider.ConfigProvider;
|
||||
import net.tcpshield.tcpshield.util.Debugger;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.InitializationException;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
@@ -21,7 +24,6 @@ public class TCPShieldBukkit extends JavaPlugin implements TCPShieldPlugin {
|
||||
|
||||
private BukkitImplProvider bukkitImpl;
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
@@ -29,23 +31,45 @@ public class TCPShieldBukkit extends JavaPlugin implements TCPShieldPlugin {
|
||||
debugger = Debugger.createDebugger(this);
|
||||
packetHandler = new TCPShieldPacketHandler(this);
|
||||
|
||||
if (BukkitImplProvider.hasPaperEvent())
|
||||
bukkitImpl = new BukkitPaper(this);
|
||||
else {
|
||||
if (getServer().getPluginManager().getPlugin("ProtocolLib") == null) {
|
||||
getLogger().severe("TCPShield not loading because ProtocolLib is not installed. Either use Paper to enable native compatibility or install ProtocolLib.");
|
||||
return;
|
||||
}
|
||||
// check force plib option -> paper -> plib -> error
|
||||
if (this.configProvider.preferProtocolLib() && getServer().getPluginManager().getPlugin("ProtocolLib") != null) {
|
||||
try {
|
||||
String[] protocolLibVersion = getServer().getPluginManager().getPlugin("ProtocolLib").getDescription().getVersion().split("-")[0].split("\\.");
|
||||
int major = Integer.parseInt(protocolLibVersion[0]);
|
||||
int minor = Integer.parseInt(protocolLibVersion[1]);
|
||||
int patch = Integer.parseInt(protocolLibVersion[2]);
|
||||
|
||||
String paperVersion = Bukkit.getServer().getMinecraftVersion();
|
||||
if (major <= 5 && minor <= 2 && patch <= 1 && (paperVersion.equals("1.20.5") || paperVersion.equals("1.20.6"))) {
|
||||
getLogger().severe("TCPShield is incompatible with ProtocolLib <= 5.2.1 on Paper 1.20.5/1.20.6 due to lack of support from ProtocolLib. Reverting to default Paper handler to prevent issues. This error can be avoided by disabling 'prefer-protocollib' in the config.");
|
||||
bukkitImpl = new BukkitPaper(this);
|
||||
} else {
|
||||
bukkitImpl = new BukkitProtocolLib(this);
|
||||
}
|
||||
} catch (Exception t) {
|
||||
getLogger().warning("Failed to check Paper or ProtocolLib version. This is not a critical error unless you are running Paper 1.20.5/1.20.6 with ProtocolLib version 5.2.1 or below.");
|
||||
getDebugger().exception(t);
|
||||
|
||||
bukkitImpl = new BukkitProtocolLib(this);
|
||||
}
|
||||
} else if (BukkitImplProvider.hasPaperEvent()) {
|
||||
bukkitImpl = new BukkitPaper(this);
|
||||
} else if (getServer().getPluginManager().getPlugin("ProtocolLib") != null) {
|
||||
bukkitImpl = new BukkitProtocolLib(this);
|
||||
} else {
|
||||
getLogger().severe("TCPShield not loading because ProtocolLib is not installed. Either use Paper to enable native compatibility or install ProtocolLib.");
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitImpl.load();
|
||||
|
||||
GeyserUtils.initGeyser(this, configProvider);
|
||||
|
||||
initialization();
|
||||
} catch (Exception e) {
|
||||
throw new InitializationException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -68,4 +92,9 @@ public class TCPShieldBukkit extends JavaPlugin implements TCPShieldPlugin {
|
||||
return configProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return super.getLogger();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@ public class BukkitPaper extends BukkitImplProvider {
|
||||
super(bukkitPlugin);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
PaperHandshakeHandler packetHandler = new PaperHandshakeHandler(this);
|
||||
|
||||
+2
-1
@@ -19,7 +19,6 @@ public class PaperHandshakeHandler implements Listener {
|
||||
this.bukkitProvider = bukkitProvider;
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onHandshake(PlayerHandshakeEvent e) {
|
||||
PaperPacket packet = new PaperPacket(e);
|
||||
@@ -36,6 +35,8 @@ public class PaperHandshakeHandler implements Listener {
|
||||
public void onServerPing(PaperServerListPingEvent e) {
|
||||
if (e.getClient().isLegacy())
|
||||
e.setCancelled(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,6 @@ public class PaperPacket implements PacketProvider {
|
||||
this.handshakeEvent = handshakeEvent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPayloadString() {
|
||||
return handshakeEvent.getOriginalHandshake();
|
||||
|
||||
@@ -18,7 +18,6 @@ public class PaperPlayer implements PlayerProvider {
|
||||
this.handshakeEvent = handshakeEvent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trys to grab the UUID of the handshake
|
||||
* @return If found, the corrosponding uuid, if not, unknown
|
||||
@@ -58,7 +57,7 @@ public class PaperPlayer implements PlayerProvider {
|
||||
@Override
|
||||
public void disconnect() {
|
||||
handshakeEvent.setCancelled(false); // Caused issues with newer versions of Paper (Thanks https://github.com/realDragonium)
|
||||
handshakeEvent.setFailMessage("Connection failed. Please try again or contract an administrator.");
|
||||
handshakeEvent.setFailMessage("Connection failed. Please try again or contact an administrator.");
|
||||
handshakeEvent.setFailed(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ public class BukkitProtocolLib extends BukkitImplProvider {
|
||||
super(bukkitPlugin);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
ProtocolLibHandshakeHandler packetHandler = new ProtocolLibHandshakeHandler(this);
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ public class ProtocolLibHandshakeHandler extends PacketAdapter {
|
||||
this.bukkitProvider = bukkitProvider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent e) {
|
||||
ProtocolLibPacket packet = new ProtocolLibPacket(e.getPacket());
|
||||
|
||||
-1
@@ -17,7 +17,6 @@ public class ProtocolLibPacket implements PacketProvider {
|
||||
this.rawPayload = packetContainer.getStrings().read(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPayloadString() {
|
||||
return rawPayload;
|
||||
|
||||
+4
-5
@@ -1,7 +1,7 @@
|
||||
package net.tcpshield.tcpshield.bukkit.protocollib.handler;
|
||||
|
||||
import com.comphenix.protocol.injector.server.SocketInjector;
|
||||
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
|
||||
import com.comphenix.protocol.injector.temporary.MinimalInjector;
|
||||
import com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory;
|
||||
import net.tcpshield.tcpshield.provider.PlayerProvider;
|
||||
import net.tcpshield.tcpshield.util.ReflectionUtil;
|
||||
import net.tcpshield.tcpshield.util.exception.manipulate.PlayerManipulationException;
|
||||
@@ -34,7 +34,6 @@ public class ProtocolLibPlayer implements PlayerProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Player player;
|
||||
private String ip;
|
||||
|
||||
@@ -72,13 +71,13 @@ public class ProtocolLibPlayer implements PlayerProvider {
|
||||
try {
|
||||
this.ip = ip.getAddress().getHostAddress();
|
||||
|
||||
SocketInjector ignored = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
||||
MinimalInjector ignored = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
||||
Object injector = ReflectionUtil.getObjectInPrivateField(ignored, "injector");
|
||||
Object networkManager = ReflectionUtil.getObjectInPrivateField(injector, "networkManager");
|
||||
|
||||
ReflectionUtil.setFinalField(networkManager, ReflectionUtil.searchFieldByClass(networkManager.getClass(), SocketAddress.class), ip);
|
||||
|
||||
Object channel = ReflectionUtil.getObjectInPrivateField(injector, "originalChannel");
|
||||
Object channel = ReflectionUtil.getObjectInPrivateField(injector, "wrappedChannel");
|
||||
ReflectionUtil.setFinalField(channel, ReflectionUtil.getDeclaredField(abstractChannelClass, "remoteAddress"), ip);
|
||||
} catch (Exception e) {
|
||||
throw new PlayerManipulationException(e);
|
||||
|
||||
@@ -37,7 +37,6 @@ public class BungeeConfig extends ConfigProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void checkNodes(String... nodes) {
|
||||
for (String node : nodes) {
|
||||
@@ -76,6 +75,7 @@ public class BungeeConfig extends ConfigProvider {
|
||||
this.onlyProxy = loadedConfiguration.getBoolean("only-allow-proxy-connections");
|
||||
this.timestampValidationMode = loadedConfiguration.getString("timestamp-validation");
|
||||
this.doDebug = loadedConfiguration.getBoolean("debug-mode");
|
||||
this.geyser = loadedConfiguration.getBoolean("enable-geyser-support");
|
||||
} catch (Exception e) {
|
||||
throw new ConfigLoadException(e);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.tcpshield.tcpshield.TCPShieldPacketHandler;
|
||||
import net.tcpshield.tcpshield.TCPShieldPlugin;
|
||||
import net.tcpshield.tcpshield.bungee.handler.BungeeHandshakeHandler;
|
||||
import net.tcpshield.tcpshield.geyser.GeyserUtils;
|
||||
import net.tcpshield.tcpshield.provider.ConfigProvider;
|
||||
import net.tcpshield.tcpshield.util.Debugger;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.InitializationException;
|
||||
@@ -19,7 +20,6 @@ public class TCPShieldBungee extends Plugin implements TCPShieldPlugin, Listener
|
||||
private TCPShieldPacketHandler packetHandler;
|
||||
private Debugger debugger;
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
@@ -30,13 +30,14 @@ public class TCPShieldBungee extends Plugin implements TCPShieldPlugin, Listener
|
||||
PluginManager pluginManager = this.getProxy().getPluginManager();
|
||||
pluginManager.registerListener(this, new BungeeHandshakeHandler(this));
|
||||
|
||||
GeyserUtils.initGeyser(this, configProvider);
|
||||
|
||||
initialization();
|
||||
} catch (Exception e) {
|
||||
throw new InitializationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The provider's base methods
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,8 @@ public class BungeeHandshakeHandler implements Listener {
|
||||
BungeePacket packet = new BungeePacket(e.getHandshake(), e.getConnection());
|
||||
BungeePlayer player = new BungeePlayer(e.getConnection());
|
||||
|
||||
this.plugin.getDebugger().warn("BungeeCord: Raw player hostname: " + packet.getPayloadString());
|
||||
|
||||
try {
|
||||
plugin.getPacketHandler().handleHandshake(packet, player);
|
||||
} catch (HandshakeException exception) {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package net.tcpshield.tcpshield.bungee.handler;
|
||||
|
||||
import io.netty.channel.AbstractChannel;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.tcpshield.tcpshield.provider.PlayerProvider;
|
||||
import net.tcpshield.tcpshield.util.ReflectionUtil;
|
||||
import net.tcpshield.tcpshield.util.exception.manipulate.PlayerManipulationException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.HandshakeException;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -28,6 +26,7 @@ public class BungeePlayer implements PlayerProvider {
|
||||
|
||||
/**
|
||||
* Trys to grab the UUID of the handshake
|
||||
*
|
||||
* @return If found, the corrosponding uuid, if not, unknown
|
||||
*/
|
||||
@Override
|
||||
@@ -64,8 +63,12 @@ public class BungeePlayer implements PlayerProvider {
|
||||
// Some BungeeCord versions, notably those on 1.7 (e.g. zBungeeCord) don't have an SocketAddress field in the ChannelWrapper class
|
||||
}
|
||||
|
||||
ReflectionUtil.setFinalField(channel, ReflectionUtil.getPrivateField(AbstractChannel.class, "remoteAddress"), ip);
|
||||
ReflectionUtil.setFinalField(channel, ReflectionUtil.getPrivateField(AbstractChannel.class, "localAddress"), ip);
|
||||
ReflectionUtil.setFinalField(channel, ReflectionUtil.getPrivateField(channel.getClass(), "remoteAddress"), ip);
|
||||
try {
|
||||
ReflectionUtil.setFinalField(channel, ReflectionUtil.getPrivateField(channel.getClass(), "localAddress"), ip);
|
||||
} catch (Throwable t) {
|
||||
// ChannelWrapper doesn't have a localAddress
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new PlayerManipulationException(e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.tcpshield.tcpshield.geyser;
|
||||
|
||||
import net.tcpshield.tcpshield.TCPShieldPlugin;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class GeyserHandshakeHandler {
|
||||
|
||||
private final TCPShieldPlugin plugin;
|
||||
|
||||
public GeyserHandshakeHandler(TCPShieldPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
InstanceHolder.getHandshakeHandlers().addHandshakeHandler(data -> {
|
||||
if (data.getIp() == null) {
|
||||
// not bedrock
|
||||
this.plugin.getDebugger().warn("Connection with no bedrock data joined and ignored: username = %s, hostname = %s", data.getCorrectUsername(), data.getHostname());
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.getDebugger().warn("Bedrock connection joined and validated: username = %s, hostname = %s", data.getCorrectUsername(), data.getHostname());
|
||||
|
||||
String oldPayload = data.getHostname();
|
||||
if (oldPayload.contains("///")) {
|
||||
oldPayload = oldPayload.split("///")[0];
|
||||
}
|
||||
|
||||
String hostname = oldPayload;
|
||||
String realIp = data.getIp();
|
||||
String timestamp = "0";
|
||||
String signature = GeyserUtils.SESSION_SECRET;
|
||||
|
||||
// so floodgate likes to append "\0Floodgate\0" or something stupid to the hostname
|
||||
// which just completely breaks this, so we have to pass these in a different
|
||||
// order to stop bungeecord detecting it as FML data, thanks floodgate.
|
||||
String newHostname = realIp + ":0///" + signature + "///" + timestamp + "///" + hostname;
|
||||
if (hostname.contains("\0")) { // this is usually fine because FML, providing the hostname is first
|
||||
this.plugin.getDebugger().warn("Hostname contains null byte: " + Arrays.toString(hostname.toCharArray()));
|
||||
}
|
||||
|
||||
this.plugin.getDebugger().warn("Setting hostname to %s - %s", newHostname, Arrays.toString(newHostname.toCharArray()));
|
||||
data.setHostname(newHostname);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.tcpshield.tcpshield.geyser;
|
||||
|
||||
import net.tcpshield.tcpshield.TCPShieldPlugin;
|
||||
import net.tcpshield.tcpshield.provider.ConfigProvider;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GeyserUtils {
|
||||
|
||||
public static final String SESSION_SECRET = UUID.randomUUID().toString();
|
||||
public static boolean GEYSER_SUPPORT_ENABLED = false;
|
||||
|
||||
public static void initGeyser(TCPShieldPlugin plugin, ConfigProvider config) {
|
||||
if (!(GEYSER_SUPPORT_ENABLED = useGeyser(config))) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserHandshakeHandler geyserHandler = new GeyserHandshakeHandler(plugin);
|
||||
geyserHandler.init();
|
||||
}
|
||||
|
||||
private static boolean useGeyser(ConfigProvider config) {
|
||||
if (!config.isGeyser()) return false;
|
||||
|
||||
try {
|
||||
Class.forName("org.geysermc.floodgate.api.InstanceHolder");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,13 +18,25 @@ public abstract class ConfigProvider {
|
||||
protected boolean onlyProxy = true;
|
||||
protected String timestampValidationMode = "htpdate";
|
||||
protected boolean doDebug = true; // Fail-safe default set to true
|
||||
protected boolean geyser = false;
|
||||
protected boolean velocityHandlePreLoginEvent = true;
|
||||
|
||||
// spigot/paper only option
|
||||
protected boolean preferProtocolLib;
|
||||
|
||||
protected File dataFolder;
|
||||
protected File configFile;
|
||||
|
||||
|
||||
public boolean isOnlyProxy() {
|
||||
return onlyProxy;
|
||||
return this.onlyProxy;
|
||||
}
|
||||
|
||||
public boolean isGeyser() {
|
||||
return this.geyser;
|
||||
}
|
||||
|
||||
public boolean handlePreLoginEvent() {
|
||||
return this.velocityHandlePreLoginEvent;
|
||||
}
|
||||
|
||||
public String getTimestampValidationMode() {
|
||||
@@ -32,7 +44,11 @@ public abstract class ConfigProvider {
|
||||
}
|
||||
|
||||
public boolean doDebug() {
|
||||
return doDebug;
|
||||
return this.doDebug;
|
||||
}
|
||||
|
||||
public boolean preferProtocolLib() {
|
||||
return this.preferProtocolLib;
|
||||
}
|
||||
|
||||
public File getDataFolder() {
|
||||
@@ -53,7 +69,6 @@ public abstract class ConfigProvider {
|
||||
return maxTimestampDifference;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Required methods
|
||||
*/
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package net.tcpshield.tcpshield.util.exception.phase;
|
||||
|
||||
import net.tcpshield.tcpshield.util.exception.TCPShieldException;
|
||||
|
||||
public class InvalidSecretException extends TCPShieldException {
|
||||
|
||||
public InvalidSecretException(Throwable throwable) {
|
||||
super("An invalid secret was provided during the geyser handshake process", throwable);
|
||||
}
|
||||
|
||||
|
||||
public InvalidSecretException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public InvalidSecretException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
|
||||
public InvalidSecretException() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import net.tcpshield.tcpshield.TCPShieldPacketHandler;
|
||||
import net.tcpshield.tcpshield.TCPShieldPlugin;
|
||||
import net.tcpshield.tcpshield.geyser.GeyserUtils;
|
||||
import net.tcpshield.tcpshield.provider.ConfigProvider;
|
||||
import net.tcpshield.tcpshield.util.Debugger;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.InitializationException;
|
||||
@@ -41,7 +42,6 @@ public class TCPShieldVelocity implements TCPShieldPlugin {
|
||||
this.dataFolder = dataFolder;
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onProxyInitialization(ProxyInitializeEvent e) {
|
||||
try {
|
||||
@@ -51,13 +51,14 @@ public class TCPShieldVelocity implements TCPShieldPlugin {
|
||||
|
||||
server.getEventManager().register(this, new VelocityHandshakeHandler(this));
|
||||
|
||||
GeyserUtils.initGeyser(this, configProvider);
|
||||
|
||||
initialization();
|
||||
} catch (Exception exception) {
|
||||
throw new InitializationException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The provider's base methods
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,6 @@ public class VelocityConfig extends ConfigProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void checkNodes(String... nodes) {
|
||||
for (String node : nodes) {
|
||||
@@ -66,11 +65,13 @@ public class VelocityConfig extends ConfigProvider {
|
||||
try {
|
||||
loadedToml = new Toml().read(configFile);
|
||||
|
||||
checkNodes("only-allow-proxy-connections", "timestamp-validation", "debug-mode");
|
||||
checkNodes("only-allow-proxy-connections", "timestamp-validation", "debug-mode", "enable-geyser-support", "pre-login-event");
|
||||
|
||||
this.onlyProxy = loadedToml.getBoolean("only-allow-proxy-connections");
|
||||
this.timestampValidationMode = loadedToml.getString("timestamp-validation");
|
||||
this.doDebug = loadedToml.getBoolean("debug-mode");
|
||||
this.geyser = loadedToml.getBoolean("enable-geyser-support");
|
||||
this.velocityHandlePreLoginEvent = loadedToml.getBoolean("pre-login-event");
|
||||
} catch (Exception e) {
|
||||
throw new ConfigLoadException(e);
|
||||
}
|
||||
|
||||
+31
-7
@@ -16,39 +16,63 @@ 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);
|
||||
handleEvent(connection, "onPreLogin");
|
||||
}
|
||||
|
||||
@Subscribe(order = PostOrder.FIRST)
|
||||
public void onHandshake(ConnectionHandshakeEvent e) {
|
||||
InboundConnection connection = e.getConnection();
|
||||
handleEvent(connection);
|
||||
handleEvent(connection, "onHandshake");
|
||||
}
|
||||
|
||||
@Subscribe(order = PostOrder.FIRST)
|
||||
public void onProxyPing(ProxyPingEvent e) {
|
||||
InboundConnection connection = e.getConnection();
|
||||
handleEvent(connection);
|
||||
|
||||
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) {
|
||||
private void handleEvent(InboundConnection connection, String debugSource) {
|
||||
VelocityPlayer player = new VelocityPlayer(connection);
|
||||
if (player.isLegacy()) {
|
||||
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) {
|
||||
|
||||
@@ -22,16 +22,36 @@ public class VelocityPacket implements PacketProvider {
|
||||
private static final Field HOSTNAME_FIELD;
|
||||
private static final Field CLEANED_ADDRESS_FIELD;
|
||||
|
||||
// new velocity support
|
||||
private static Class<?> LOGIN_INBOUND_CONNECTION_CLASS;
|
||||
private static Field LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<?> inboundConnection = Class.forName("com.velocitypowered.proxy.connection.client.InitialInboundConnection");
|
||||
|
||||
HANDSHAKE_FIELD = ReflectionUtil.getPrivateField(inboundConnection, "handshake");
|
||||
HOSTNAME_FIELD = ReflectionUtil.getPrivateField(Class.forName("com.velocitypowered.proxy.protocol.packet.Handshake"), "serverAddress");
|
||||
|
||||
Field hostnameField;
|
||||
try {
|
||||
hostnameField = ReflectionUtil.getPrivateField(Class.forName("com.velocitypowered.proxy.protocol.packet.HandshakePacket"), "serverAddress");
|
||||
} catch (Exception e) {
|
||||
hostnameField = ReflectionUtil.getPrivateField(Class.forName("com.velocitypowered.proxy.protocol.packet.Handshake"), "serverAddress");
|
||||
}
|
||||
HOSTNAME_FIELD = hostnameField;
|
||||
|
||||
CLEANED_ADDRESS_FIELD = ReflectionUtil.getPrivateField(inboundConnection, "cleanedAddress");
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +59,15 @@ public class VelocityPacket implements PacketProvider {
|
||||
private final String rawPayload;
|
||||
|
||||
public VelocityPacket(InboundConnection inboundConnection) {
|
||||
// support new velocity connection type
|
||||
if (inboundConnection.getClass() == LOGIN_INBOUND_CONNECTION_CLASS) {
|
||||
try {
|
||||
inboundConnection = (InboundConnection) LOGIN_INBOUND_CONNECTION_DELEGATE_FIELD.get(inboundConnection);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
this.inboundConnection = inboundConnection;
|
||||
try {
|
||||
this.rawPayload = (String) HOSTNAME_FIELD.get(HANDSHAKE_FIELD.get(inboundConnection));
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import net.tcpshield.tcpshield.provider.PlayerProvider;
|
||||
import net.tcpshield.tcpshield.util.ReflectionUtil;
|
||||
import net.tcpshield.tcpshield.util.exception.manipulate.PlayerManipulationException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.HandshakeException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.InitializationException;
|
||||
import net.tcpshield.tcpshield.util.exception.phase.ReflectionException;
|
||||
|
||||
@@ -26,6 +25,11 @@ public class VelocityPlayer implements PlayerProvider {
|
||||
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");
|
||||
@@ -38,22 +42,39 @@ public class VelocityPlayer implements PlayerProvider {
|
||||
} 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 boolean legacy;
|
||||
private final ConnectionType connectionType;
|
||||
private String ip;
|
||||
|
||||
public VelocityPlayer(InboundConnection inboundConnection) {
|
||||
this.inboundConnection = inboundConnection;
|
||||
this.legacy = inboundConnection.getClass() != INITIAL_INBOUND_CONNECTION_CLASS;
|
||||
// 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
|
||||
@@ -63,6 +84,7 @@ public class VelocityPlayer implements PlayerProvider {
|
||||
|
||||
/**
|
||||
* Unsupported with Velocity handshakes
|
||||
*
|
||||
* @return unknown
|
||||
*/
|
||||
@Override
|
||||
@@ -75,26 +97,26 @@ public class VelocityPlayer implements PlayerProvider {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIP(InetSocketAddress ip) throws PlayerManipulationException {
|
||||
try {
|
||||
this.ip = ip.getAddress().getHostAddress();
|
||||
|
||||
Object minecraftConnection = MINECRAFT_CONNECTION_FIELD.get(inboundConnection);
|
||||
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 = legacy ? LEGACY_MINECRAFT_CONNECTION_FIELD.get(inboundConnection) : MINECRAFT_CONNECTION_FIELD.get(inboundConnection);
|
||||
Object minecraftConnection = this.getMinecraftConnection();
|
||||
|
||||
CLOSE_CHANNEL_METHOD.invoke(minecraftConnection);
|
||||
} catch (Exception e) {
|
||||
@@ -102,4 +124,32 @@ public class VelocityPlayer implements PlayerProvider {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
name: TCPShield
|
||||
version: 2.5.2
|
||||
version: 2.8.0
|
||||
main: net.tcpshield.tcpshield.bungee.TCPShieldBungee
|
||||
author: https://tcpshield.com
|
||||
softdepends:
|
||||
- floodgate
|
||||
@@ -5,4 +5,10 @@ only-allow-proxy-connections = true
|
||||
timestamp-validation = 'htpdate'
|
||||
|
||||
# Turn on to diagnose connection issues
|
||||
debug-mode = false
|
||||
debug-mode = false
|
||||
|
||||
# Toggle to enable support for Geyser/Floodgate v2
|
||||
enable-geyser-support = false
|
||||
|
||||
# enable handling handshake on PreLoginEvent
|
||||
pre-login-event = true
|
||||
@@ -5,4 +5,10 @@ only-allow-proxy-connections: true
|
||||
timestamp-validation: 'htpdate'
|
||||
|
||||
# Turn on to diagnose connection issues
|
||||
debug-mode: false
|
||||
debug-mode: false
|
||||
|
||||
# Toggle to enable support for Geyser/Floodgate v2
|
||||
enable-geyser-support: false
|
||||
|
||||
# Spigot/Paper option only, does not affect bungeecord
|
||||
prefer-protocollib: false
|
||||
@@ -1,7 +1,9 @@
|
||||
name: TCPShield
|
||||
version: 2.5.2
|
||||
version: 2.8.0
|
||||
main: net.tcpshield.tcpshield.bukkit.TCPShieldBukkit
|
||||
softdepend:
|
||||
- ProtocolLib
|
||||
- floodgate
|
||||
author: https://tcpshield.com
|
||||
description: TCPShield IP parsing capabilities for Velocity
|
||||
api-version: 1.16
|
||||
@@ -1 +1,16 @@
|
||||
{"id":"tcpshield","name":"TCPShield","version":"2.5.2","description":"TCPShield IP parsing capabilities for Velocity","authors":["TCPShield"],"dependencies":[],"main":"net.tcpshield.tcpshield.velocity.TCPShieldVelocity"}
|
||||
{
|
||||
"id": "tcpshield",
|
||||
"name": "TCPShield",
|
||||
"version": "2.8.0",
|
||||
"description": "TCPShield IP parsing capabilities for Velocity",
|
||||
"authors": [
|
||||
"TCPShield"
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "floodgate",
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"main": "net.tcpshield.tcpshield.velocity.TCPShieldVelocity"
|
||||
}
|
||||
Reference in new issue
Block a user