TCPShield overwrites the IP address during connection. ProtocolLib
doesn't notice this change, because it uses the end-to-end connection
which is the proxy IP. This causes getAddress calls during Spigot play
state and ProtocolLib auth state not match and then have conflicting
session ids.
A solution is also to hold onto the temporary player object. However
since we don't get a notification for a disconnect, holding it will
prevent to get GCed until the timeout occurs (1 minute).
Fixes#595
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
index ca8a927..bc03268 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
@@ -25,6 +25,7 @@
*/
package com.github.games647.fastlogin.bukkit;
+import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
@@ -55,6 +56,8 @@ import java.util.concurrent.ConcurrentMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.floodgate.api.FloodgateApi;
@@ -104,6 +107,15 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
+ getServer().getPluginManager().registerEvents(new Listener() {
+
+ @EventHandler
+ void onHandshake(PlayerHandshakeEvent handshakeEvent) {
+ handshakeEvent.setCancelled(false);
+ handshakeEvent.setSocketAddressHostname("192.168.0.1");
+ }
+ }, this);
+
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
@@ -290,16 +302,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
receiver.sendMessage(message);
}
- /**
- * Checks if a plugin is installed on the server
- * @param name the name of the plugin
- * @return true if the plugin is installed
- */
- @Override
- public boolean isPluginInstalled(String name) {
- // the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
- return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
- }
+ /**
+ * Checks if a plugin is installed on the server
+ *
+ * @param name the name of the plugin
+ * @return true if the plugin is installed
+ */
+ @Override
+ public boolean isPluginInstalled(String name) {
+ // the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
+ return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
+ }
public FloodgateService getFloodgateService() {
return floodgateService;
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
index 10a396f..01cb4b9 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
@@ -28,18 +28,20 @@ package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
+
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.events.RestoreSessionEvent;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
+
+import java.lang.reflect.Field;
+
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
-import java.lang.reflect.Field;
-
/**
* GitHub: https://github.com/Xephi/AuthMeReloaded/
* <p>
@@ -75,7 +77,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
Player player = restoreSessionEvent.getPlayer();
- BukkitLoginSession session = plugin.getSession(player.getAddress());
+ BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session != null && session.isVerified()) {
restoreSessionEvent.setCancelled(true);
}
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
index 2378450..856aa9a 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
@@ -127,7 +127,7 @@ public class BungeeListener implements PluginMessageListener {
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
session.setVerified(true);
- plugin.putSession(player.getAddress(), session);
+ plugin.putSession(player.spigot().getRawAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn't
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
index 05c9a18..d7c1ef1 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
@@ -80,7 +80,7 @@ public class ConnectionListener implements Listener {
// session exists so the player is ready for force login
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
// having the login session from the login process
- BukkitLoginSession session = plugin.getSession(player.getAddress());
+ BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session == null) {
// Floodgate players usually don't have a session at this point
@@ -95,7 +95,7 @@ public class ConnectionListener implements Listener {
}
}
- String sessionId = plugin.getSessionId(player.getAddress());
+ String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId);
} else {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
index 2e98178..0e182b4 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
@@ -51,7 +51,7 @@ public class ProtocolLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
- return loginStartEvent.getAddress();
+ return loginStartEvent.getConnection().getRawAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
index 8ce23da..6fa5cbe 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
@@ -70,7 +70,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
}
String username = loginStartEvent.getConnection().getProfile().getName();
- InetSocketAddress address = loginStartEvent.getAddress();
+ InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
//remove old data every time on a new login in order to keep the session only for one person
plugin.removeSession(address);
@@ -81,13 +81,14 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
@EventHandler
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
- InetSocketAddress address = closeEvent.getConnection().getAddress();
+ InetSocketAddress address = closeEvent.getConnection().getRawAddress();
plugin.removeSession(address);
}
@EventHandler
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
- InetSocketAddress address = profileCompleteEvent.getAddress();
+ InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
+
BukkitLoginSession session = plugin.getSession(address);
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
index ab4ceed..3165c5d 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
@@ -25,6 +25,7 @@
*/
package com.github.games647.fastlogin.bukkit;
+import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
@@ -55,6 +56,8 @@ import java.util.concurrent.ConcurrentMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.floodgate.api.FloodgateApi;
@@ -104,6 +107,15 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
+ getServer().getPluginManager().registerEvents(new Listener() {
+
+ @EventHandler
+ void onHandshake(PlayerHandshakeEvent handshakeEvent) {
+ handshakeEvent.setCancelled(false);
+ handshakeEvent.setSocketAddressHostname("192.168.0.1");
+ }
+ }, this);
+
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
@@ -290,16 +302,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
receiver.sendMessage(message);
}
- /**
- * Checks if a plugin is installed on the server
- * @param name the name of the plugin
- * @return true if the plugin is installed
- */
- @Override
- public boolean isPluginInstalled(String name) {
- // the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
- return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
- }
+ /**
+ * Checks if a plugin is installed on the server
+ *
+ * @param name the name of the plugin
+ * @return true if the plugin is installed
+ */
+ @Override
+ public boolean isPluginInstalled(String name) {
+ // the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
+ return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
+ }
public FloodgateService getFloodgateService() {
return floodgateService;
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
index 6003c02..26e3d37 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java
@@ -28,18 +28,20 @@ package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
+
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.events.RestoreSessionEvent;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
+
+import java.lang.reflect.Field;
+
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
-import java.lang.reflect.Field;
-
/**
* GitHub: https://github.com/Xephi/AuthMeReloaded/
* <p>
@@ -75,7 +77,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
Player player = restoreSessionEvent.getPlayer();
- BukkitLoginSession session = plugin.getSession(player.getAddress());
+ BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session != null && session.isVerified()) {
restoreSessionEvent.setCancelled(true);
}
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
index 4b72ff8..9de359f 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java
@@ -127,7 +127,7 @@ public class BungeeListener implements PluginMessageListener {
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
session.setVerified(true);
- plugin.putSession(player.getAddress(), session);
+ plugin.putSession(player.spigot().getRawAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn't
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
index d31ef7a..3d12522 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java
@@ -80,7 +80,7 @@ public class ConnectionListener implements Listener {
// session exists so the player is ready for force login
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
// having the login session from the login process
- BukkitLoginSession session = plugin.getSession(player.getAddress());
+ BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session == null) {
// Floodgate players usually don't have a session at this point
@@ -95,7 +95,7 @@ public class ConnectionListener implements Listener {
}
}
- String sessionId = plugin.getSessionId(player.getAddress());
+ String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
plugin.getLog().info("Setups using Minecraft proxies will start delayed " +
"when the command from the proxy is received");
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
index 087b7a3..87aee6f 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java
@@ -51,7 +51,7 @@ public class ProtocolLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
- return loginStartEvent.getAddress();
+ return loginStartEvent.getConnection().getRawAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
index 608078c..cb45e0e 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java
@@ -70,7 +70,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
}
String username = loginStartEvent.getConnection().getProfile().getName();
- InetSocketAddress address = loginStartEvent.getAddress();
+ InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
//remove old data every time on a new login in order to keep the session only for one person
plugin.removeSession(address);
@@ -81,13 +81,14 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
@EventHandler
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
- InetSocketAddress address = closeEvent.getConnection().getAddress();
+ InetSocketAddress address = closeEvent.getConnection().getRawAddress();
plugin.removeSession(address);
}
@EventHandler
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
- InetSocketAddress address = profileCompleteEvent.getAddress();
+ InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
+
BukkitLoginSession session = plugin.getSession(address);
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
The comment for useProxyAgnosticResolver in config.yml was re-phrased and supplied with additional information regarding its effective context and its relation to the prevent-proxy setting in server.properties.
The URL of the mojang session server call in ProxyAgnosticMojangResolver was extracted into a constant in order to mitigate the "magic constants" problem.
Additionally, the 204 in the response code check was replaced by a constant from HttpURLConnection, again, in order to not use any magic numbers.
The initial debug-entry modification regarding the invalid session message was reverted. Now the logging and parameter expansion is done solely by the SLF4J library.
A config option was added to allow users to use the ProxyAgnosticMojangResolver if they feel the need to do so. This setting won't affect existing users since it's disabled by default.
ProxyAgnosticMojangResolver serves as a cleaner implementation of the hasJoined static method from previous commit. All the reflection involved was removed due to no longer being necessary. This way, a lot cleaner code could be made. All the inner workings remained the same. For more information on how it works, check out ProxyAgnosticMojangResolver.java.
This commit contains a crude but functional fix for problem described by issue #810. It works by reimplementing the MojangResolver#hasJoined method using reflection to access the inaccessible fields. The significant difference is that unlike in the CraftAPI implementation, which sends the "ip" parameter when the hostIp parameter is an IPv4 address, but skips it for IPv6, this implementation ommits the "ip" parameter also for IPv4, effectively enabling transparent proxies to work.
WARNING: This commit contains only a proof-of-concept code with crude hacks to make it work with the least amount of code edits. Improvements upon the code will be included in following commits. The code is at the moment really ineffective, and therefore SHOULD NOT BE USED IN PRODUCTION! You have been warned.
If a header is missing, then the build should fail. If someone commits
a new file, WITHOUT building it beforehnd, than that header won't be
added. The CI will build the plugin, but changes made by the CI are not
retained in the source tree.
'autoRegisterFloodgate' and 'autoLoginFloodgate' have the same possible
options, and they are checked against the player in the exact same way.
For example, if either one of them is set to isLinked, linked status is
checked in the same way, regardless of wether it's checked for login or
for registering.