Support for making requests to Mojang from different IPv4 addresses

(Related #27)
This commit is contained in:
games647
2016-06-20 13:52:37 +02:00
parent 0d89614f3c
commit 6faf00e1bf
13 changed files with 166 additions and 26 deletions

View File

@@ -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

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.6.1</version>
<version>1.7</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -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);

View File

@@ -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<String> localAddresses) {
super(plugin, localAddresses);
}
@Override

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.6.1</version>
<version>1.7</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -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<UUID> 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<PendingConnection, BungeeLoginSession> getSession() {

View File

@@ -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<String> localAddresses) {
super(plugin, localAddresses);
}
@Override

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.6.1</version>
<version>1.7</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -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<InetAddress> localAddresses;
private final Object lock = new Object();
private int id;
public BalancedSSLFactory(SSLSocketFactory oldFactory, Set<InetAddress> 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);
}
}

View File

@@ -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<String> localAddresses) {
this.plugin = plugin;
if (localAddresses.isEmpty()) {
this.sslFactory = null;
} else {
Set<InetAddress> 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;
}
}

View File

@@ -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)

View File

@@ -8,7 +8,7 @@
<packaging>pom</packaging>
<name>FastLogin</name>
<version>1.6.1</version>
<version>1.7</version>
<inceptionYear>2015</inceptionYear>
<url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
<description>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.6.1</version>
<version>1.7</version>
<relativePath>../pom.xml</relativePath>
</parent>