forked from TuxCoding/FastLogin
Support for making requests to Mojang from different IPv4 addresses
(Related #27)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user