[FEATURE][EXPERIMENTAL] LaunchServer в качестве прокси

This commit is contained in:
Gravit 2019-05-03 23:07:37 +07:00
parent dd596805e1
commit f1cd39babd
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
10 changed files with 145 additions and 2 deletions

View file

@ -283,12 +283,22 @@ public class NettyConfig {
public NettyPerformanceConfig performance; public NettyPerformanceConfig performance;
public NettyBindAddress[] binds; public NettyBindAddress[] binds;
public LogLevel logLevel = LogLevel.DEBUG; public LogLevel logLevel = LogLevel.DEBUG;
public NettyProxyConfig proxy = new NettyProxyConfig();
} }
public class NettyPerformanceConfig public class NettyPerformanceConfig
{ {
public int bossThread; public int bossThread;
public int workerThread; public int workerThread;
} }
public class NettyProxyConfig
{
public boolean enabled;
public String address = "ws://localhost:9275/api";
public String login = "login";
public String password = "password";
public String auth_id = "std";
public ArrayList<String> requests = new ArrayList<>();
}
public class NettyBindAddress public class NettyBindAddress
{ {
public String address; public String address;

View file

@ -8,6 +8,7 @@
public class Client { public class Client {
public long session; public long session;
public boolean proxy;
public String auth_id; public String auth_id;
public long timestamp; public long timestamp;
public Type type; public Type type;

View file

@ -13,8 +13,12 @@
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.logging.LoggingHandler; import io.netty.handler.logging.LoggingHandler;
import ru.gravit.launcher.request.Request;
import ru.gravit.launcher.request.auth.AuthRequest;
import ru.gravit.launcher.request.websockets.StandartClientWebSocketService;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.websocket.fileserver.FileServerHandler; import ru.gravit.launchserver.websocket.fileserver.FileServerHandler;
import ru.gravit.utils.helper.LogHelper;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -45,6 +49,18 @@ public void initChannel(NioSocketChannel ch) {
pipeline.addLast(new WebSocketFrameHandler()); pipeline.addLast(new WebSocketFrameHandler());
} }
}); });
if(config.proxy.enabled)
{
LogHelper.info("Connect to main server %s");
Request.service = StandartClientWebSocketService.initWebSockets(config.proxy.address, false);
AuthRequest authRequest = new AuthRequest(config.proxy.login, config.proxy.password, config.proxy.auth_id, AuthRequest.ConnectTypes.PROXY);
authRequest.initProxy = true;
try {
authRequest.request();
} catch (Exception e) {
LogHelper.error(e);
}
}
} }
public ChannelFuture bind(InetSocketAddress address) public ChannelFuture bind(InetSocketAddress address)
{ {

View file

@ -13,7 +13,9 @@
import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedEntryAdapter; import ru.gravit.launcher.hasher.HashedEntryAdapter;
import ru.gravit.launcher.request.JsonResultSerializeAdapter; import ru.gravit.launcher.request.JsonResultSerializeAdapter;
import ru.gravit.launcher.request.RequestException;
import ru.gravit.launcher.request.ResultInterface; import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.launcher.request.admin.ProxyRequest;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.websocket.json.JsonResponseAdapter; import ru.gravit.launchserver.websocket.json.JsonResponseAdapter;
@ -21,6 +23,7 @@
import ru.gravit.launchserver.websocket.json.SimpleResponse; import ru.gravit.launchserver.websocket.json.SimpleResponse;
import ru.gravit.launchserver.websocket.json.admin.AddLogListenerResponse; import ru.gravit.launchserver.websocket.json.admin.AddLogListenerResponse;
import ru.gravit.launchserver.websocket.json.admin.ExecCommandResponse; import ru.gravit.launchserver.websocket.json.admin.ExecCommandResponse;
import ru.gravit.launchserver.websocket.json.admin.ProxyCommandResponse;
import ru.gravit.launchserver.websocket.json.auth.*; import ru.gravit.launchserver.websocket.json.auth.*;
import ru.gravit.launchserver.websocket.json.profile.BatchProfileByUsername; import ru.gravit.launchserver.websocket.json.profile.BatchProfileByUsername;
import ru.gravit.launchserver.websocket.json.profile.ProfileByUUIDResponse; import ru.gravit.launchserver.websocket.json.profile.ProfileByUUIDResponse;
@ -57,6 +60,48 @@ public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) { void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) {
String request = frame.text(); String request = frame.text();
JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class); JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class);
if(server.config.netty.proxy.enabled)
{
if(server.config.netty.proxy.requests.contains(response.getType()))
{
if(response instanceof SimpleResponse)
{
SimpleResponse simpleResponse = (SimpleResponse) response;
simpleResponse.server = server;
simpleResponse.service = this;
simpleResponse.ctx = ctx;
}
LogHelper.debug("Proxy %s request", response.getType());
ProxyRequest proxyRequest = new ProxyRequest(response, 0);
try {
ResultInterface result = proxyRequest.request();
sendObject(ctx, result);
} catch (RequestException e)
{
sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
} catch (Exception e) {
LogHelper.error(e);
RequestEvent event;
if(server.config.netty.sendExceptionEnabled)
{
event = new ExceptionEvent(e);
}
else
{
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
}
if(response instanceof SimpleResponse)
{
event.requestUUID = ((SimpleResponse) response).requestUUID;
}
sendObject(ctx, event);
}
}
}
process(ctx,response, client);
}
void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client)
{
if(response instanceof SimpleResponse) if(response instanceof SimpleResponse)
{ {
SimpleResponse simpleResponse = (SimpleResponse) response; SimpleResponse simpleResponse = (SimpleResponse) response;
@ -115,6 +160,7 @@ public void registerResponses() {
registerResponse("getSecureToken", GetSecureTokenResponse.class); registerResponse("getSecureToken", GetSecureTokenResponse.class);
registerResponse("verifySecureToken", VerifySecureTokenResponse.class); registerResponse("verifySecureToken", VerifySecureTokenResponse.class);
registerResponse("getAvailabilityAuth", GetAvailabilityAuthResponse.class); registerResponse("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
registerResponse("proxy", ProxyCommandResponse.class);
} }
public void sendObject(ChannelHandlerContext ctx, Object obj) { public void sendObject(ChannelHandlerContext ctx, Object obj) {

View file

@ -1,9 +1,10 @@
package ru.gravit.launchserver.websocket.json; package ru.gravit.launchserver.websocket.json;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.request.websockets.RequestInterface;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
public interface JsonResponseInterface { public interface JsonResponseInterface extends RequestInterface {
String getType(); String getType();
void execute(ChannelHandlerContext ctx, Client client) throws Exception; void execute(ChannelHandlerContext ctx, Client client) throws Exception;

View file

@ -0,0 +1,25 @@
package ru.gravit.launchserver.websocket.json.admin;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.websocket.json.JsonResponseInterface;
import ru.gravit.launchserver.websocket.json.SimpleResponse;
public class ProxyCommandResponse extends SimpleResponse {
public JsonResponseInterface response;
public long session;
@Override
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
if(!client.proxy) {
sendError("Proxy server error");
return;
}
Client real_client = server.sessionManager.getOrNewClient(session);
response.execute(ctx, real_client);
}
@Override
public String getType() {
return "proxy";
}
}

View file

@ -45,6 +45,7 @@ public AuthResponse(String login, String password, String auth_id, OshiHWID hwid
} }
public String auth_id; public String auth_id;
public boolean initProxy;
public ConnectTypes authType; public ConnectTypes authType;
public OshiHWID hwid; public OshiHWID hwid;
@ -120,6 +121,11 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
LaunchServer.server.sessionManager.addClient(clientData); LaunchServer.server.sessionManager.addClient(clientData);
result.session = clientData.session; result.session = clientData.session;
} }
if(initProxy)
{
if(!clientData.permissions.canProxy) throw new AuthException("initProxy not allow");
clientData.proxy = true;
}
if(LaunchServer.server.config.protectHandler.allowGetAccessToken(context)) if(LaunchServer.server.config.protectHandler.allowGetAccessToken(context))
{ {
UUID uuid = pair.handler.auth(aresult); UUID uuid = pair.handler.auth(aresult);

View file

@ -20,6 +20,8 @@ public class ClientPermissions {
public boolean canUSR3; public boolean canUSR3;
@LauncherAPI @LauncherAPI
public boolean canBot; public boolean canBot;
@LauncherAPI
public boolean canProxy;
public ClientPermissions(HInput input) throws IOException { public ClientPermissions(HInput input) throws IOException {
this(input.readLong()); this(input.readLong());

View file

@ -0,0 +1,20 @@
package ru.gravit.launcher.request.admin;
import ru.gravit.launcher.request.Request;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.launcher.request.websockets.RequestInterface;
public class ProxyRequest extends Request<ResultInterface> implements RequestInterface {
public RequestInterface response;
public long session;
public ProxyRequest(RequestInterface response, long session) {
this.response = response;
this.session = session;
}
@Override
public String getType() {
return "proxy";
}
}

View file

@ -23,6 +23,10 @@ public final class AuthRequest extends Request<AuthRequestEvent> implements Requ
private final boolean getSession; private final boolean getSession;
@LauncherNetworkAPI @LauncherNetworkAPI
private final ConnectTypes authType; private final ConnectTypes authType;
@LauncherNetworkAPI
public boolean initProxy;
@LauncherNetworkAPI
public String password;
public enum ConnectTypes { public enum ConnectTypes {
@LauncherNetworkAPI @LauncherNetworkAPI
@ -30,7 +34,9 @@ public enum ConnectTypes {
@LauncherNetworkAPI @LauncherNetworkAPI
CLIENT, CLIENT,
@LauncherNetworkAPI @LauncherNetworkAPI
BOT BOT,
@LauncherNetworkAPI
PROXY
} }
@LauncherAPI @LauncherAPI
@ -75,6 +81,16 @@ public AuthRequest(String login, byte[] encryptedPassword, String auth_id, Conne
this.customText = ""; this.customText = "";
this.getSession = false; this.getSession = false;
} }
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
this.login = login;
this.password = password;
this.encryptedPassword = null;
this.auth_id = auth_id;
this.authType = authType;
this.hwid = null;
this.customText = "";
this.getSession = false;
}
@Override @Override
public String getType() { public String getType() {