Skip to content

Commit 6fd1e5e

Browse files
author
games647
committed
Fix TCPShield compat by using raw address for sessions
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
1 parent 213bacf commit 6fd1e5e

File tree

8 files changed

+75
-65
lines changed

8 files changed

+75
-65
lines changed

bukkit/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
<dependency>
146146
<groupId>com.destroystokyo.paper</groupId>
147147
<artifactId>paper-api</artifactId>
148-
<version>1.15.2-R0.1-SNAPSHOT</version>
148+
<version>1.16.5-R0.1-SNAPSHOT</version>
149149
<scope>provided</scope>
150150
</dependency>
151151

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.github.games647.fastlogin.bukkit;
2727

28+
import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
2829
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
2930
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
3031
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
@@ -51,6 +52,8 @@
5152
import org.bukkit.Bukkit;
5253
import org.bukkit.command.CommandSender;
5354
import org.bukkit.entity.Player;
55+
import org.bukkit.event.EventHandler;
56+
import org.bukkit.event.Listener;
5457
import org.bukkit.plugin.PluginManager;
5558
import org.bukkit.plugin.java.JavaPlugin;
5659
import org.slf4j.Logger;
@@ -64,10 +67,9 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
6467
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
6568
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
6669
private final Logger logger;
67-
70+
private final BukkitScheduler scheduler;
6871
private boolean serverStarted;
6972
private BungeeManager bungeeManager;
70-
private final BukkitScheduler scheduler;
7173
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
7274

7375
private PremiumPlaceholder premiumPlaceholder;
@@ -88,17 +90,26 @@ public void onEnable() {
8890
setEnabled(false);
8991
return;
9092
}
91-
92-
// Check Floodgate config values
93-
if (!isValidFloodgateConfigString("autoLoginFloodgate")
94-
|| !isValidFloodgateConfigString("allowFloodgateNameConflict")) {
95-
setEnabled(false);
96-
return;
97-
}
93+
94+
// Check Floodgate config values
95+
if (!isValidFloodgateConfigString("autoLoginFloodgate")
96+
|| !isValidFloodgateConfigString("allowFloodgateNameConflict")) {
97+
setEnabled(false);
98+
return;
99+
}
98100

99101
bungeeManager = new BungeeManager(this);
100102
bungeeManager.initialize();
101-
103+
104+
getServer().getPluginManager().registerEvents(new Listener() {
105+
106+
@EventHandler
107+
void onHandshake(PlayerHandshakeEvent handshakeEvent) {
108+
handshakeEvent.setCancelled(false);
109+
handshakeEvent.setSocketAddressHostname("192.168.0.1");
110+
}
111+
}, this);
112+
102113
PluginManager pluginManager = getServer().getPluginManager();
103114
if (bungeeManager.isEnabled()) {
104115
markInitialized();
@@ -182,10 +193,6 @@ public ConcurrentMap<String, BukkitLoginSession> getLoginSessions() {
182193
public BukkitLoginSession getSession(InetSocketAddress addr) {
183194
String id = getSessionId(addr);
184195
BukkitLoginSession session = loginSession.get(id);
185-
if (session == null) {
186-
logger.info("No session found for id {}", id);
187-
}
188-
189196
return session;
190197
}
191198

@@ -195,7 +202,6 @@ public String getSessionId(InetSocketAddress addr) {
195202

196203
public void putSession(InetSocketAddress addr, BukkitLoginSession session) {
197204
String id = getSessionId(addr);
198-
logger.info("Starting session {}", id);
199205
loginSession.put(id, session);
200206
}
201207

@@ -256,44 +262,45 @@ public BukkitScheduler getScheduler() {
256262
public void sendMessage(CommandSender receiver, String message) {
257263
receiver.sendMessage(message);
258264
}
259-
260-
/**
261-
* Checks if a config entry (related to Floodgate) is valid. <br>
262-
* Writes to Log if the value is invalid.
263-
* <p>
264-
* This should be used for:
265-
* <ul>
266-
* <li>allowFloodgateNameConflict
267-
* <li>autoLoginFloodgate
268-
* <li>autoRegisterFloodgate
269-
* </ul>
270-
* </p>
271-
*
272-
* @param key the key of the entry in config.yml
273-
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
274-
*/
275-
private boolean isValidFloodgateConfigString(String key) {
276-
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
277-
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
278-
logger.error("Invalid value detected for {} in FastLogin/config.yml.", key);
279-
return false;
280-
}
281-
return true;
282-
}
283-
284-
/**
285-
* Checks if a plugin is installed on the server
286-
* @param name the name of the plugin
287-
* @return true if the plugin is installed
288-
*/
289-
@Override
290-
public boolean isPluginInstalled(String name) {
291-
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
292-
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
293-
}
294265

295266
/**
296-
* Send warning messages to log if incompatible plugins are used
267+
* Checks if a config entry (related to Floodgate) is valid. <br>
268+
* Writes to Log if the value is invalid.
269+
* <p>
270+
* This should be used for:
271+
* <ul>
272+
* <li>allowFloodgateNameConflict
273+
* <li>autoLoginFloodgate
274+
* <li>autoRegisterFloodgate
275+
* </ul>
276+
* </p>
277+
*
278+
* @param key the key of the entry in config.yml
279+
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
280+
*/
281+
private boolean isValidFloodgateConfigString(String key) {
282+
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
283+
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
284+
logger.error("Invalid value detected for {} in FastLogin/config.yml.", key);
285+
return false;
286+
}
287+
return true;
288+
}
289+
290+
/**
291+
* Checks if a plugin is installed on the server
292+
*
293+
* @param name the name of the plugin
294+
* @return true if the plugin is installed
295+
*/
296+
@Override
297+
public boolean isPluginInstalled(String name) {
298+
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
299+
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
300+
}
301+
302+
/**
303+
* Send warning messages to log if incompatible plugins are used
297304
*/
298305
private void dependencyWarnings() {
299306
if (isPluginInstalled("floodgate-bukkit")) {
@@ -303,13 +310,13 @@ private void dependencyWarnings() {
303310
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
304311
logger.warn("Don't forget to update Geyser to a supported version as well from "
305312
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
306-
} else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) {
313+
} else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) {
307314
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
308315
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate's name prefixes from " +
309316
"showing up when it is together used with ProtocolLib.");
310317
logger.warn("If you would like to use Floodgate name prefixes, you can replace ProtocolLib with " +
311318
"ProtocolSupport which does not have this issue.");
312319
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
313-
}
320+
}
314321
}
315322
}

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/hook/AuthMeHook.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,20 @@
2828
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
2929
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
3030
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
31+
3132
import fr.xephi.authme.api.v3.AuthMeApi;
3233
import fr.xephi.authme.events.RestoreSessionEvent;
3334
import fr.xephi.authme.process.Management;
3435
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
3536
import fr.xephi.authme.process.register.executors.RegistrationMethod;
37+
38+
import java.lang.reflect.Field;
39+
3640
import org.bukkit.entity.Player;
3741
import org.bukkit.event.EventHandler;
3842
import org.bukkit.event.EventPriority;
3943
import org.bukkit.event.Listener;
4044

41-
import java.lang.reflect.Field;
42-
4345
/**
4446
* GitHub: https://github.com/Xephi/AuthMeReloaded/
4547
* <p>
@@ -75,7 +77,7 @@ public AuthMeHook(FastLoginBukkit plugin) {
7577
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
7678
Player player = restoreSessionEvent.getPlayer();
7779

78-
BukkitLoginSession session = plugin.getSession(player.getAddress());
80+
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
7981
if (session != null && session.isVerified()) {
8082
restoreSessionEvent.setCancelled(true);
8183
}

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private void onRegisterMessage(Player player, String playerName, InetSocketAddre
126126

127127
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
128128
session.setVerified(true);
129-
plugin.putSession(player.getAddress(), session);
129+
plugin.putSession(player.spigot().getRawAddress(), session);
130130

131131
// only start a new login task if the join event fired earlier. This event then didn
132132
boolean result = plugin.getBungeeManager().didJoinEventFired(player);

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void onPlayerJoin(PlayerJoinEvent joinEvent) {
7272
// session exists so the player is ready for force login
7373
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
7474
// having the login session from the login process
75-
BukkitLoginSession session = plugin.getSession(player.getAddress());
75+
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
7676

7777
boolean isFloodgateLogin = false;
7878
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
@@ -86,7 +86,7 @@ public void onPlayerJoin(PlayerJoinEvent joinEvent) {
8686

8787
if (!isFloodgateLogin) {
8888
if (session == null) {
89-
String sessionId = plugin.getSessionId(player.getAddress());
89+
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
9090
plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId);
9191
} else {
9292
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/VerifyResponseTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private boolean checkVerifyToken(BukkitLoginSession session) throws GeneralSecur
188188

189189
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
190190
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
191-
//check if the verify token are equal to the server sent one
191+
//check if the verify-token are equal to the server sent one
192192
disconnect("invalid-verify-token", true
193193
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
194194
, session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolLoginSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void kick(String message) {
5151

5252
@Override
5353
public InetSocketAddress getAddress() {
54-
return loginStartEvent.getAddress();
54+
return loginStartEvent.getConnection().getRawAddress();
5555
}
5656

5757
public PlayerLoginStartEvent getLoginStartEvent() {

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
7171
}
7272

7373
String username = loginStartEvent.getConnection().getProfile().getName();
74-
InetSocketAddress address = loginStartEvent.getAddress();
74+
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
7575

7676
//remove old data every time on a new login in order to keep the session only for one person
7777
plugin.removeSession(address);
@@ -82,13 +82,14 @@ public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
8282

8383
@EventHandler
8484
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
85-
InetSocketAddress address = closeEvent.getConnection().getAddress();
85+
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
8686
plugin.removeSession(address);
8787
}
8888

8989
@EventHandler
9090
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
91-
InetSocketAddress address = profileCompleteEvent.getAddress();
91+
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
92+
9293
BukkitLoginSession session = plugin.getSession(address);
9394

9495
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {

0 commit comments

Comments
 (0)