diff --git a/Bungee/src/main/java/me/egg82/antivpn/events/PlayerEvents.java b/Bungee/src/main/java/me/egg82/antivpn/events/PlayerEvents.java index f7e523af..48776a7b 100644 --- a/Bungee/src/main/java/me/egg82/antivpn/events/PlayerEvents.java +++ b/Bungee/src/main/java/me/egg82/antivpn/events/PlayerEvents.java @@ -15,15 +15,18 @@ import me.egg82.antivpn.api.model.ip.IPManager; import me.egg82.antivpn.api.model.player.PlayerManager; import me.egg82.antivpn.api.platform.BungeePlatform; +import me.egg82.antivpn.bungee.BungeeEnvironmentUtil; import me.egg82.antivpn.config.CachedConfig; import me.egg82.antivpn.config.ConfigUtil; import me.egg82.antivpn.hooks.LuckPermsHook; import me.egg82.antivpn.services.lookup.PlayerInfo; import me.egg82.antivpn.services.lookup.PlayerLookup; +import me.egg82.antivpn.utils.LoginEventWrapper; import me.egg82.antivpn.utils.ExceptionUtil; import me.egg82.antivpn.utils.ValidationUtil; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.PostLoginEvent; import net.md_5.bungee.api.event.PreLoginEvent; import net.md_5.bungee.api.plugin.Plugin; @@ -41,12 +44,22 @@ public class PlayerEvents extends EventHolder { public PlayerEvents(@NonNull Plugin plugin, @NonNull CommandIssuer console) { this.console = console; + boolean useLoginEvent = true; + CachedConfig cachedConfig = ConfigUtil.getCachedConfig(); + if (cachedConfig != null) { + useLoginEvent = cachedConfig.getLoginEvent(); + } + if(!useLoginEvent) { + logger.warn("Not using LoginEvent, performance issues and failed UUID lookups expected"); + } + events.add( - BungeeEvents.subscribe(plugin, PreLoginEvent.class, EventPriority.HIGH) + (useLoginEvent ? BungeeEvents.subscribe(plugin, LoginEvent.class, EventPriority.LOW) + : BungeeEvents.subscribe(plugin, PreLoginEvent.class, EventPriority.HIGH)) .handler(e -> e.registerIntent(plugin)) .handler(e -> POOL.submit(() -> { try { - checkPerms(e); + checkPerms(new LoginEventWrapper(e,plugin)); } finally { e.completeIntent(plugin); } @@ -54,8 +67,9 @@ public PlayerEvents(@NonNull Plugin plugin, @NonNull CommandIssuer console) { ); events.add( - BungeeEvents.subscribe(plugin, PostLoginEvent.class, EventPriority.LOWEST) - .handler(this::checkPlayer) + (useLoginEvent ? BungeeEvents.subscribe(plugin, LoginEvent.class, EventPriority.NORMAL) + : BungeeEvents.subscribe(plugin, PostLoginEvent.class, EventPriority.LOWEST)) + .handler(e -> this.checkPlayer(new LoginEventWrapper(e,plugin))) ); events.add( @@ -71,7 +85,7 @@ public PlayerEvents(@NonNull Plugin plugin, @NonNull CommandIssuer console) { ); } - private void checkPerms(@NonNull PreLoginEvent event) { + private void checkPerms(@NonNull LoginEventWrapper event) { Optional luckPermsHook; try { luckPermsHook = ServiceLocator.getOptional(LuckPermsHook.class); @@ -115,7 +129,7 @@ private void checkPerms(@NonNull PreLoginEvent event) { } } - private void checkPermsPlayer(@NonNull PreLoginEvent event, @NonNull UUID uuid, boolean hasBypass) { + private void checkPermsPlayer(@NonNull LoginEventWrapper event, @NonNull UUID uuid, boolean hasBypass) { if (hasBypass) { if (ConfigUtil.getDebugOrFalse()) { console.sendMessage("" + event.getConnection().getName() + " bypasses pre-check. Ignoring."); @@ -160,8 +174,7 @@ private void checkPermsPlayer(@NonNull PreLoginEvent event, @NonNull UUID uuid, } String kickMessage = ipManager.getVpnKickMessage(event.getConnection().getName(), uuid, ip); if (kickMessage != null) { - event.setCancelled(true); - event.setCancelReason(TextComponent.fromLegacyText(kickMessage)); + event.disconnect(ip,false,TextComponent.fromLegacyText(kickMessage)); } } @@ -174,13 +187,12 @@ private void checkPermsPlayer(@NonNull PreLoginEvent event, @NonNull UUID uuid, } String kickMessage = playerManager.getMcLeaksKickMessage(event.getConnection().getName(), uuid, ip); if (kickMessage != null) { - event.setCancelled(true); - event.setCancelReason(TextComponent.fromLegacyText(kickMessage)); + event.disconnect(ip,true,TextComponent.fromLegacyText(kickMessage)); } } } - private void cachePlayer(@NonNull PreLoginEvent event, UUID uuid) { + private void cachePlayer(@NonNull LoginEventWrapper event, UUID uuid) { if (uuid == null) { return; } @@ -245,7 +257,7 @@ private void cacheData(@NonNull String ip, @NonNull UUID uuid, @NonNull CachedCo } } - private void checkPlayer(@NonNull PostLoginEvent event) { + private void checkPlayer(@NonNull LoginEventWrapper event) { Optional luckPermsHook; try { luckPermsHook = ServiceLocator.getOptional(LuckPermsHook.class); @@ -258,7 +270,7 @@ private void checkPlayer(@NonNull PostLoginEvent event) { return; } - String ip = getIp(event.getPlayer().getAddress()); + String ip = getIp(event.getAddress()); if (ip == null || ip.isEmpty()) { return; } @@ -269,7 +281,7 @@ private void checkPlayer(@NonNull PostLoginEvent event) { return; } - if (event.getPlayer().hasPermission("avpn.bypass")) { + if (event.getPlayer() != null && event.getPlayer().hasPermission("avpn.bypass")) { if (ConfigUtil.getDebugOrFalse()) { console.sendMessage("" + event.getPlayer().getName() + " bypasses actions. Ignoring."); } @@ -279,40 +291,40 @@ private void checkPlayer(@NonNull PostLoginEvent event) { for (String testAddress : cachedConfig.getIgnoredIps()) { if (ValidationUtil.isValidIp(testAddress) && ip.equalsIgnoreCase(testAddress)) { if (ConfigUtil.getDebugOrFalse()) { - console.sendMessage("" + event.getPlayer().getName() + " is using an ignored IP " + ip + ". Ignoring."); + console.sendMessage("" + event.getName() + " is using an ignored IP " + ip + ". Ignoring."); } return; } else if (ValidationUtil.isValidIpRange(testAddress) && rangeContains(testAddress, ip)) { if (ConfigUtil.getDebugOrFalse()) { - console.sendMessage("" + event.getPlayer().getName() + " is under an ignored range " + testAddress + " (" + ip + ")" + ". Ignoring."); + console.sendMessage("" + event.getName() + " is under an ignored range " + testAddress + " (" + ip + ")" + ". Ignoring."); } return; } } - if (isVpn(ip, event.getPlayer().getName(), cachedConfig)) { + if (isVpn(ip, event.getName(), cachedConfig)) { AntiVPN.incrementBlockedVPNs(); IPManager ipManager = VPNAPIProvider.getInstance().getIPManager(); - List commands = ipManager.getVpnCommands(event.getPlayer().getName(), event.getPlayer().getUniqueId(), ip); + List commands = ipManager.getVpnCommands(event.getName(), event.getUniqueId(), ip); for (String command : commands) { ProxyServer.getInstance().getPluginManager().dispatchCommand(ProxyServer.getInstance().getConsole(), command); } - String kickMessage = ipManager.getVpnKickMessage(event.getPlayer().getName(), event.getPlayer().getUniqueId(), ip); + String kickMessage = ipManager.getVpnKickMessage(event.getName(), event.getUniqueId(), ip); if (kickMessage != null) { - event.getPlayer().disconnect(TextComponent.fromLegacyText(kickMessage)); + event.disconnect(ip,false,TextComponent.fromLegacyText(kickMessage)); } } - if (isMcLeaks(event.getPlayer().getName(), event.getPlayer().getUniqueId(), cachedConfig)) { + if (isMcLeaks(event.getName(), event.getUniqueId(), cachedConfig)) { AntiVPN.incrementBlockedMCLeaks(); PlayerManager playerManager = VPNAPIProvider.getInstance().getPlayerManager(); - List commands = playerManager.getMcLeaksCommands(event.getPlayer().getName(), event.getPlayer().getUniqueId(), ip); + List commands = playerManager.getMcLeaksCommands(event.getName(), event.getUniqueId(), ip); for (String command : commands) { ProxyServer.getInstance().getPluginManager().dispatchCommand(ProxyServer.getInstance().getConsole(), command); } - String kickMessage = playerManager.getMcLeaksKickMessage(event.getPlayer().getName(), event.getPlayer().getUniqueId(), ip); + String kickMessage = playerManager.getMcLeaksKickMessage(event.getName(), event.getUniqueId(), ip); if (kickMessage != null) { - event.getPlayer().disconnect(TextComponent.fromLegacyText(kickMessage)); + event.disconnect(ip,true,TextComponent.fromLegacyText(kickMessage)); } } } diff --git a/Bungee/src/main/java/me/egg82/antivpn/utils/LoginEventWrapper.java b/Bungee/src/main/java/me/egg82/antivpn/utils/LoginEventWrapper.java new file mode 100644 index 00000000..7ba6004c --- /dev/null +++ b/Bungee/src/main/java/me/egg82/antivpn/utils/LoginEventWrapper.java @@ -0,0 +1,115 @@ +package me.egg82.antivpn.utils; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.connection.PendingConnection; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.event.LoginEvent; +import net.md_5.bungee.api.event.PostLoginEvent; +import net.md_5.bungee.api.event.PreLoginEvent; +import net.md_5.bungee.api.plugin.Plugin; + +import javax.annotation.Nullable; +import java.net.InetSocketAddress; +import java.util.UUID; + +public class LoginEventWrapper { + private PreLoginEvent preLoginEvent = null; + private PostLoginEvent postLoginEvent = null; + private LoginEvent loginEvent = null; + private Plugin plugin; + + public LoginEventWrapper(Object event,Plugin plugin) { + if (event instanceof PreLoginEvent) { + preLoginEvent = (PreLoginEvent) event; + }else if (event instanceof PostLoginEvent) { + postLoginEvent = (PostLoginEvent) event; + } else { + loginEvent = (LoginEvent) event; + } + this.plugin = plugin; + } + + public InetSocketAddress getAddress() { + if (preLoginEvent != null) { + return preLoginEvent.getConnection().getAddress(); + } else if (postLoginEvent != null) { + return postLoginEvent.getPlayer().getAddress(); + } else { + return loginEvent.getConnection().getAddress(); + } + } + public void disconnect(String ip,boolean mcLeaks,BaseComponent... message){ + if (preLoginEvent != null) { + preLoginEvent.setCancelled(true); + preLoginEvent.setCancelReason(message); + } else if (postLoginEvent != null) { + postLoginEvent.getPlayer().disconnect(message); + } else { + loginEvent.setCancelled(true); + loginEvent.setCancelReason(message); + } + plugin.getLogger().info("Disconnecting " + getConnection().getName() + " for using a" + (mcLeaks ? "n MCLeaks account" : " VPN") + ". Address: " + ip); + } + + public UUID getUniqueId() { + if (preLoginEvent != null) { + throw new IllegalArgumentException("PreLoginEvent doesn't have method getUniqueID"); + } else if (postLoginEvent != null) { + return postLoginEvent.getPlayer().getUniqueId(); + } else { + return loginEvent.getConnection().getUniqueId(); + } + } + + public String getName() { + if (preLoginEvent != null) { + return preLoginEvent.getConnection().getName(); + } else if (postLoginEvent != null) { + return postLoginEvent.getPlayer().getName(); + } else { + return loginEvent.getConnection().getName(); + } + } + + @Nullable + public ProxiedPlayer getPlayer() { + if (preLoginEvent != null) { + return null; + } else if (postLoginEvent != null) { + return postLoginEvent.getPlayer(); + } else { + return null; + } + } + + public void setCancelReason(BaseComponent... cancelReason) { + if (preLoginEvent != null) { + preLoginEvent.setCancelReason(cancelReason); + } else if (postLoginEvent != null) { + throw new IllegalArgumentException("PostLoginEvent doesn't have method setCancelReason"); + } else { + loginEvent.setCancelReason(cancelReason); + } + } + + public PendingConnection getConnection() { + if (preLoginEvent != null) { + return preLoginEvent.getConnection(); + } else if (postLoginEvent != null) { + throw new IllegalArgumentException("PostLoginEvent doesn't have method getConnection"); + } else { + return loginEvent.getConnection(); + } + } + + public void setCancelled(boolean cancelled) { + if (preLoginEvent != null) { + preLoginEvent.setCancelled(true); + } else if (postLoginEvent != null) { + throw new IllegalArgumentException("PostLoginEvent doesn't have method setCancelReason"); + } else { + loginEvent.setCancelled(true); + } + } + +} diff --git a/Common/src/main/java/me/egg82/antivpn/api/model/source/IPInfo.java b/Common/src/main/java/me/egg82/antivpn/api/model/source/IPInfo.java index f77b63b6..ea2a05ef 100644 --- a/Common/src/main/java/me/egg82/antivpn/api/model/source/IPInfo.java +++ b/Common/src/main/java/me/egg82/antivpn/api/model/source/IPInfo.java @@ -48,7 +48,7 @@ public IPInfo() { throw new APIException(true, "Key is not defined for " + getName()); } - WebRequest.Builder builder = getDefaultBuilder("https://ipinfo.io/" + ip + "/privacy?token=" + key, getCachedConfig().getTimeout()); + WebRequest.Builder builder = getDefaultBuilder("https://ipinfo.io/" + ip + "?token=" + key, getCachedConfig().getTimeout()); HttpURLConnection conn = getConnection(builder.build()); JSONDeserializer modelDeserializer = new JSONDeserializer<>(); return modelDeserializer.deserialize(getString(conn), IPInfoModel.class); diff --git a/Common/src/main/java/me/egg82/antivpn/config/CachedConfig.java b/Common/src/main/java/me/egg82/antivpn/config/CachedConfig.java index 950ddecf..aef1f312 100644 --- a/Common/src/main/java/me/egg82/antivpn/config/CachedConfig.java +++ b/Common/src/main/java/me/egg82/antivpn/config/CachedConfig.java @@ -46,6 +46,9 @@ private CachedConfig() { } private long timeout = 5000L; public long getTimeout() { return timeout; } + private boolean loginEvent = true; + public boolean getLoginEvent() { return loginEvent; } + private String vpnKickMessage = "&cPlease disconnect from your proxy or VPN before re-joining!"; public @NonNull String getVPNKickMessage() { return vpnKickMessage; } @@ -156,6 +159,11 @@ public CachedConfig.Builder timeout(long value) { return this; } + public CachedConfig.Builder loginEvent(boolean value) { + values.loginEvent = value; + return this; + } + public CachedConfig.Builder vpnKickMessage(@NonNull String value) { values.vpnKickMessage = value; return this; diff --git a/Common/src/main/java/me/egg82/antivpn/config/ConfigurationFileUtil.java b/Common/src/main/java/me/egg82/antivpn/config/ConfigurationFileUtil.java index 071f37dc..c508629e 100644 --- a/Common/src/main/java/me/egg82/antivpn/config/ConfigurationFileUtil.java +++ b/Common/src/main/java/me/egg82/antivpn/config/ConfigurationFileUtil.java @@ -74,6 +74,7 @@ public static void reloadConfig(@NonNull File dataDirectory, @NonNull CommandIss .ignoredIps(getIgnoredIps(config, debug, console)) .threads(config.node("connection", "threads").getInt(4)) .timeout(config.node("connection", "timeout").getLong(5000L)) + .loginEvent(config.node("use-login-event").getBoolean(true)) .vpnKickMessage(config.node("action", "vpn", "kick-message").getString("&cPlease disconnect from your proxy or VPN before re-joining!")) .vpnActionCommands(getVpnActionCommands(config, debug, console)) .mcleaksKickMessage(config.node("action", "mcleaks", "kick-message").getString("&cPlease discontinue your use of an MCLeaks account!")) diff --git a/Common/src/main/resources/config.yml b/Common/src/main/resources/config.yml index 36c4523a..f73767cd 100644 --- a/Common/src/main/resources/config.yml +++ b/Common/src/main/resources/config.yml @@ -340,6 +340,8 @@ connection: # When true, logs some extra output to the console so you can see if/why things might be failing debug: false +# When true, uses login event instead of Pre/PostLoginEvent (requires restart) +use-login-event: true # Default language (affects console output) lang: 'en'