diff --git a/src/main/java/com/lenis0012/bukkit/loginsecurity/LoginSecurityConfig.java b/src/main/java/com/lenis0012/bukkit/loginsecurity/LoginSecurityConfig.java index dbc1c276..328d6879 100644 --- a/src/main/java/com/lenis0012/bukkit/loginsecurity/LoginSecurityConfig.java +++ b/src/main/java/com/lenis0012/bukkit/loginsecurity/LoginSecurityConfig.java @@ -62,6 +62,19 @@ public class LoginSecurityConfig extends AbstractConfig { @ConfigKey(path = "join.hide-inventory-safe") private boolean hideInventory = false; + /** + * Ban settings. + */ + @ConfigHeader("When enabled, automatically bans IPs trying to join as already logged in users") + @ConfigKey(path = "join.ban.simultaneous-login") + private boolean banSimultaneous = false; + @ConfigHeader("Notifies OPs in chat about LoginSecurity autobans") + @ConfigKey(path = "join.ban.notify-ops") + private boolean banNotifyOps = true; + @ConfigHeader("When enabled, automatically bans IPs which exceed 4 login tries") + @ConfigKey(path = "join.ban.bruteforce-attempt") + private boolean banBruteforceAttempt = false; + /** * Username settings. */ diff --git a/src/main/java/com/lenis0012/bukkit/loginsecurity/commands/CommandLogin.java b/src/main/java/com/lenis0012/bukkit/loginsecurity/commands/CommandLogin.java index 4b16cc94..c84533b1 100644 --- a/src/main/java/com/lenis0012/bukkit/loginsecurity/commands/CommandLogin.java +++ b/src/main/java/com/lenis0012/bukkit/loginsecurity/commands/CommandLogin.java @@ -12,8 +12,10 @@ import com.lenis0012.bukkit.loginsecurity.session.action.LoginAction; import com.lenis0012.bukkit.loginsecurity.storage.PlayerProfile; import com.lenis0012.bukkit.loginsecurity.util.MetaData; +import com.lenis0012.bukkit.loginsecurity.util.OpNotifier; import com.lenis0012.pluginutils.command.Command; import org.bukkit.Bukkit; +import org.bukkit.BanList; import org.bukkit.entity.Player; import java.util.logging.Level; @@ -35,7 +37,18 @@ public void execute() { LoginSecurityConfig config = LoginSecurity.getConfiguration(); int tries = MetaData.incrementAndGet(player, "ls_login_tries"); if(tries > config.getMaxLoginTries()) { - player.kickPlayer("[LoginSecurity] " + translate(LOGIN_TRIES_EXCEEDED).param("max", config.getMaxLoginTries()).toString()); + if(config.isBanBruteforceAttempt()) { + if(config.isBanNotifyOps()) { + OpNotifier.notify("[LoginSecurity] " + player.getAddress().getHostString() + + " " + translate(BAN_BRUTEFORCE_ATTEMPT) + player.getName()); + } + Bukkit.getBanList(BanList.Type.IP).addBan(player.getAddress().getHostString(), + translate(BAN_BRUTEFORCE_ATTEMPT).toString() + player.getName(), + null, "LoginSecurity"); + player.kickPlayer("[LoginSecurity] " + translate(BAN_BRUTEFORCE_ATTEMPT) + player.getName()); + } else { + player.kickPlayer("[LoginSecurity] " + translate(LOGIN_TRIES_EXCEEDED).param("max", config.getMaxLoginTries()).toString()); + } return; } diff --git a/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/general/PlayerListener.java b/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/general/PlayerListener.java index 27c4ba22..261542f1 100644 --- a/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/general/PlayerListener.java +++ b/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/general/PlayerListener.java @@ -12,9 +12,11 @@ import com.lenis0012.bukkit.loginsecurity.storage.PlayerProfile; import com.lenis0012.bukkit.loginsecurity.util.MetaData; import com.lenis0012.bukkit.loginsecurity.util.UserIdMode; +import com.lenis0012.bukkit.loginsecurity.util.OpNotifier; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.BanList; import org.bukkit.entity.EntityType; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; @@ -66,13 +68,29 @@ public PlayerListener(GeneralModule general) { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) { + final LoginSecurityConfig config = LoginSecurity.getConfiguration(); // Check if player already online for(Player player : Bukkit.getOnlinePlayers()) { if(player.getName().equalsIgnoreCase(event.getName())) { PlayerSession session = LoginSecurity.getSessionManager().getPlayerSession(player); if(session.isAuthorized()) { - event.setLoginResult(Result.KICK_OTHER); - event.setKickMessage("[LoginSecurity] " + translate(KICK_ALREADY_ONLINE)); + if(config.isBanSimultaneous()) { + BanList banlist = Bukkit.getBanList(BanList.Type.IP); + if(!banlist.isBanned(event.getAddress().getHostAddress())) { + banlist.addBan(event.getAddress().getHostAddress(), + translate(BAN_ALREADY_ONLINE).toString() + player.getName(), + null, "LoginSecurity"); + if(config.isBanNotifyOps()) { + OpNotifier.notify("[LoginSecurity] " + event.getAddress().getHostAddress() + + " " + translate(BAN_ALREADY_ONLINE) + player.getName()); + } + } + event.setLoginResult(Result.KICK_BANNED); + event.setKickMessage("[LoginSecurity] " + translate(BAN_ALREADY_ONLINE) + player.getName()); + } else { + event.setLoginResult(Result.KICK_OTHER); + event.setKickMessage("[LoginSecurity] " + translate(KICK_ALREADY_ONLINE)); + } return; } } @@ -80,7 +98,6 @@ public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) { // Verify name final String name = event.getName(); - final LoginSecurityConfig config = LoginSecurity.getConfiguration(); if(config.isFilterSpecialChars() && !name.replaceAll("[^a-zA-Z0-9_]", "").equals(name)) { event.setLoginResult(Result.KICK_OTHER); event.setKickMessage("[LoginSecurity] " + translate(KICK_USERNAME_CHARS)); diff --git a/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/language/LanguageKeys.java b/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/language/LanguageKeys.java index ea7ebffb..9d3b7083 100644 --- a/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/language/LanguageKeys.java +++ b/src/main/java/com/lenis0012/bukkit/loginsecurity/modules/language/LanguageKeys.java @@ -72,7 +72,12 @@ public enum LanguageKeys { KICK_USERNAME_CHARS("kickUsernameChars"), KICK_USERNAME_LENGTH("kickUsernameLength"), KICK_TIME_OUT("kickTimeOut"), - KICK_USERNAME_REGISTERED("kickUsernameRegistered"); + KICK_USERNAME_REGISTERED("kickUsernameRegistered"), + /** + * Ban messages + */ + BAN_ALREADY_ONLINE("banAlreadyOnline"), + BAN_BRUTEFORCE_ATTEMPT("banBruteforceAttempt"); private final String value; diff --git a/src/main/java/com/lenis0012/bukkit/loginsecurity/util/OpNotifier.java b/src/main/java/com/lenis0012/bukkit/loginsecurity/util/OpNotifier.java new file mode 100644 index 00000000..2c22c584 --- /dev/null +++ b/src/main/java/com/lenis0012/bukkit/loginsecurity/util/OpNotifier.java @@ -0,0 +1,17 @@ +package com.lenis0012.bukkit.loginsecurity.util; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class OpNotifier { + /** + * Send out a message to all server OPs + */ + public static void notify(String message) { + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.isOp()) { + p.sendMessage(message); + } + } + } +}