mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 16:41:46 +03:00
Копирование наработок из ветки SSL
This commit is contained in:
parent
bea69c9675
commit
ac8083ac35
5 changed files with 292 additions and 1 deletions
|
@ -43,7 +43,7 @@
|
||||||
compile project(':libLauncher') // pack
|
compile project(':libLauncher') // pack
|
||||||
compileOnly 'org.spigotmc:spigot-api:1.8-R0.1-SNAPSHOT' // api
|
compileOnly 'org.spigotmc:spigot-api:1.8-R0.1-SNAPSHOT' // api
|
||||||
compileOnly 'net.md-5:bungeecord-api:1.8-SNAPSHOT' // api
|
compileOnly 'net.md-5:bungeecord-api:1.8-SNAPSHOT' // api
|
||||||
|
compileOnly group: 'io.netty', name: 'netty-all', version: '4.1.28.Final'
|
||||||
compileOnly 'org.ow2.asm:asm-debug-all:5.0.4'
|
compileOnly 'org.ow2.asm:asm-debug-all:5.0.4'
|
||||||
bundleOnly 'org.ow2.asm:asm-all:5.0.4'
|
bundleOnly 'org.ow2.asm:asm-all:5.0.4'
|
||||||
bundle 'org.apache.logging.log4j:log4j-core:2.9.0'
|
bundle 'org.apache.logging.log4j:log4j-core:2.9.0'
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
package ru.gravit.launchserver.socket;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import io.netty.handler.codec.http.HttpServerCodec;
|
||||||
|
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
import ru.gravit.launcher.LauncherAPI;
|
||||||
|
import ru.gravit.launcher.hasher.HashedEntry;
|
||||||
|
import ru.gravit.launcher.serialize.HInput;
|
||||||
|
import ru.gravit.launcher.serialize.HOutput;
|
||||||
|
import ru.gravit.launcher.ssl.LauncherKeyStore;
|
||||||
|
import ru.gravit.launcher.ssl.LauncherTrustManager;
|
||||||
|
import ru.gravit.launchserver.LaunchServer;
|
||||||
|
import ru.gravit.launchserver.response.Response;
|
||||||
|
import ru.gravit.utils.helper.CommonHelper;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
import ru.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
||||||
|
private static SSLServerSocketFactory ssf;
|
||||||
|
private static final ThreadFactory THREAD_FACTORY = r -> CommonHelper.newThread("Network Thread", true, r);
|
||||||
|
@LauncherAPI
|
||||||
|
public volatile boolean logConnections = Boolean.getBoolean("launcher.logConnections");
|
||||||
|
|
||||||
|
// Instance
|
||||||
|
private final LaunchServer server;
|
||||||
|
private final AtomicReference<ServerSocket> serverSocket = new AtomicReference<>();
|
||||||
|
private final ExecutorService threadPool = Executors.newCachedThreadPool(THREAD_FACTORY);
|
||||||
|
|
||||||
|
// API
|
||||||
|
private final Map<String, Response.Factory> customResponses = new ConcurrentHashMap<>(2);
|
||||||
|
private final AtomicLong idCounter = new AtomicLong(0L);
|
||||||
|
private Set<Socket> sockets;
|
||||||
|
private Selector selector;
|
||||||
|
private ServerSocketChannel serverChannel;
|
||||||
|
private volatile Listener listener;
|
||||||
|
|
||||||
|
public NettyServerSocketHandler(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
ServerSocket socket = serverSocket.getAndSet(null);
|
||||||
|
if (socket != null) {
|
||||||
|
LogHelper.info("Closing server socket listener");
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SSLContext SSLContextInit() throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException, IOException, CertificateException {
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new LauncherTrustManager()
|
||||||
|
};
|
||||||
|
KeyStore ks = LauncherKeyStore.getKeyStore("keystore","PSP1000");
|
||||||
|
|
||||||
|
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
|
||||||
|
.getDefaultAlgorithm());
|
||||||
|
kmf.init(ks, "PSP1000".toCharArray());
|
||||||
|
SSLContext sc = SSLContext.getInstance("TLSv1.2");
|
||||||
|
sc.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SSLContext sc = null;
|
||||||
|
try {
|
||||||
|
sc = SSLContextInit();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (UnrecoverableKeyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (KeyManagementException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
//System.setProperty( "javax.net.ssl.keyStore","keystore");
|
||||||
|
//System.setProperty( "javax.net.ssl.keyStorePassword","PSP1000");
|
||||||
|
try {
|
||||||
|
selector = Selector.open();
|
||||||
|
serverChannel = ServerSocketChannel.open();
|
||||||
|
serverChannel.configureBlocking(false);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
LogHelper.info("Starting server socket thread");
|
||||||
|
SSLEngine engine = sc.createSSLEngine();
|
||||||
|
engine.setUseClientMode(false);
|
||||||
|
EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||||
|
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
|
try {
|
||||||
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
|
b.group(bossGroup, workerGroup)
|
||||||
|
.channel(NioServerSocketChannel.class)
|
||||||
|
.handler(new LoggingHandler(LogLevel.DEBUG))
|
||||||
|
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(NioSocketChannel ch) throws Exception {
|
||||||
|
ChannelPipeline p = ch.pipeline();
|
||||||
|
//p.addLast(new LoggingHandler(LogLevel.INFO));
|
||||||
|
System.out.println("P!");
|
||||||
|
p.addLast("httpServerCodec", new HttpServerCodec());
|
||||||
|
p.addLast(new WebSocketServerProtocolHandler("/chat"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ChannelFuture f = b.bind(server.config.getSocketAddress()).sync();
|
||||||
|
f.channel().closeFuture().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
workerGroup.shutdownGracefully();
|
||||||
|
bossGroup.shutdownGracefully();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
try (SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket()) {
|
||||||
|
serverSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
|
||||||
|
if (!this.serverSocket.compareAndSet(null, serverSocket)) {
|
||||||
|
throw new IllegalStateException("Previous socket wasn't closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set socket params
|
||||||
|
serverSocket.setReuseAddress(true);
|
||||||
|
serverSocket.setPerformancePreferences(1, 0, 2);
|
||||||
|
//serverSocket.setReceiveBufferSize(0x10000);
|
||||||
|
serverSocket.bind(server.config.getSocketAddress());
|
||||||
|
LogHelper.info("Server socket thread successfully started");
|
||||||
|
// Listen for incoming connections
|
||||||
|
while (serverSocket.isBound()) {
|
||||||
|
SSLSocket socket = (SSLSocket) serverSocket.accept();
|
||||||
|
sockets.add(socket);
|
||||||
|
socket.startHandshake();
|
||||||
|
// Invoke pre-connect listener
|
||||||
|
long id = idCounter.incrementAndGet();
|
||||||
|
if (listener != null && !listener.onConnect(id, socket.getInetAddress())) {
|
||||||
|
continue; // Listener didn't accepted this connection
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reply in separate thread
|
||||||
|
threadPool.execute(new ResponseThread(server, id, socket));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Ignore error after close/rebind
|
||||||
|
if (serverSocket.get() != null) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public void registerCustomResponse(String name, Response.Factory factory) {
|
||||||
|
VerifyHelper.verifyIDName(name);
|
||||||
|
VerifyHelper.putIfAbsent(customResponses, name, Objects.requireNonNull(factory, "factory"),
|
||||||
|
String.format("Custom response has been already registered: '%s'", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public void setListener(Listener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ void onDisconnect(long id, Exception e) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onDisconnect(id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ boolean onHandshake(long id, Integer type) {
|
||||||
|
return listener == null || listener.onHandshake(id, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
@LauncherAPI
|
||||||
|
boolean onConnect(long id, InetAddress address);
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
void onDisconnect(long id, Exception e);
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
boolean onHandshake(long id, Integer type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package ru.gravit.launcher.ssl;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
public class LauncherKeyStore {
|
||||||
|
public static KeyStore getKeyStore(String keystore,String password) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
InputStream ksIs = new FileInputStream(keystore);
|
||||||
|
try {
|
||||||
|
ks.load(ksIs, password.toCharArray());
|
||||||
|
} finally {
|
||||||
|
if (ksIs != null) {
|
||||||
|
ksIs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ru.gravit.launcher.ssl;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
public class LauncherSSLContext {
|
||||||
|
public SSLServerSocketFactory ssf;
|
||||||
|
public SSLSocketFactory sf;
|
||||||
|
private SSLContext sc;
|
||||||
|
public LauncherSSLContext(KeyStore ks,String keypassword) throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, UnrecoverableKeyException, KeyManagementException {
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new LauncherTrustManager()
|
||||||
|
};
|
||||||
|
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
|
||||||
|
.getDefaultAlgorithm());
|
||||||
|
kmf.init(ks, keypassword.toCharArray());
|
||||||
|
SSLContext sc = SSLContext.getInstance("TLSv1.2");
|
||||||
|
sc.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());
|
||||||
|
ssf = sc.getServerSocketFactory();
|
||||||
|
sf = sc.getSocketFactory();
|
||||||
|
}
|
||||||
|
public LauncherSSLContext() throws NoSuchAlgorithmException, KeyManagementException {
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new LauncherTrustManager()
|
||||||
|
};
|
||||||
|
SSLContext sc = SSLContext.getInstance("TLSv1.2");
|
||||||
|
sc.init(null, trustAllCerts, new SecureRandom());
|
||||||
|
ssf = null;
|
||||||
|
sf = sc.getSocketFactory();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ru.gravit.launcher.ssl;
|
||||||
|
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
public class LauncherTrustManager implements X509TrustManager {
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue