[FEATURE] AuthLimiter теперь компонент

This commit is contained in:
Gravit 2019-03-13 16:49:28 +07:00
parent 3eabd1e38e
commit 694c994807
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
7 changed files with 59 additions and 55 deletions

View file

@ -8,7 +8,7 @@
import ru.gravit.launcher.managers.GarbageManager; import ru.gravit.launcher.managers.GarbageManager;
import ru.gravit.launcher.profiles.ClientProfile; import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
import ru.gravit.launchserver.auth.AuthLimiter; import ru.gravit.launchserver.components.AuthLimiterComponent;
import ru.gravit.launchserver.auth.handler.AuthHandler; import ru.gravit.launchserver.auth.handler.AuthHandler;
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler; import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler; import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler;
@ -33,7 +33,6 @@
import ru.gravit.launchserver.texture.RequestTextureProvider; import ru.gravit.launchserver.texture.RequestTextureProvider;
import ru.gravit.launchserver.texture.TextureProvider; import ru.gravit.launchserver.texture.TextureProvider;
import ru.gravit.utils.helper.*; import ru.gravit.utils.helper.*;
import sun.nio.cs.ext.COMPOUND_TEXT;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -48,8 +47,6 @@
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.time.Duration;
import java.time.Instant;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -111,14 +108,6 @@ public static final class Config {
public boolean compress; public boolean compress;
public int authRateLimit;
public int authRateLimitMilis;
public String[] authLimitExclusions;
public String authRejectString;
public String whitelistRejectString; public String whitelistRejectString;
public boolean genMappings; public boolean genMappings;
@ -329,8 +318,6 @@ public static void main(String... args) throws Throwable {
public final LauncherBinary launcherEXEBinary; public final LauncherBinary launcherEXEBinary;
// HWID ban + anti-brutforce // HWID ban + anti-brutforce
public final AuthLimiter limiter;
public final SessionManager sessionManager; public final SessionManager sessionManager;
public final SocketHookManager socketHookManager; public final SocketHookManager socketHookManager;
@ -463,7 +450,6 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
// build hooks, anti-brutforce and other // build hooks, anti-brutforce and other
buildHookManager = new BuildHookManager(); buildHookManager = new BuildHookManager();
limiter = new AuthLimiter(this);
proguardConf = new ProguardConf(this); proguardConf = new ProguardConf(this);
sessionManager = new SessionManager(); sessionManager = new SessionManager();
mirrorManager = new MirrorManager(); mirrorManager = new MirrorManager();
@ -472,7 +458,6 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
socketHookManager = new SocketHookManager(); socketHookManager = new SocketHookManager();
authHookManager = new AuthHookManager(); authHookManager = new AuthHookManager();
GarbageManager.registerNeedGC(sessionManager); GarbageManager.registerNeedGC(sessionManager);
GarbageManager.registerNeedGC(limiter);
reloadManager.registerReloadable("launchServer", this); reloadManager.registerReloadable("launchServer", this);
if (config.permissionsHandler instanceof Reloadable) if (config.permissionsHandler instanceof Reloadable)
reloadManager.registerReloadable("permissionsHandler", (Reloadable) config.permissionsHandler); reloadManager.registerReloadable("permissionsHandler", (Reloadable) config.permissionsHandler);
@ -632,7 +617,6 @@ private void generateConfigIfNotExists() throws IOException {
newConfig.permissionsHandler = new JsonFilePermissionsHandler(); newConfig.permissionsHandler = new JsonFilePermissionsHandler();
newConfig.port = 7240; newConfig.port = 7240;
newConfig.bindAddress = "0.0.0.0"; newConfig.bindAddress = "0.0.0.0";
newConfig.authRejectString = "Превышен лимит авторизаций";
newConfig.binaryName = "Launcher"; newConfig.binaryName = "Launcher";
newConfig.whitelistRejectString = "Вас нет в белом списке"; newConfig.whitelistRejectString = "Вас нет в белом списке";
@ -649,6 +633,13 @@ private void generateConfigIfNotExists() throws IOException {
newConfig.deleteTempFiles = true; newConfig.deleteTempFiles = true;
newConfig.isWarningMissArchJava = true; newConfig.isWarningMissArchJava = true;
newConfig.components = new HashMap<>();
AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent();
authLimiterComponent.rateLimit = 3;
authLimiterComponent.rateLimitMilis = 8000;
authLimiterComponent.message = "Превышен лимит авторизаций";
newConfig.components.put("authLimiter", authLimiterComponent);
// Set server address // Set server address
System.out.println("LaunchServer address: "); System.out.println("LaunchServer address: ");
newConfig.setAddress(commandHandler.readLine()); newConfig.setAddress(commandHandler.readLine());

View file

@ -1,14 +1,42 @@
package ru.gravit.launchserver.auth; package ru.gravit.launchserver.components;
import ru.gravit.launcher.NeedGarbageCollection; import ru.gravit.launcher.NeedGarbageCollection;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.provider.AuthProvider;
import ru.gravit.launchserver.components.Component;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.Client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
public class AuthLimiter implements NeedGarbageCollection { public class AuthLimiterComponent extends Component implements NeedGarbageCollection {
private LaunchServer server;
@Override
public void preInit(LaunchServer launchServer) {
}
@Override
public void init(LaunchServer launchServer) {
server = launchServer;
launchServer.authHookManager.registerPreHook(this::preAuthHook);
}
@Override
public void postInit(LaunchServer launchServer) {
}
public void preAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException {
if(isLimit(context.ip))
{
AuthProvider.authError(message);
}
}
static class AuthEntry { static class AuthEntry {
public int value; public int value;
@ -50,20 +78,12 @@ public String toString() {
public static final long TIMEOUT = 10 * 60 * 1000; //10 минут public static final long TIMEOUT = 10 * 60 * 1000; //10 минут
public final int rateLimit; public int rateLimit;
public final int rateLimitMilis; public int rateLimitMilis;
public String message;
private final HashMap<String, AuthEntry> map; public transient HashMap<String, AuthEntry> map;
private final List<String> excludeIps; public List<String> excludeIps;
public AuthLimiter(LaunchServer srv) {
map = new HashMap<>();
excludeIps = new ArrayList<>();
if (srv.config.authLimitExclusions != null)
excludeIps.addAll(Arrays.asList(srv.config.authLimitExclusions));
rateLimit = srv.config.authRateLimit;
rateLimitMilis = srv.config.authRateLimitMilis;
}
@Override @Override
public void garbageCollection() { public void garbageCollection() {

View file

@ -30,6 +30,7 @@ public static String getComponentName(Class<Component> clazz) {
public static void registerComponents() { public static void registerComponents() {
if (!registredComp) { if (!registredComp) {
registerComponent("authLimiter", AuthLimiterComponent.class);
registredComp = true; registredComp = true;
} }
} }

View file

@ -1,5 +1,7 @@
package ru.gravit.launchserver.manangers.hook; package ru.gravit.launchserver.manangers.hook;
import ru.gravit.launcher.request.RequestException;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.auth.AuthResponse; import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
@ -14,22 +16,22 @@ public class AuthHookManager {
@FunctionalInterface @FunctionalInterface
public interface AuthPreHook { public interface AuthPreHook {
void preAuthHook(AuthResponse.AuthContext context, Client client); void preAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException;
} }
@FunctionalInterface @FunctionalInterface
public interface AuthPostHook { public interface AuthPostHook {
void postAuthHook(AuthResponse.AuthContext context, Client client); void postAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException;
} }
@FunctionalInterface @FunctionalInterface
public interface CheckServerHook { public interface CheckServerHook {
void checkServerHook(String username, String serverID); void checkServerHook(String username, String serverID) throws AuthException;
} }
@FunctionalInterface @FunctionalInterface
public interface JoinServerHook { public interface JoinServerHook {
void joinServerHook(String username, String accessToken, String serverID); void joinServerHook(String username, String accessToken, String serverID) throws AuthException;
} }
public void registerPostHook(AuthPostHook hook) { public void registerPostHook(AuthPostHook hook) {
@ -48,25 +50,25 @@ public void registerPreHook(AuthPreHook hook) {
PRE_HOOKS.add(hook); PRE_HOOKS.add(hook);
} }
public void preHook(AuthResponse.AuthContext context, Client client) { public void preHook(AuthResponse.AuthContext context, Client client) throws AuthException {
for (AuthPreHook preHook : PRE_HOOKS) { for (AuthPreHook preHook : PRE_HOOKS) {
preHook.preAuthHook(context, client); preHook.preAuthHook(context, client);
} }
} }
public void checkServerHook(String username, String serverID) { public void checkServerHook(String username, String serverID) throws AuthException {
for (CheckServerHook hook : CHECKSERVER_HOOKS) { for (CheckServerHook hook : CHECKSERVER_HOOKS) {
hook.checkServerHook(username, serverID); hook.checkServerHook(username, serverID);
} }
} }
public void joinServerHook(String username, String accessToken, String serverID) { public void joinServerHook(String username, String accessToken, String serverID) throws AuthException {
for (JoinServerHook hook : JOINSERVER_HOOKS) { for (JoinServerHook hook : JOINSERVER_HOOKS) {
hook.joinServerHook(username, accessToken, serverID); hook.joinServerHook(username, accessToken, serverID);
} }
} }
public void postHook(AuthResponse.AuthContext context, Client client) { public void postHook(AuthResponse.AuthContext context, Client client) throws AuthException {
for (AuthPostHook postHook : POST_HOOKS) { for (AuthPostHook postHook : POST_HOOKS) {
postHook.postAuthHook(context, client); postHook.postAuthHook(context, client);
} }

View file

@ -36,13 +36,14 @@ public AuthResponse(LaunchServer server, long session, HInput input, HOutput out
} }
public static class AuthContext { public static class AuthContext {
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, boolean isServerAuth) { public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
this.session = session; this.session = session;
this.login = login; this.login = login;
this.password_lenght = password_lenght; this.password_lenght = password_lenght;
this.customText = customText; this.customText = customText;
this.client = client; this.client = client;
this.hwid = hwid; this.hwid = hwid;
this.ip = ip;
this.isServerAuth = isServerAuth; this.isServerAuth = isServerAuth;
} }
@ -52,6 +53,7 @@ public AuthContext(long session, String login, int password_lenght, String custo
public String client; public String client;
public String hwid; public String hwid;
public String customText; public String customText;
public String ip;
public boolean isServerAuth; public boolean isServerAuth;
} }
@ -82,13 +84,9 @@ public void reply() throws Exception {
AuthProviderResult result; AuthProviderResult result;
AuthProvider provider = server.config.authProvider[auth_id]; AuthProvider provider = server.config.authProvider[auth_id];
clientData.type = Client.Type.USER; clientData.type = Client.Type.USER;
AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, false); AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, ip, false);
try { try {
server.authHookManager.preHook(context, clientData); server.authHookManager.preHook(context, clientData);
if (server.limiter.isLimit(ip)) {
AuthProvider.authError(server.config.authRejectString);
return;
}
if (!clientData.checkSign) { if (!clientData.checkSign) {
throw new AuthException("You must using checkLauncher"); throw new AuthException("You must using checkLauncher");
} }

View file

@ -53,10 +53,6 @@ public void reply() throws Exception {
AuthProviderResult result; AuthProviderResult result;
AuthProvider provider = server.config.authProvider[auth_id]; AuthProvider provider = server.config.authProvider[auth_id];
try { try {
if (server.limiter.isLimit(ip)) {
AuthProvider.authError(server.config.authRejectString);
return;
}
result = provider.auth(login, password, ip); result = provider.auth(login, password, ip);
if (!VerifyHelper.isValidUsername(result.username)) { if (!VerifyHelper.isValidUsername(result.username)) {
AuthProvider.authError(String.format("Illegal result: '%s'", result.username)); AuthProvider.authError(String.format("Illegal result: '%s'", result.username));

View file

@ -56,10 +56,6 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
try { try {
AuthRequestEvent result = new AuthRequestEvent(); AuthRequestEvent result = new AuthRequestEvent();
String ip = IOHelper.getIP(ctx.channel().remoteAddress()); String ip = IOHelper.getIP(ctx.channel().remoteAddress());
if (LaunchServer.server.limiter.isLimit(ip)) {
AuthProvider.authError(LaunchServer.server.config.authRejectString);
return;
}
if ((authType == null || authType == ConnectTypes.CLIENT) &&!clientData.checkSign) { if ((authType == null || authType == ConnectTypes.CLIENT) &&!clientData.checkSign) {
AuthProvider.authError("Don't skip Launcher Update"); AuthProvider.authError("Don't skip Launcher Update");
return; return;
@ -82,7 +78,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
{ {
AuthProvider.authError("authType: SERVER not allowed for this account"); AuthProvider.authError("authType: SERVER not allowed for this account");
} }
ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(),customText, client, null, false); ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(),customText, client, ip, null, false);
AuthProvider provider = LaunchServer.server.config.authProvider[authid]; AuthProvider provider = LaunchServer.server.config.authProvider[authid];
LaunchServer.server.authHookManager.preHook(context, clientData); LaunchServer.server.authHookManager.preHook(context, clientData);
provider.preAuth(login,password,customText,ip); provider.preAuth(login,password,customText,ip);