diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a39781..4381fe7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +######1.7 + +* Added support for making requests to Mojang from different IPv4 addresses + +######1.6.2 + +* Fixed support for new LoginSecurity version + ######1.6.1 * Fix message typo in BungeeCord which created a NPE if premium-warning is activated diff --git a/bukkit/pom.xml b/bukkit/pom.xml index ea988e89..b36ebd4a 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -5,7 +5,7 @@ com.github.games647 fastlogin - 1.6.1 + 1.7 ../pom.xml 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 8ee57796..f76503b1 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 @@ -64,11 +64,11 @@ public class FastLoginBukkit extends JavaPlugin { @Override public void onEnable() { - core.setMojangApiConnector(new MojangApiBukkit(core)); - core.loadConfig(); core.loadMessages(); + core.setMojangApiConnector(new MojangApiBukkit(core, getConfig().getStringList("ip-addresses"))); + try { if (ClassUtil.isPresent("org.spigotmc.SpigotConfig")) { bungeeCord = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null); diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java index 8bd54754..7cd81e51 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java @@ -6,6 +6,7 @@ import com.github.games647.fastlogin.core.MojangApiConnector; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.util.List; import java.util.UUID; import java.util.logging.Level; @@ -18,8 +19,8 @@ public class MojangApiBukkit extends MojangApiConnector { //mojang api check to prove a player is logged in minecraft and made a join server request private static final String HAS_JOINED_URL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?"; - public MojangApiBukkit(FastLoginCore plugin) { - super(plugin); + public MojangApiBukkit(FastLoginCore plugin, List localAddresses) { + super(plugin, localAddresses); } @Override diff --git a/bungee/pom.xml b/bungee/pom.xml index 46cb30c9..64437079 100644 --- a/bungee/pom.xml +++ b/bungee/pom.xml @@ -5,7 +5,7 @@ com.github.games647 fastlogin - 1.6.1 + 1.7 ../pom.xml diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java index d845d78d..1f825639 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java @@ -32,7 +32,7 @@ public class FastLoginBungee extends Plugin { private final FastLoginCore loginCore = new BungeeCore(this); private BungeeAuthPlugin bungeeAuthPlugin; - private Configuration configuration; + private Configuration config; private final Random random = new Random(); private final Set pendingConfirms = Sets.newHashSet(); @@ -41,22 +41,22 @@ public class FastLoginBungee extends Plugin { @Override public void onEnable() { - loginCore.setMojangApiConnector(new MojangApiBungee(loginCore)); - loginCore.loadConfig(); loginCore.loadMessages(); try { File configFile = new File(getDataFolder(), "config.yml"); - configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); + config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); - String driver = configuration.getString("driver"); - String host = configuration.getString("host", ""); - int port = configuration.getInt("port", 3306); - String database = configuration.getString("database"); + loginCore.setMojangApiConnector(new MojangApiBungee(loginCore, config.getStringList("ip-addresses"))); - String username = configuration.getString("username", ""); - String password = configuration.getString("password", ""); + String driver = config.getString("driver"); + String host = config.getString("host", ""); + int port = config.getInt("port", 3306); + String database = config.getString("database"); + + String username = config.getString("username", ""); + String password = config.getString("password", ""); if (!loginCore.setupDatabase(driver, host, port, database, username, password)) { return; } @@ -98,7 +98,7 @@ public class FastLoginBungee extends Plugin { } public Configuration getConfig() { - return configuration; + return config; } public ConcurrentMap getSession() { diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/MojangApiBungee.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/MojangApiBungee.java index 39bdeb9c..7f5db268 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/MojangApiBungee.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/MojangApiBungee.java @@ -3,14 +3,15 @@ package com.github.games647.fastlogin.bungee; import com.github.games647.fastlogin.core.FastLoginCore; import com.github.games647.fastlogin.core.MojangApiConnector; +import java.util.List; import java.util.UUID; import net.md_5.bungee.BungeeCord; public class MojangApiBungee extends MojangApiConnector { - public MojangApiBungee(FastLoginCore plugin) { - super(plugin); + public MojangApiBungee(FastLoginCore plugin, List localAddresses) { + super(plugin, localAddresses); } @Override diff --git a/core/pom.xml b/core/pom.xml index e4621c1b..a790dea3 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ com.github.games647 fastlogin - 1.6.1 + 1.7 ../pom.xml diff --git a/core/src/main/java/com/github/games647/fastlogin/core/BalancedSSLFactory.java b/core/src/main/java/com/github/games647/fastlogin/core/BalancedSSLFactory.java new file mode 100644 index 00000000..61e55a0f --- /dev/null +++ b/core/src/main/java/com/github/games647/fastlogin/core/BalancedSSLFactory.java @@ -0,0 +1,80 @@ +package com.github.games647.fastlogin.core; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.net.ssl.SSLSocketFactory; + +public class BalancedSSLFactory extends SSLSocketFactory { + + private final SSLSocketFactory oldFactory; + + //in order to be thread-safe + private final List localAddresses; + + private final Object lock = new Object(); + + private int id; + + public BalancedSSLFactory(SSLSocketFactory oldFactory, Set localAddresses) { + this.oldFactory = oldFactory; + this.localAddresses = new ArrayList<>(localAddresses); + } + + @Override + public String[] getDefaultCipherSuites() { + return oldFactory.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return oldFactory.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoclose) throws IOException { + return oldFactory.createSocket(host, port, getNextLocalAddress(), 0); + } + + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + return oldFactory.createSocket(host, port, getNextLocalAddress(), 0); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) + throws IOException, UnknownHostException { + //default + return oldFactory.createSocket(host, port, localAddress, localPort); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return oldFactory.createSocket(host, port, getNextLocalAddress(), 0); + } + + @Override + public Socket createSocket(InetAddress host, int port, InetAddress local, int localPort) throws IOException { + //Default + return oldFactory.createSocket(host, port, local, localPort); + } + + private InetAddress getNextLocalAddress() { + int next; + synchronized (lock) { + next = id; + id++; + if (next == Integer.MAX_VALUE) { + id = 0; + } + } + + int index = next % localAddresses.size(); + return localAddresses.get(index); + } +} diff --git a/core/src/main/java/com/github/games647/fastlogin/core/MojangApiConnector.java b/core/src/main/java/com/github/games647/fastlogin/core/MojangApiConnector.java index 7f84a9fc..8120ba2c 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/MojangApiConnector.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/MojangApiConnector.java @@ -4,11 +4,18 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.net.InetAddress; import java.net.URL; +import java.net.UnknownHostException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; import java.util.regex.Pattern; +import javax.net.ssl.HttpsURLConnection; + public abstract class MojangApiConnector { //http connection, read timeout and user agent for a connection to mojang api servers @@ -23,10 +30,33 @@ public abstract class MojangApiConnector { //compile the pattern only on plugin enable -> and this have to be threadsafe private final Pattern playernameMatcher = Pattern.compile(VALID_PLAYERNAME); + private final BalancedSSLFactory sslFactory; + protected final FastLoginCore plugin; - public MojangApiConnector(FastLoginCore plugin) { + public MojangApiConnector(FastLoginCore plugin, List localAddresses) { this.plugin = plugin; + + if (localAddresses.isEmpty()) { + this.sslFactory = null; + } else { + Set addresses = new HashSet<>(); + for (String localAddress : localAddresses) { + try { + InetAddress address = InetAddress.getByName(localAddress); + if (!address.isAnyLocalAddress()) { + plugin.getLogger().log(Level.WARNING, "Submitted IP-Address is not local", address); + continue; + } + + addresses.add(address); + } catch (UnknownHostException ex) { + plugin.getLogger().log(Level.SEVERE, "IP-Address is unknown to us", ex); + } + } + + this.sslFactory = new BalancedSSLFactory(HttpsURLConnection.getDefaultSSLSocketFactory(), addresses); + } } /** @@ -39,7 +69,7 @@ public abstract class MojangApiConnector { if (playernameMatcher.matcher(playerName).matches()) { //only make a API call if the name is valid existing mojang account try { - HttpURLConnection connection = getConnection(UUID_LINK + playerName); + HttpsURLConnection connection = getConnection(UUID_LINK + playerName); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line = reader.readLine(); @@ -61,14 +91,18 @@ public abstract class MojangApiConnector { protected abstract UUID getUUIDFromJson(String json); - protected HttpURLConnection getConnection(String url) throws IOException { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + protected HttpsURLConnection getConnection(String url) throws IOException { + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); connection.setConnectTimeout(TIMEOUT); connection.setReadTimeout(2 * TIMEOUT); //the new Mojang API just uses json as response connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("User-Agent", USER_AGENT); + if (sslFactory != null) { + connection.setSSLSocketFactory(sslFactory); + } + return connection; } } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index d5a0b819..354dfe7b 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -106,6 +106,22 @@ forwardSkin: true # If they still want to invoke the command, they have to invoke /premium again premium-warning: true +# If you have autoRegister or nameChangeCheck enabled, you could be rate-limited by Mojang. +# The requests of the both options will be only made by FastLogin if the username is unknown to the server +# You are allowed to make 600 requests per 10-minutes (60 per minute) +# If you own a big server this value could be too low +# Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired. +# (to the next ten minutes) +# +# The limit is IP-wide. If you have multiple IPv4-Addreses you specify them here. FastLogin will then use it in rotating +# order --> 5 different IP-addreses 5 * 600 per 10 minutes +# If this list is empty only the default one will be used +# +# Lists are created like this: +#ip-addresses: +# - 192-168-0-2 +ip-addresses: [] + # Database configuration # Recommened is the use of MariaDB (a better version of MySQL) diff --git a/pom.xml b/pom.xml index 12bdba06..b7421785 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ pom FastLogin - 1.6.1 + 1.7 2015 https://www.spigotmc.org/resources/fastlogin.14153/ diff --git a/universal/pom.xml b/universal/pom.xml index 131a8d25..44f982c1 100644 --- a/universal/pom.xml +++ b/universal/pom.xml @@ -5,7 +5,7 @@ com.github.games647 fastlogin - 1.6.1 + 1.7 ../pom.xml