Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

standard ssl implementation #110

Merged
merged 50 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1786244
ssl
tvd12 Jul 9, 2023
21b8b6f
update (#111)
tvd12 Jul 10, 2023
63e6ce3
can handshake ssl
tvd12 Jul 11, 2023
66a3e36
add EzySslHandshakeHandler
tvd12 Jul 11, 2023
be44160
update keystore
tvd12 Jul 11, 2023
65818bb
update
tvd12 Jul 11, 2023
fc541a2
can ssh hanshake with android client
tvd12 Jul 12, 2023
dc090bd
can transfer data with swift
tvd12 Jul 12, 2023
a66f991
add EzyChannel.pack
tvd12 Jul 12, 2023
1dfa3d3
update EzySecureSocketDataReceiver
tvd12 Jul 13, 2023
539cfa1
update ssl-keystore
tvd12 Jul 13, 2023
7f87e67
close connection
tvd12 Jul 13, 2023
3161995
EzySslHandshakeHandlerTest unitest for unwrap
tvd12 Jul 13, 2023
1c11264
done EzySslHandshakeHandlerTest
tvd12 Jul 13, 2023
083104b
update EzyAbstractResponseApiTest
tvd12 Jul 13, 2023
0e8df3c
add setting unit test
tvd12 Jul 13, 2023
8608b36
change SslType and update EzyAbstractServerBootstrapBuilderTest
tvd12 Jul 14, 2023
f841853
update EzySocketResponseApiTest
tvd12 Jul 14, 2023
6f94624
update EzyHandShakeControllerTest
tvd12 Jul 14, 2023
e8af92f
add EzyChannelTest and SslByteBuffersTest
tvd12 Jul 14, 2023
0d5be6e
add EzySocketChannels
tvd12 Jul 14, 2023
139ee17
add EzySecureSocketDataReceiverTest
tvd12 Jul 14, 2023
64df64a
add EzyNioSecureSocketChannelTest
tvd12 Jul 15, 2023
b240df3
update bootstrap and test
tvd12 Jul 15, 2023
3407e8d
update EzyNioSocketAcceptorTest
tvd12 Jul 15, 2023
4dfe8ef
update EzyAbstractHandlerGroupTest
tvd12 Jul 15, 2023
0a98959
update EzySimpleNioHandlerGroupTest
tvd12 Jul 15, 2023
4c0fa78
update EzySecureSocketDataReceiverTest
tvd12 Jul 15, 2023
2ca1ad0
update EzyNioServerBootstrapBuilderImplTest
tvd12 Jul 15, 2023
ad6c481
update EzyAbstractHandlerGroupTest
tvd12 Jul 15, 2023
e0d9926
update unit test
tvd12 Jul 15, 2023
506c61e
update EzyHandshakeController to check clientKey != null
tvd12 Jul 16, 2023
7c7d0ad
check null
tvd12 Aug 1, 2023
2fb916f
update EzySimplePacket.getSize
tvd12 Aug 1, 2023
6ca564b
remove tryNewSslContext
tvd12 Aug 2, 2023
f5bef64
update EzySslHandshakeHandler logs
tvd12 Aug 2, 2023
b7ecba9
v2
tvd12 Aug 5, 2023
b00b3dc
update
tvd12 Aug 6, 2023
3376947
runnable
tvd12 Aug 6, 2023
55b87af
Merge branch 'master' into ssl
tvd12 Aug 6, 2023
77d427b
Merge branch 'master' into ssl
tvd12 Aug 7, 2023
a6c93c3
move logic to channel
tvd12 Aug 7, 2023
68e8ba3
try to complete unit test
tvd12 Aug 8, 2023
f86c500
almost done unit test
tvd12 Aug 10, 2023
1b28b6a
complete unit test and remove session locks
tvd12 Aug 11, 2023
2775412
update settings
tvd12 Aug 11, 2023
cd007b4
add max request size
tvd12 Aug 12, 2023
e97e966
Merge branch 'master' into ssl
tvd12 Aug 23, 2023
0e494c1
Merge branch 'master' into ssl
tvd12 Aug 23, 2023
80ec6ec
resolve review comments
tvd12 Oct 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ezyfox-server-core/settings/ssl-config.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ssl.keystore="ssl/ssl-key-store.txt"
ssl.keystore=ssl/ssl-keystore.txt
ssl.keystore_password=ssl/ssl-keystore-password.txt
ssl.certificate_password=ssl/ssl-certificate-password.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import com.tvd12.ezyfox.constant.EzyConstant;
import com.tvd12.ezyfox.entity.EzyArray;
import com.tvd12.ezyfox.util.EzyLoggable;
import com.tvd12.ezyfoxserver.constant.EzyTransportType;
import com.tvd12.ezyfoxserver.entity.EzySession;
import com.tvd12.ezyfoxserver.response.EzyPackage;
import com.tvd12.ezyfoxserver.socket.EzyPacket;
import com.tvd12.ezyfoxserver.socket.EzySimplePacket;

import java.util.Collection;

public abstract class EzyAbstractResponseApi implements EzyResponseApi {
public abstract class EzyAbstractResponseApi
extends EzyLoggable
implements EzyResponseApi {

@Override
public void response(
Expand All @@ -32,13 +37,40 @@ protected final void normalResponse(
return;
}
Object bytes = encodeData(pack.getData());
EzyConstant transportType = pack.getTransportType();
if (immediate) {
for (EzySession session : recipients) {
session.sendNow(createPacket(bytes, pack));
EzyPacket packet = null;
try {
packet = createPacket(
session,
transportType,
bytes
);
sendPacketNow(session, packet);
} catch (Throwable e) {
if (packet != null) {
packet.release();
}
logger.info("response data now to session: {} failed", session, e);
vu-luong marked this conversation as resolved.
Show resolved Hide resolved
}
}
} else {
for (EzySession session : recipients) {
session.send(createPacket(bytes, pack));
EzyPacket packet = null;
try {
packet = createPacket(
session,
transportType,
bytes
);
sendPacket(session, packet);
} catch (Throwable e) {
if (packet != null) {
packet.release();
}
logger.info("response data to session: {} failed", session, e);
}
}
}
}
Expand All @@ -53,26 +85,106 @@ protected final void secureResponse(
return;
}
byte[] messageContent = dataToMessageContent(pack.getData());
EzyConstant transportType = pack.getTransportType();
if (immediate) {
for (EzySession session : recipients) {
byte[] bytes = encryptMessageContent(messageContent, session.getSessionKey());
session.sendNow(createPacket(bytes, pack));
EzyPacket packet = null;
try {
byte[] bytes = encryptMessageContent(messageContent, session.getSessionKey());
packet = createPacket(
session,
transportType,
bytes
);
sendPacketNow(session, packet);
} catch (Throwable e) {
if (packet != null) {
packet.release();
}
logger.info("response data now to session: {} failed", session, e);
}
}
} else {
for (EzySession session : recipients) {
byte[] bytes = encryptMessageContent(messageContent, session.getSessionKey());
session.send(createPacket(bytes, pack));
EzyPacket packet = null;
try {
byte[] bytes = encryptMessageContent(messageContent, session.getSessionKey());
packet = createPacket(
session,
transportType,
bytes
);
sendPacket(session, packet);
} catch (Throwable e) {
if (packet != null) {
packet.release();
}
logger.info("response data to session: {} failed", session, e);
}
}
}
}

protected EzySimplePacket createPacket(Object bytes, EzyPackage pack) {
private EzyPacket createPacket(
EzySession session,
EzyConstant transportType,
Object bytes
) {
EzyConstant actualTransportType = transportType;
if (actualTransportType == EzyTransportType.UDP_OR_TCP) {
actualTransportType = session.getDatagramChannelPool() != null
? EzyTransportType.UDP
: EzyTransportType.TCP;
}
return createPacket(actualTransportType, bytes);
}

protected EzySimplePacket createPacket(
EzyConstant transportType,
Object bytes
) {
EzySimplePacket packet = new EzySimplePacket();
packet.setTransportType(pack.getTransportType());
packet.setTransportType(transportType);
packet.setData(bytes);
return packet;
}

private void sendPacket(
EzySession session,
EzyPacket packet
) throws Exception {
if (packet.getTransportType() == EzyTransportType.UDP) {
session.send(packet);
} else {
sendTcpPacket(session, packet);
}
vu-luong marked this conversation as resolved.
Show resolved Hide resolved
}

protected void sendTcpPacket(
EzySession session,
EzyPacket packet
) throws Exception {
session.send(packet);
}

private void sendPacketNow(
EzySession session,
EzyPacket packet
) throws Exception {
if (packet.getTransportType() == EzyTransportType.UDP) {
session.sendNow(packet);
} else {
sendTcpPacketNow(session, packet);
}
vu-luong marked this conversation as resolved.
Show resolved Hide resolved
}

protected void sendTcpPacketNow(
EzySession session,
EzyPacket packet
) throws Exception {
session.sendNow(packet);
}

protected abstract EzyConstant getConnectionType();

protected abstract Object encodeData(EzyArray data) throws Exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ public EzyProxyResponseApi(EzyCodecFactory codecFactory) {

private EzyResponseApi newSocketResponseApi(Object socketEncoder) {
return socketEncoder != null
? new EzySocketResponseApi(socketEncoder)
? createSocketResponseApi(socketEncoder)
: EzyEmptyResponseApi.getInstance();
}

protected EzySocketResponseApi createSocketResponseApi(
Object socketEncoder
) {
return new EzySocketResponseApi(socketEncoder);
}

private EzyResponseApi newWebsocketResponseApi(Object wsEncoder) {
return wsEncoder != null
? new EzyWsResponseApi(wsEncoder)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.tvd12.ezyfoxserver.api;

import com.tvd12.ezyfoxserver.codec.EzyCodecFactory;

public class EzySecureProxyResponseApi extends EzyProxyResponseApi {

public EzySecureProxyResponseApi(EzyCodecFactory codecFactory) {
super(codecFactory);
}

@Override
protected EzySocketResponseApi createSocketResponseApi(
Object socketEncoder
) {
return new EzySecureSocketResponseApi(socketEncoder);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.tvd12.ezyfoxserver.api;

import com.tvd12.ezyfoxserver.entity.EzySession;
import com.tvd12.ezyfoxserver.exception.EzyConnectionCloseException;
import com.tvd12.ezyfoxserver.socket.EzyChannel;
import com.tvd12.ezyfoxserver.socket.EzyPacket;
import com.tvd12.ezyfoxserver.socket.EzySecureChannel;

import java.io.IOException;

public class EzySecureSocketResponseApi extends EzySocketResponseApi {

public EzySecureSocketResponseApi(Object encoder) {
super(encoder);
}

@Override
protected void sendTcpPacket(
EzySession session,
EzyPacket packet
) throws Exception {
EzyChannel channel = session.getChannel();
if (channel == null) {
throw new IOException("session destroyed");
}
EzySecureChannel secureChannel = (EzySecureChannel) channel;
try {
synchronized (secureChannel.getPackingLock()) {
byte[] packedBytes = secureChannel.pack(
(byte[]) packet.getData()
);
packet.replaceData(packedBytes);
session.send(packet);
}
} catch (EzyConnectionCloseException e) {
session.disconnect();
throw e;
}
}

@Override
protected void sendTcpPacketNow(
EzySession session,
EzyPacket packet
) throws Exception {
EzyChannel channel = session.getChannel();
if (channel == null) {
throw new IOException("session destroyed");
}
EzySecureChannel secureChannel = (EzySecureChannel) channel;
try {
synchronized (secureChannel.getPackingLock()) {
byte[] packedBytes = secureChannel.pack(
(byte[]) packet.getData()
);
packet.replaceData(packedBytes);
session.sendNow(packet);
}
} catch (EzyConnectionCloseException e) {
session.disconnect();
throw e;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public class EzySocketResponseApi extends EzyAbstractResponseApi {
protected final EzyMessageDataEncoder encoder;

public EzySocketResponseApi(Object encoder) {
this.encoder = new EzySimpleMessageDataEncoder((EzyObjectToByteEncoder) encoder);
this.encoder = new EzySimpleMessageDataEncoder(
(EzyObjectToByteEncoder) encoder
);
}

@Override
Expand All @@ -21,14 +23,21 @@ protected Object encodeData(EzyArray data) throws Exception {
}

@Override
protected byte[] dataToMessageContent(EzyArray data) throws Exception {
protected byte[] dataToMessageContent(
EzyArray data
) throws Exception {
return encoder.toMessageContent(data);
}

@Override
protected byte[] encryptMessageContent(
byte[] messageContent, byte[] encryptionKey) throws Exception {
return encoder.encryptMessageContent(messageContent, encryptionKey);
byte[] messageContent,
byte[] encryptionKey
) throws Exception {
return encoder.encryptMessageContent(
messageContent,
encryptionKey
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public void response(EzyPackage pack, boolean immediate) throws Exception {
}

@Override
protected EzySimplePacket createPacket(Object bytes, EzyPackage pack) {
EzySimplePacket packet = super.createPacket(bytes, pack);
protected EzySimplePacket createPacket(EzyConstant transportType, Object bytes) {
EzySimplePacket packet = super.createPacket(transportType, bytes);
packet.setBinary(false);
return packet;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ protected EzyServerContext newServerContext(EzyServer server) {
}

protected SSLContext newSslContext(EzySslConfigSetting sslConfig) {
if (getWebsocketSetting().isSslActive()) {
EzySocketSetting socketSetting = getSocketSetting();
EzyWebSocketSetting webSocketSetting = getWebsocketSetting();
boolean activeSslForSocket = socketSetting.isCertificationSslActive();
boolean activeSslForWebsocket = webSocketSetting.isSslActive();
if (activeSslForSocket || activeSslForWebsocket) {
return newSslContextInitializer(sslConfig).init();
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,27 @@ public EzyCloseSessionImpl(EzyServerContext ctx) {

@Override
public void close(EzySession session, EzyConstant reason) {
sendToClients(session, reason);
sendToClient(session, reason);
disconnectSession(session, reason);
}

protected void sendToClients(EzySession session, EzyConstant reason) {
protected void sendToClient(EzySession session, EzyConstant reason) {
if (shouldSendToClient(reason)) {
doSendToClients(session, reason);
doSendToClient(session, reason);
}
}

protected boolean shouldSendToClient(EzyConstant reason) {
return reason != EzyDisconnectReason.UNKNOWN;
return reason != EzyDisconnectReason.UNKNOWN
&& reason != EzyDisconnectReason.SSH_HANDSHAKE_FAILED;
}

protected void disconnectSession(EzySession session, EzyConstant reason) {
logger.info("close session: {}, reason: {}", session.getClientAddress(), reason);
session.close();
}

protected void doSendToClients(EzySession session, EzyConstant reason) {
protected void doSendToClient(EzySession session, EzyConstant reason) {
EzyResponse response = newResponse(reason);
context.sendNow(response, session);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public enum EzyDisconnectReason implements EzyConstant {
ADMIN_KICK(5),
MAX_REQUEST_PER_SECOND(6),
MAX_REQUEST_SIZE(7),
SERVER_ERROR(8);
SERVER_ERROR(8),
SSH_HANDSHAKE_FAILED(9);

private static final Map<Integer, EzyDisconnectReason> REASONS_BY_ID = reasonsById();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.tvd12.ezyfoxserver.constant;

public enum SslType {
CERTIFICATION,
CUSTOMIZATION
}
Loading
Loading