[fix] 优化tcp架构

This commit is contained in:
wujiawei
2024-12-13 14:29:11 +08:00
parent 41a81133f1
commit 42bc37c712
113 changed files with 3617 additions and 300 deletions

View File

@ -88,7 +88,7 @@ public class ClusterNodeChangeEventImpl implements ClientChangeEvent {
if (serverEndpointChannelChannel != null && serverEndpointChannelChannel.isActive()) {
// 客户端本地获取所有 已经连接的服务端的channel 通知他们 扫描数据库node信息重新初始化
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.REPORT_CLUSTER_NODE_REGISTER_MESSAGE);
nettyMsg.setType(MessageType.TCP_REPORT_CLUSTER_NODE_REGISTER_MESSAGE);
nettyMsg.setClientId(clientId);
nettyMsg.setData((clientId).getBytes());
serverEndpointChannelChannel.writeAndFlush(nettyMsg);

View File

@ -1,102 +0,0 @@
package org.framework.lazy.cloud.network.heartbeat.server.config;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.server.netty.tcp.advanced.*;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.*;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Role;
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class HeartbeatServerConfiguration {
/**
* 服务端 处理客户端心跳
*
* @return ServerHandleTcpChannelHeartbeatTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpChannelHeartbeatTypeAdvanced serverChannelHeartbeatTypeAdvanced() {
return new ServerHandleTcpChannelHeartbeatTypeAdvanced();
}
/**
* 处理 服务端处理客户端数据传输
*
* @return ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced serverReportChannelTransferTypeAdvanced(ChannelFlowAdapter channelFlowAdapter) {
return new ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced(channelFlowAdapter);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpClientConnectSuccessTypeAdvanced serverReportConnectSuccessTypeAdvanced(
LazyClientStatsChangeApplication lazyClientStatsChangeApplication,
LazyNettyClientBlacklistApplication lazyNettyClientBlacklistApplication,
LazyInternalNetworkServerPermeateClientMappingApplication lazyInternalNetworkServerPermeateClientMappingApplication,
LazyInternalNetworkClientPermeateServerMappingApplication lazyInternalNetworkClientPermeateServerMappingApplication,
LazyInternalNetworkClientPermeateClientMappingApplication lazyInternalNetworkClientPermeateClientMappingApplication,
LazyNettyClientTokenBucketApplication lazyNettyClientTokenBucketApplication,
ServerNodeProperties serverNodeProperties
) {
return new ServerHandleTcpClientConnectSuccessTypeAdvanced(lazyClientStatsChangeApplication,
lazyNettyClientBlacklistApplication,
lazyInternalNetworkServerPermeateClientMappingApplication,
lazyInternalNetworkClientPermeateServerMappingApplication,
lazyInternalNetworkClientPermeateClientMappingApplication,
lazyNettyClientTokenBucketApplication,
serverNodeProperties
);
}
/**
* 服务端处理集群注册信息
*
* @param lazyNettyClusterNodeApplication 集群信息获取
* @return ServerHandleTcpReportClusterNodeRegisterTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportClusterNodeRegisterTypeAdvanced serverHandleReportClusterNodeRegisterTypeAdvanced() {
return new ServerHandleTcpReportClusterNodeRegisterTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportDisconnectTypeAdvanced serverReportDisconnectTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportDisconnectTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportServicePermeateClientCloseVisitorTypeAdvanced serverReportSingleClientCloseVisitorTypeAdvanced() {
return new ServerHandleTcpReportServicePermeateClientCloseVisitorTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportServicePermeateClientRealConnectTypeAdvanced serverReportSingleClientRealConnectTypeAdvanced() {
return new ServerHandleTcpReportServicePermeateClientRealConnectTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportStagingClosedTypeAdvanced serverReportStagingClosedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportStagingClosedTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpReportStagingOpenedTypeAdvanced serverReportStagingOpenedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportStagingOpenedTypeAdvanced(lazyClientStatsChangeApplication);
}
}

View File

@ -0,0 +1,196 @@
package org.framework.lazy.cloud.network.heartbeat.server.config;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.server.netty.tcp.advanced.*;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced.*;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.*;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ServerAutoConfiguration {
@Configuration( )
static class ServerTcpConfiguration{
/**
* 服务端 处理客户端心跳
*
* @return ServerHandleTcpChannelHeartbeatTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleTcpChannelHeartbeatTypeAdvanced serverChannelHeartbeatTypeAdvanced() {
return new ServerHandleTcpChannelHeartbeatTypeAdvanced();
}
/**
* 处理 服务端处理客户端数据传输
*
* @return ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced serverReportChannelTransferTypeAdvanced(ChannelFlowAdapter channelFlowAdapter) {
return new ServerHandleTcpReportServicePermeateClientTransferTypeAdvanced(channelFlowAdapter);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpClientConnectSuccessTypeAdvanced serverReportConnectSuccessTypeAdvanced(
LazyClientStatsChangeApplication lazyClientStatsChangeApplication,
LazyNettyClientBlacklistApplication lazyNettyClientBlacklistApplication,
LazyInternalNetworkServerPermeateClientMappingApplication lazyInternalNetworkServerPermeateClientMappingApplication,
LazyInternalNetworkClientPermeateServerMappingApplication lazyInternalNetworkClientPermeateServerMappingApplication,
LazyInternalNetworkClientPermeateClientMappingApplication lazyInternalNetworkClientPermeateClientMappingApplication,
LazyNettyClientTokenBucketApplication lazyNettyClientTokenBucketApplication,
ServerNodeProperties serverNodeProperties
) {
return new ServerHandleTcpClientConnectSuccessTypeAdvanced(lazyClientStatsChangeApplication,
lazyNettyClientBlacklistApplication,
lazyInternalNetworkServerPermeateClientMappingApplication,
lazyInternalNetworkClientPermeateServerMappingApplication,
lazyInternalNetworkClientPermeateClientMappingApplication,
lazyNettyClientTokenBucketApplication,
serverNodeProperties
);
}
/**
* 服务端处理集群注册信息
*
* @param lazyNettyClusterNodeApplication 集群信息获取
* @return ServerHandleTcpReportClusterNodeRegisterTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportClusterNodeRegisterTypeAdvanced serverHandleReportClusterNodeRegisterTypeAdvanced() {
return new ServerHandleTcpReportClusterNodeRegisterTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportDisconnectTypeAdvanced serverReportDisconnectTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportDisconnectTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportServicePermeateClientCloseVisitorTypeAdvanced serverReportSingleClientCloseVisitorTypeAdvanced() {
return new ServerHandleTcpReportServicePermeateClientCloseVisitorTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportServicePermeateClientRealConnectTypeAdvanced serverReportSingleClientRealConnectTypeAdvanced() {
return new ServerHandleTcpReportServicePermeateClientRealConnectTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportStagingClosedTypeAdvanced serverReportStagingClosedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportStagingClosedTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleTcpReportStagingOpenedTypeAdvanced serverReportStagingOpenedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleTcpReportStagingOpenedTypeAdvanced(lazyClientStatsChangeApplication);
}
}
@Configuration( )
static class ServerUdpConfiguration{
/**
* 服务端 处理客户端心跳
*
* @return ServerHandleUdpChannelHeartbeatTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public ServerHandleUdpChannelHeartbeatTypeAdvanced serverChannelHeartbeatTypeAdvanced() {
return new ServerHandleUdpChannelHeartbeatTypeAdvanced();
}
/**
* 处理 服务端处理客户端数据传输
*
* @return ServerHandleUdpReportServicePermeateClientTransferTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportServicePermeateClientTransferTypeAdvanced serverReportChannelTransferTypeAdvanced(ChannelFlowAdapter channelFlowAdapter) {
return new ServerHandleUdpReportServicePermeateClientTransferTypeAdvanced(channelFlowAdapter);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpClientConnectSuccessTypeAdvanced serverReportConnectSuccessTypeAdvanced(
LazyClientStatsChangeApplication lazyClientStatsChangeApplication,
LazyNettyClientBlacklistApplication lazyNettyClientBlacklistApplication,
LazyInternalNetworkServerPermeateClientMappingApplication lazyInternalNetworkServerPermeateClientMappingApplication,
LazyInternalNetworkClientPermeateServerMappingApplication lazyInternalNetworkClientPermeateServerMappingApplication,
LazyInternalNetworkClientPermeateClientMappingApplication lazyInternalNetworkClientPermeateClientMappingApplication,
LazyNettyClientTokenBucketApplication lazyNettyClientTokenBucketApplication,
ServerNodeProperties serverNodeProperties
) {
return new ServerHandleUdpClientConnectSuccessTypeAdvanced(lazyClientStatsChangeApplication,
lazyNettyClientBlacklistApplication,
lazyInternalNetworkServerPermeateClientMappingApplication,
lazyInternalNetworkClientPermeateServerMappingApplication,
lazyInternalNetworkClientPermeateClientMappingApplication,
lazyNettyClientTokenBucketApplication,
serverNodeProperties
);
}
/**
* 服务端处理集群注册信息
*
* @param lazyNettyClusterNodeApplication 集群信息获取
* @return ServerHandleUdpReportClusterNodeRegisterTypeAdvanced
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportClusterNodeRegisterTypeAdvanced serverHandleReportClusterNodeRegisterTypeAdvanced() {
return new ServerHandleUdpReportClusterNodeRegisterTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportDisconnectTypeAdvanced serverReportDisconnectTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleUdpReportDisconnectTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportServicePermeateClientCloseVisitorTypeAdvanced serverReportSingleClientCloseVisitorTypeAdvanced() {
return new ServerHandleUdpReportServicePermeateClientCloseVisitorTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportServicePermeateClientRealConnectTypeAdvanced serverReportSingleClientRealConnectTypeAdvanced() {
return new ServerHandleUdpReportServicePermeateClientRealConnectTypeAdvanced();
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportStagingClosedTypeAdvanced serverReportStagingClosedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleUdpReportStagingClosedTypeAdvanced(lazyClientStatsChangeApplication);
}
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
static ServerHandleUdpReportStagingOpenedTypeAdvanced serverReportStagingOpenedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
return new ServerHandleUdpReportStagingOpenedTypeAdvanced(lazyClientStatsChangeApplication);
}
}
}

View File

@ -10,6 +10,7 @@ import io.netty.util.internal.SystemPropertyUtil;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.server.netty.tcp.filter.NettyTcpServerFilter;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpServerFilter;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
@ -20,12 +21,12 @@ import org.springframework.stereotype.Component;
public class NettyUdpServerSocketApplicationListener implements ApplicationListener<ApplicationStartedEvent> {
private final EventLoopGroup bossGroup = "linux".equalsIgnoreCase(SystemPropertyUtil.get("os.name")) ? new EpollEventLoopGroup() : new NioEventLoopGroup();
private final NettyTcpServerFilter nettyTcpServerFilter;// 通道业务处理
private final NettyUdpServerFilter nettyUdpServerFilter;// 通道业务处理
private ChannelFuture channelFuture;
private final ServerNodeProperties serverNodeProperties;
public NettyUdpServerSocketApplicationListener(NettyTcpServerFilter nettyTcpServerFilter, ServerNodeProperties serverNodeProperties) {
this.nettyTcpServerFilter = nettyTcpServerFilter;
public NettyUdpServerSocketApplicationListener(NettyUdpServerFilter nettyUdpServerFilter, ServerNodeProperties serverNodeProperties) {
this.nettyUdpServerFilter = nettyUdpServerFilter;
this.serverNodeProperties = serverNodeProperties;
}
@ -59,7 +60,7 @@ public class NettyUdpServerSocketApplicationListener implements ApplicationListe
.option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 10)
//发送缓存区 10M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024 * 10)
.handler(nettyTcpServerFilter);
.handler(nettyUdpServerFilter);
channelFuture = b.bind(udpPort).sync();
channelFuture.addListener((ChannelFutureListener) channelFuture -> {

View File

@ -12,7 +12,7 @@ import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
/**
* 服务端 处理客户端心跳
* TYPE_HEARTBEAT
* TCP_TYPE_HEARTBEAT
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Component
@ -27,7 +27,7 @@ public class ServerHandleTcpChannelHeartbeatTypeAdvanced extends AbstractTcpHand
@Override
public void doHandler(Channel channel, NettyProxyMsg msg) {
NettyProxyMsg hb = new NettyProxyMsg();
hb.setType(MessageType.TYPE_HEARTBEAT);
hb.setType(MessageType.TCP_TYPE_HEARTBEAT);
channel.writeAndFlush(hb);
}

View File

@ -28,7 +28,7 @@ import java.util.List;
/**
* 服务端连接成功处理
* REPORT_CLIENT_CONNECT_SUCCESS
* TCP_REPORT_CLIENT_CONNECT_SUCCESS
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j

View File

@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透服务端通信
* REPORT_CLIENT_PERMEATE_SERVER_TRANSFER
* TCP_REPORT_CLIENT_PERMEATE_SERVER_TRANSFER
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j

View File

@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
/**
* 服务端处理客户端数据传输
* REPORT_CLIENT_TRANSFER
* TCP_REPORT_CLIENT_TRANSFER
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j

View File

@ -73,7 +73,7 @@ public class NettyTcpServerHandler extends SimpleChannelInboundHandler<NettyProx
// 给所有客户端发送 这个客户端离线了
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setClientId(clientId);
nettyMsg.setType(MessageType.REPORT_CLIENT_DISCONNECTION);
nettyMsg.setType(MessageType.TCP_REPORT_CLIENT_DISCONNECTION);
channelTypeAdapter.handler(channel, nettyMsg);
channel.close();
} else {
@ -132,7 +132,7 @@ public class NettyTcpServerHandler extends SimpleChannelInboundHandler<NettyProx
// 断开客户端的连接:{}
log.warn("Disconnect client:{}", clientId);
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.REPORT_CLIENT_DISCONNECTION);
nettyMsg.setType(MessageType.TCP_REPORT_CLIENT_DISCONNECTION);
nettyMsg.setClientId(clientId);
channelTypeAdapter.handler(channel, nettyMsg);
super.channelInactive(ctx);

View File

@ -0,0 +1,35 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.AbstractUdpHandleChannelHeartbeatTypeAdvanced;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 服务端 处理客户端心跳
* TCP_TYPE_HEARTBEAT
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Component
public class ServerHandleUdpChannelHeartbeatTypeAdvanced extends AbstractUdpHandleChannelHeartbeatTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel channel, NettyProxyMsg msg) {
NettyProxyMsg hb = new NettyProxyMsg();
hb.setType(MessageType.TCP_TYPE_HEARTBEAT);
channel.writeAndFlush(hb);
}
}

View File

@ -0,0 +1,182 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpClientConnectSuccessTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.*;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.permeate.client.mapping.LazyInternalNetworkClientPermeateClientMappingQueryListCommand;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.permeate.server.mapping.LazyInternalNetworkClientPermeateServerMappingQueryListCommand;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.state.LazyNettyClientLoginCommand;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.dto.LazyInternalNetworkClientPermeateClientMappingDTO;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.dto.LazyInternalNetworkClientPermeateServerMappingDTO;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.domain.model.lazy.netty.client.blacklist.LazyNettyClientBlacklist;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import org.wu.framework.web.response.Result;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 服务端连接成功处理
* TCP_REPORT_CLIENT_CONNECT_SUCCESS
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpClientConnectSuccessTypeAdvanced extends AbstractHandleUdpClientConnectSuccessTypeAdvanced<NettyProxyMsg> {
private final LazyClientStatsChangeApplication lazyClientStatsChangeApplication;
private final LazyNettyClientBlacklistApplication lazyNettyClientBlacklistApplication;
private final LazyInternalNetworkServerPermeateClientMappingApplication lazyInternalNetworkServerPermeateClientMappingApplication;
private final LazyInternalNetworkClientPermeateServerMappingApplication lazyInternalNetworkClientPermeateServerMappingApplication;
private final LazyInternalNetworkClientPermeateClientMappingApplication lazyInternalNetworkClientPermeateClientMappingApplication;
private final LazyNettyClientTokenBucketApplication lazyNettyClientTokenBucketApplication;
private final ServerNodeProperties serverNodeProperties;
public ServerHandleUdpClientConnectSuccessTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication, LazyNettyClientBlacklistApplication lazyNettyClientBlacklistApplication, LazyInternalNetworkServerPermeateClientMappingApplication lazyInternalNetworkServerPermeateClientMappingApplication, LazyInternalNetworkClientPermeateServerMappingApplication lazyInternalNetworkClientPermeateServerMappingApplication, LazyInternalNetworkClientPermeateClientMappingApplication lazyInternalNetworkClientPermeateClientMappingApplication, LazyNettyClientTokenBucketApplication lazyNettyClientTokenBucketApplication, ServerNodeProperties serverNodeProperties) {
this.lazyClientStatsChangeApplication = lazyClientStatsChangeApplication;
this.lazyNettyClientBlacklistApplication = lazyNettyClientBlacklistApplication;
this.lazyInternalNetworkServerPermeateClientMappingApplication = lazyInternalNetworkServerPermeateClientMappingApplication;
this.lazyInternalNetworkClientPermeateServerMappingApplication = lazyInternalNetworkClientPermeateServerMappingApplication;
this.lazyInternalNetworkClientPermeateClientMappingApplication = lazyInternalNetworkClientPermeateClientMappingApplication;
this.lazyNettyClientTokenBucketApplication = lazyNettyClientTokenBucketApplication;
this.serverNodeProperties = serverNodeProperties;
}
/**
* 处理当前数据
*
* @param newChannel 当前通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel newChannel, NettyProxyMsg msg) {
String clientId = msg.getClientIdString();
String appKey = msg.getAppKeyString();
String appSecret = msg.getAppSecretString();
String originalIp = msg.getOriginalIpString();
ChannelContext.push(newChannel, clientId);
ChannelAttributeKeyUtils.buildClientId(newChannel, clientId);
ChannelAttributeKeyUtils.buildAppKey(newChannel, appKey);
ChannelAttributeKeyUtils.buildAppSecret(newChannel, appSecret);
ChannelAttributeKeyUtils.buildOriginalIp(newChannel, originalIp);
// 客户端:{}IP:{}连接成功
log.info("Client: {}, IP: {} Connection successful", new String(msg.getClientId()), newChannel.remoteAddress().toString());
// 验证客户端是否时黑名单
LazyNettyClientBlacklist lazyNettyClientBlacklist = new LazyNettyClientBlacklist();
lazyNettyClientBlacklist.setClientId(clientId);
lazyNettyClientBlacklist.setIsDeleted(false);
lazyNettyClientBlacklistApplication.exists(lazyNettyClientBlacklist).accept(exists -> {
if (!exists) {
// 认证验证
Result<Boolean> existsTokenResult = lazyNettyClientTokenBucketApplication.certificationToken(clientId, appKey, appSecret);
Boolean existsToken= existsTokenResult.getData();
Boolean enableTokenVerification = serverNodeProperties.getEnableTokenVerification();
existsToken = enableTokenVerification ? existsToken : true;
if(existsToken){
// 服务状态在线
LazyNettyClientLoginCommand lazyNettyClientLoginCommand = new LazyNettyClientLoginCommand();
lazyNettyClientLoginCommand.setClientId(clientId);
lazyNettyClientLoginCommand.setAppKey(appKey);
lazyNettyClientLoginCommand.setAppSecret(appSecret);
lazyNettyClientLoginCommand.setOriginalIp(originalIp);
lazyClientStatsChangeApplication.clientOnLine(lazyNettyClientLoginCommand);
// 当前在线客户端数量:{}
log.info("Current number of online clients: {}", ChannelContext.getClientIds().size());
// 所有的客户端ID
List<String> clientIdList = ChannelContext.getClientIds();
// TODO 多副本本地channel 无法共享问题
// 通知所有客户端有人上线了
ChannelContext.getChannels().forEach((existClientId, channels) -> {
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_CONNECTION_SUCCESS_NOTIFICATION);
nettyMsg.setData((JSON.toJSONString(clientIdList)
.getBytes(StandardCharsets.UTF_8)));
// 发送所有客户端ID
for (Channel channel : channels) {
channel.writeAndFlush(nettyMsg);
}
});
// 开始开启客户端:【{}】,端口映射
log.info("Start opening client: [{}], port mapping", clientId);
// 创建访问者(内网穿透连接创建)
lazyInternalNetworkServerPermeateClientMappingApplication.createVisitor(clientId);
// 结束开启客户端:【{}】,端口映射
log.info("End opening client: [{}], port mapping", clientId);
}else {
// 关闭通道
log.warn("无法认证客户端:【{}】",clientId);
newChannel.close();
}
} else {
// 黑名单客户端
}
});
// 查询客户端渗透服务端信息
LazyInternalNetworkClientPermeateServerMappingQueryListCommand lazyInternalNetworkClientPermeateServerMappingQueryListCommand = new LazyInternalNetworkClientPermeateServerMappingQueryListCommand();
lazyInternalNetworkClientPermeateServerMappingQueryListCommand.setClientId(clientId);
lazyInternalNetworkClientPermeateServerMappingQueryListCommand.setIsDeleted(false);
lazyInternalNetworkClientPermeateServerMappingApplication.findList(lazyInternalNetworkClientPermeateServerMappingQueryListCommand)
.accept(lazyInternalNetworkClientPermeateServerMappingDTOS -> {
for (LazyInternalNetworkClientPermeateServerMappingDTO lazyInternalNetworkClientPermeateServerMappingDTO : lazyInternalNetworkClientPermeateServerMappingDTOS) {
String permeateTargetIp = lazyInternalNetworkClientPermeateServerMappingDTO.getPermeateTargetIp();
Integer permeateTargetPort = lazyInternalNetworkClientPermeateServerMappingDTO.getPermeateTargetPort();
Integer visitorPort = lazyInternalNetworkClientPermeateServerMappingDTO.getVisitorPort();
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_SERVER_INIT);
nettyMsg.setClientTargetIp(permeateTargetIp);
nettyMsg.setClientTargetPort(permeateTargetPort);
nettyMsg.setVisitorPort(visitorPort);
newChannel.writeAndFlush(nettyMsg);
}
});
// 查询客户端渗透客户端信息
LazyInternalNetworkClientPermeateClientMappingQueryListCommand lazyInternalNetworkClientPermeateClientMappingQueryListCommand = new LazyInternalNetworkClientPermeateClientMappingQueryListCommand();
lazyInternalNetworkClientPermeateClientMappingQueryListCommand.setFromClientId(clientId);
lazyInternalNetworkClientPermeateClientMappingQueryListCommand.setIsDeleted(false);
lazyInternalNetworkClientPermeateClientMappingApplication.findList(lazyInternalNetworkClientPermeateClientMappingQueryListCommand)
.accept(lazyInternalNetworkClientPermeateServerMappingDTOS -> {
for (LazyInternalNetworkClientPermeateClientMappingDTO lazyInternalNetworkClientPermeateClientMappingDTO : lazyInternalNetworkClientPermeateServerMappingDTOS) {
String permeateTargetIp = lazyInternalNetworkClientPermeateClientMappingDTO.getPermeateTargetIp();
Integer permeateTargetPort = lazyInternalNetworkClientPermeateClientMappingDTO.getPermeateTargetPort();
Integer visitorPort = lazyInternalNetworkClientPermeateClientMappingDTO.getVisitorPort();
String toClientId = lazyInternalNetworkClientPermeateClientMappingDTO.getToClientId();
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_CLIENT_INIT);
nettyMsg.setClientTargetIp(permeateTargetIp);
nettyMsg.setClientTargetPort(permeateTargetPort);
nettyMsg.setVisitorPort(visitorPort);
nettyMsg.setClientId(clientId);
nettyMsg.setData(toClientId.getBytes(StandardCharsets.UTF_8));
newChannel.writeAndFlush(nettyMsg);
}
});
}
}

View File

@ -0,0 +1,37 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientPermeateClientCloseTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透客户端init close 信息
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientPermeateClientCloseTypeAdvanced extends AbstractHandleUdpReportClientPermeateClientCloseTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 关闭 next、next transfer 通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
Channel transferNextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
channel.close();
nextChannel.close();
transferNextChannel.close();
}
}

View File

@ -0,0 +1,44 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientPermeateClientTransferCloseTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报客户端渗透客户端通信通道关闭
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientPermeateClientTransferCloseTypeAdvanced extends AbstractHandleUdpReportClientPermeateClientTransferCloseTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 关闭 next、next transfer 通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
Channel transferNextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
// 下发关闭客户端真实通道
NettyProxyMsg closeTransferNettyProxyMsg = new NettyProxyMsg();
closeTransferNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_CLIENT_TRANSFER_CLOSE);
transferNextChannel.writeAndFlush(closeTransferNettyProxyMsg);
channel.close();
nextChannel.close();
transferNextChannel.close();
}
}

View File

@ -0,0 +1,32 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientPermeateServerTransferCloseTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透服务端通信通道关闭
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientPermeateServerTransferCloseTypeAdvanced extends AbstractHandleUdpReportClientPermeateServerTransferCloseTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 关闭传输通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
nextChannel.close();
channel.close();
}
}

View File

@ -0,0 +1,65 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientPermeateServerTransferTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透服务端通信
* TCP_REPORT_CLIENT_PERMEATE_SERVER_TRANSFER
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientPermeateServerTransferTypeAdvanced extends AbstractHandleUdpReportClientPermeateServerTransferTypeAdvanced<NettyProxyMsg> {
private final ChannelFlowAdapter channelFlowAdapter;
public ServerHandleUdpReportClientPermeateServerTransferTypeAdvanced(ChannelFlowAdapter channelFlowAdapter) {
this.channelFlowAdapter = channelFlowAdapter;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg msg) {
String clientId = new String(msg.getClientId());
Integer visitorPort = Integer.valueOf(new String(msg.getVisitorPort()));
byte[] visitorId = msg.getVisitorId();
log.debug("【客户端渗透服务端】访客ID:【{}】 访客端口:[{}] 接收到客户端:[{}] 接收服务端数据大小:[{}]", new String(visitorId), visitorPort, clientId, msg.getData().length);
log.debug("【客户端渗透服务端】访客ID:【{}】接收到客户端:[{}] 接收服务端数据大小:[{}] 接收服务端数据:[{}]", new String(visitorId), clientId, msg.getData().length, new String(msg.getData()));
// 将数据转发访客通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
if (nextChannel != null) {
ByteBuf buf = nextChannel.config().getAllocator().buffer(msg.getData().length);
buf.writeBytes(msg.getData());
ChannelFuture channelFuture = nextChannel.writeAndFlush(buf);
boolean success = channelFuture.isSuccess();
log.debug("visitor writerAndFlush status: {}", success);
// 记录进口数据
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.IN_FLOW)
.port(visitorPort)
.clientId(clientId)
.flow(msg.getData().length)
.build();
channelFlowAdapter.asyncHandler(channel, serverChannelFlow);
}
log.debug("客户端渗透服务端】访客ID:【{}】接收到客户端:[{}] 传输真实数据成功", new String(visitorId), clientId);
}
}

View File

@ -0,0 +1,60 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyTransferChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientTransferClientPermeateChannelConnectionSuccessfulTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透客户端数据传输通道连接成功
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientTransferClientPermeateChannelConnectionSuccessfulTypeAdvanced extends AbstractHandleUdpReportClientTransferClientPermeateChannelConnectionSuccessfulTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param transferChannel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel transferChannel, NettyProxyMsg nettyProxyMsg) {
// 创建目标地址连接
byte[] msgVisitorId = nettyProxyMsg.getVisitorId();
byte[] msgVisitorPort = nettyProxyMsg.getVisitorPort();
byte[] msgClientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] msgClientTargetPort = nettyProxyMsg.getClientTargetPort();
byte[] clientId = nettyProxyMsg.getClientId();// 目标客户端ID
ChannelAttributeKeyUtils.buildClientId(transferChannel, clientId);
ChannelAttributeKeyUtils.buildVisitorPort(transferChannel, Integer.parseInt(new String(msgVisitorPort)));
ChannelAttributeKeyUtils.buildVisitorId(transferChannel, msgVisitorId);
// 绑定访客通道
NettyTransferChannelContext.pushVisitor(transferChannel,msgVisitorId);
Channel clientChannel = ChannelContext.getLoadBalance(clientId);
NettyProxyMsg clientConnectTagetNettyProxyMsg = new NettyProxyMsg();
clientConnectTagetNettyProxyMsg.setVisitorId(msgVisitorId);
clientConnectTagetNettyProxyMsg.setVisitorPort(msgVisitorPort);
clientConnectTagetNettyProxyMsg.setClientTargetIp(msgClientTargetIp);
clientConnectTagetNettyProxyMsg.setClientTargetPort(msgClientTargetPort);
clientConnectTagetNettyProxyMsg.setClientId(clientId);
clientConnectTagetNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_TRANSFER_CLIENT_PERMEATE_CHANNEL_CONNECTION_SUCCESSFUL);
if (clientChannel != null) {
clientChannel.writeAndFlush(clientConnectTagetNettyProxyMsg);
}else {
log.error("can not find the client:【】 channel",clientId);
}
}
}

View File

@ -0,0 +1,62 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyTransferChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientTransferClientPermeateChannelInitSuccessfulTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报 客户端渗透客户端数据传输通道init
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientTransferClientPermeateChannelInitSuccessfulTypeAdvanced extends AbstractHandleUdpReportClientTransferClientPermeateChannelInitSuccessfulTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param transferChannel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel transferChannel, NettyProxyMsg nettyProxyMsg) {
// 创建目标地址连接
byte[] msgVisitorId = nettyProxyMsg.getVisitorId();
byte[] msgVisitorPort = nettyProxyMsg.getVisitorPort();
byte[] msgClientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] msgClientTargetPort = nettyProxyMsg.getClientTargetPort();
byte[] clientId = nettyProxyMsg.getClientId();
ChannelAttributeKeyUtils.buildVisitorPort(transferChannel, Integer.parseInt(new String(msgVisitorPort)));
// next translation
Channel nextTransferChannel = NettyTransferChannelContext.getVisitor(msgVisitorId);
ChannelAttributeKeyUtils.buildTransferNextChannel(nextTransferChannel,transferChannel);
ChannelAttributeKeyUtils.buildTransferNextChannel(transferChannel,nextTransferChannel);
ChannelAttributeKeyUtils.buildClientId(transferChannel,clientId);
ChannelAttributeKeyUtils.buildVisitorId(transferChannel,msgVisitorId);
Channel nextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(transferChannel);
NettyProxyMsg clientConnectTagetNettyProxyMsg = new NettyProxyMsg();
clientConnectTagetNettyProxyMsg.setVisitorId(msgVisitorId);
clientConnectTagetNettyProxyMsg.setVisitorPort(msgVisitorPort);
clientConnectTagetNettyProxyMsg.setClientTargetIp(msgClientTargetIp);
clientConnectTagetNettyProxyMsg.setClientTargetPort(msgClientTargetPort);
clientConnectTagetNettyProxyMsg.setClientId(clientId);
clientConnectTagetNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_CLIENT_TRANSFER_CHANNEL_INIT_SUCCESSFUL);
if (nextChannel != null) {
nextChannel.writeAndFlush(clientConnectTagetNettyProxyMsg);
}else {
log.error("can not find the client:【】 channel",clientId);
}
}
}

View File

@ -0,0 +1,71 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientTransferClientResponseTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import org.wu.framework.spring.utils.SpringContextHolder;
/**
* 上报客户端渗透客户端数据传输结果
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientTransferClientResponseTypeAdvanced extends AbstractHandleUdpReportClientTransferClientResponseTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 创建目标地址连接
byte[] msgVisitorId = nettyProxyMsg.getVisitorId();
byte[] msgVisitorPort = nettyProxyMsg.getVisitorPort();
byte[] msgClientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] msgClientTargetPort = nettyProxyMsg.getClientTargetPort();
String clientId = nettyProxyMsg.getClientIdString();
// 下发客户端初始化成功
Channel nextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
NettyProxyMsg clientConnectTagetNettyProxyMsg = new NettyProxyMsg();
clientConnectTagetNettyProxyMsg.setVisitorId(msgVisitorId);
clientConnectTagetNettyProxyMsg.setVisitorPort(msgVisitorPort);
clientConnectTagetNettyProxyMsg.setClientTargetIp(msgClientTargetIp);
clientConnectTagetNettyProxyMsg.setClientTargetPort(msgClientTargetPort);
clientConnectTagetNettyProxyMsg.setClientId(clientId);
clientConnectTagetNettyProxyMsg.setData(nettyProxyMsg.getData());
clientConnectTagetNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_CLIENT_TRANSFER_RESPONSE);
if (nextChannel != null) {
nextChannel.writeAndFlush(clientConnectTagetNettyProxyMsg);
//记录出口流量
ChannelFlowAdapter channelFlowAdapter = SpringContextHolder.getBean(ChannelFlowAdapter.class);
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.OUT_FLOW)
.port(Integer.parseInt(new String(msgVisitorPort)))
.clientId(clientId)
.flow(clientConnectTagetNettyProxyMsg.getData().length)
.build();
channelFlowAdapter.asyncHandler(channel, serverChannelFlow);
}else {
log.error("can not find the client:【{}】 channel",clientId);
}
}
}

View File

@ -0,0 +1,67 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientTransferClientTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import org.wu.framework.spring.utils.SpringContextHolder;
/**
* 上报客户端渗透客户端数据传输
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClientTransferClientTypeAdvanced extends AbstractHandleUdpReportClientTransferClientTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 创建目标地址连接
byte[] msgVisitorId = nettyProxyMsg.getVisitorId();
byte[] msgVisitorPort = nettyProxyMsg.getVisitorPort();
byte[] msgClientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] msgClientTargetPort = nettyProxyMsg.getClientTargetPort();
String clientId = nettyProxyMsg.getClientIdString();
// 下发客户端初始化成功
Channel nextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
Integer visitorPort = ChannelAttributeKeyUtils.getVisitorPort(channel);
NettyProxyMsg clientConnectTagetNettyProxyMsg = new NettyProxyMsg();
clientConnectTagetNettyProxyMsg.setVisitorId(msgVisitorId);
clientConnectTagetNettyProxyMsg.setVisitorPort(msgVisitorPort);
clientConnectTagetNettyProxyMsg.setClientTargetIp(msgClientTargetIp);
clientConnectTagetNettyProxyMsg.setClientTargetPort(msgClientTargetPort);
clientConnectTagetNettyProxyMsg.setClientId(clientId);
clientConnectTagetNettyProxyMsg.setData(nettyProxyMsg.getData());
clientConnectTagetNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_CLIENT_TRANSFER_REQUEST);
if (nextChannel != null) {
nextChannel.writeAndFlush(clientConnectTagetNettyProxyMsg);
// 记录进口数据
ChannelFlowAdapter channelFlowAdapter = SpringContextHolder.getBean(ChannelFlowAdapter.class);
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.IN_FLOW)
.port(visitorPort)
.clientId(clientId)
.flow(clientConnectTagetNettyProxyMsg.getData().length)
.build();
channelFlowAdapter.asyncHandler(channel, serverChannelFlow);
}else {
log.error("can not find the client:【{}】 channel",clientId);
}
}
}

View File

@ -0,0 +1,45 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClientTransferServerPermeateChannelConnectionSuccessfulTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket.NettyUdpClientPermeateServerConnectRealSocket;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 上报客户端通信通道连接成功
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Component
public class ServerHandleUdpReportClientTransferServerPermeateChannelConnectionSuccessfulTypeAdvanced extends AbstractHandleUdpReportClientTransferServerPermeateChannelConnectionSuccessfulTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param transferChannel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel transferChannel, NettyProxyMsg nettyProxyMsg) {
// 创建目标地址连接
byte[] msgVisitorId = nettyProxyMsg.getVisitorId();
byte[] msgVisitorPort = nettyProxyMsg.getVisitorPort();
byte[] msgClientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] msgClientTargetPort = nettyProxyMsg.getClientTargetPort();
byte[] msgClientId = nettyProxyMsg.getClientId();
String clientId = new String(msgClientId);
// 绑定客户端ID
ChannelAttributeKeyUtils.buildClientId(transferChannel,clientId);
ChannelAttributeKeyUtils.buildVisitorId(transferChannel,msgVisitorId);
NettyUdpClientPermeateServerConnectRealSocket.buildNewRealServer(new String(msgVisitorId),
Integer.parseInt(new String(msgVisitorPort)),
new String(msgClientTargetIp),
Integer.parseInt(new String(msgClientTargetPort)),
transferChannel
);
}
}

View File

@ -0,0 +1,43 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportClusterNodeRegisterTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.server.cluster.application.LazyNettyClusterNodeApplication;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import org.wu.framework.bean.factory.BeanContext;
/**
* 集群节点注册 服务端本地处理
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportClusterNodeRegisterTypeAdvanced extends
AbstractHandleUdpReportClusterNodeRegisterTypeAdvanced<NettyProxyMsg> {
public ServerHandleUdpReportClusterNodeRegisterTypeAdvanced() {
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
log.info("node register and me start scan node config");
// 本地扫描节点配置重新注册
LazyNettyClusterNodeApplication lazyNettyClusterNodeApplication = BeanContext.getBean(LazyNettyClusterNodeApplication.class);
// 循环依赖问题
lazyNettyClusterNodeApplication.starterClusterNodes();
}
}

View File

@ -0,0 +1,96 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyClientVisitorContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportDisconnectTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket.NettyUdpServerPermeateClientVisitorSocket;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.LazyClientStatsChangeApplication;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.state.LazyNettyClientLoginCommand;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import org.wu.framework.core.utils.ObjectUtils;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 服务端处理客户端断开连接处理
* TYPE_DISCONNECT
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportDisconnectTypeAdvanced extends AbstractHandleUdpReportDisconnectTypeAdvanced<NettyProxyMsg> {
private final LazyClientStatsChangeApplication lazyClientStatsChangeApplication;
public ServerHandleUdpReportDisconnectTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
this.lazyClientStatsChangeApplication = lazyClientStatsChangeApplication;
}
/**
* 处理当前数据
*
* @param deathChannel 关闭的通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel deathChannel, NettyProxyMsg msg) {
// 关闭连接通知
String clientId = msg.getClientIdString();
log.warn("close client :{} channel", clientId);
Channel deathClientChannelDTO = ChannelContext.getLoadBalance(clientId);
String appKey = ChannelAttributeKeyUtils.getAppKey(deathChannel);
String appSecret = ChannelAttributeKeyUtils.getAppSecret(deathChannel);
String originalIp = ChannelAttributeKeyUtils.getOriginalIp(deathChannel);
if (deathClientChannelDTO != null) {
// 服务状态离线
LazyNettyClientLoginCommand lazyNettyClientLoginCommand = new LazyNettyClientLoginCommand();
lazyNettyClientLoginCommand.setClientId(clientId);
lazyNettyClientLoginCommand.setAppKey(appKey);
lazyNettyClientLoginCommand.setAppSecret(appSecret);
lazyNettyClientLoginCommand.setOriginalIp(originalIp);
lazyClientStatsChangeApplication.clientOffLine(lazyNettyClientLoginCommand);
ChannelContext.remove(clientId);
// 通知其他客户端 channelId 关闭了
ChannelContext.getChannels().forEach((existClientId, channels) -> {
for (Channel channel : channels) {
// 离线通知
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_DISCONNECTION_NOTIFICATION);
nettyMsg.setClientId(clientId);
nettyMsg.setData(clientId.getBytes(StandardCharsets.UTF_8));
channel.writeAndFlush(nettyMsg);
// 暂存通知
NettyProxyMsg stagingNettyProxyMsg = new NettyProxyMsg();
stagingNettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_STAGING_OPENED_NOTIFICATION);
stagingNettyProxyMsg.setData(clientId.getBytes(StandardCharsets.UTF_8));
stagingNettyProxyMsg.setClientId(clientId);
channel.writeAndFlush(stagingNettyProxyMsg);
}
});
// 关闭绑定的访客端口
List<NettyUdpServerPermeateClientVisitorSocket> visitorSockets = NettyClientVisitorContext.getVisitorSockets(new String(clientId));
if (!ObjectUtils.isEmpty(visitorSockets)) {
for (NettyUdpServerPermeateClientVisitorSocket visitorSocket : visitorSockets) {
int visitorPort = visitorSocket.getVisitorPort();
visitorSocket.close();
log.warn("client :[{}] visitorPort:[{}] close", new String(clientId), visitorPort);
}
}
}
}
}

View File

@ -0,0 +1,35 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyRealIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportServicePermeateClientCloseVisitorTypeAdvanced;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 服务端处理客户端 关闭一个访客
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportServicePermeateClientCloseVisitorTypeAdvanced extends AbstractHandleUdpReportServicePermeateClientCloseVisitorTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 关闭访客通道
byte[] visitorId = nettyProxyMsg.getVisitorId();
NettyCommunicationIdContext.clear(visitorId);
NettyRealIdContext.clear(visitorId);
}
}

View File

@ -0,0 +1,56 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyRealIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportServicePermeateClientRealConnectTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 服务端渗透客户端通信通道
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportServicePermeateClientRealConnectTypeAdvanced extends AbstractHandleUdpReportServicePermeateClientRealConnectTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param transferChannel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel transferChannel, NettyProxyMsg nettyProxyMsg) {
// 客户端绑定端口成功
byte[] clientId = nettyProxyMsg.getClientId();
byte[] clientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] clientTargetPort = nettyProxyMsg.getClientTargetPort();
byte[] visitorPort = nettyProxyMsg.getVisitorPort();
byte[] visitorId = nettyProxyMsg.getVisitorId();
log.info("客户端:{},绑定真实服务ip:{},port:{},成功", new String(clientId), new String(clientTargetIp), new String(clientTargetPort));
// 绑定服务端访客通信通道
NettyCommunicationIdContext.pushVisitor(transferChannel, new String(visitorId));
ChannelAttributeKeyUtils.buildVisitorId(transferChannel, visitorId);
ChannelAttributeKeyUtils.buildClientId(transferChannel, clientId);
ChannelAttributeKeyUtils.buildVisitorPort(transferChannel, Integer.valueOf(new String(visitorPort)));
// 访客通道开启自动读取
Channel visitorRealChannel = NettyRealIdContext.getReal(visitorId);
visitorRealChannel.config().setOption(ChannelOption.AUTO_READ, true);
ChannelAttributeKeyUtils.buildNextChannel(transferChannel, visitorRealChannel);
ChannelAttributeKeyUtils.buildNextChannel(visitorRealChannel, transferChannel);
// 或许此处还应该通知服务端 这个访客绑定的客户端真实通道打开
// 下发客户端 真实通道自动读写开启
}
}

View File

@ -0,0 +1,70 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyRealIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportServicePermeateClientTransferTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
/**
* 服务端处理客户端数据传输
* TCP_REPORT_CLIENT_TRANSFER
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportServicePermeateClientTransferTypeAdvanced extends AbstractHandleUdpReportServicePermeateClientTransferTypeAdvanced<NettyProxyMsg> {
private final ChannelFlowAdapter channelFlowAdapter;
public ServerHandleUdpReportServicePermeateClientTransferTypeAdvanced(ChannelFlowAdapter channelFlowAdapter) {
this.channelFlowAdapter = channelFlowAdapter;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel channel, NettyProxyMsg msg) {
String clientId = new String(msg.getClientId());
Integer visitorPort = Integer.valueOf(new String(msg.getVisitorPort()));
byte[] visitorId = msg.getVisitorId();
// log.info("访客ID:【{}】 访客端口:[{}] 接收到客户端:[{}]", new String(visitorId), visitorPort, clientId);
// log.debug("访客ID:【{}】接收到客户端:[{}] 返回数据大小:[{}] 内网穿透返回的数据:[{}]", new String(visitorId), clientId, msg.getData().length, new String(msg.getData()));
// 将数据转发访客通道
Channel visitor = NettyRealIdContext.getReal(visitorId);
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
if (nextChannel != null) {
ByteBuf buf = nextChannel.config().getAllocator().buffer(msg.getData().length);
buf.writeBytes(msg.getData());
ChannelFuture channelFuture = nextChannel.writeAndFlush(buf);
boolean success = channelFuture.isSuccess();
log.debug("visitor writerAndFlush status: {}", success);
// 记录出口数据
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.OUT_FLOW)
.port(visitorPort)
.clientId(clientId)
.flow(msg.getData().length)
.build();
channelFlowAdapter.asyncHandler(channel, serverChannelFlow);
}
log.debug("访客ID:【{}】接收到客户端:[{}] 发送真实数据成功", new String(visitorId), clientId);
}
}

View File

@ -0,0 +1,72 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportStagingClosedTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.LazyClientStatsChangeApplication;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.state.LazyNettyClientLoginCommand;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 服务端处理上报的暂存关闭
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportStagingClosedTypeAdvanced extends AbstractHandleUdpReportStagingClosedTypeAdvanced<NettyProxyMsg> {
private final LazyClientStatsChangeApplication lazyClientStatsChangeApplication;
public ServerHandleUdpReportStagingClosedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
this.lazyClientStatsChangeApplication = lazyClientStatsChangeApplication;
}
/**
* 处理当前数据
*
* @param stagingClosedChannel 关闭暂存的通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel stagingClosedChannel, NettyProxyMsg msg) {
String appKey = ChannelAttributeKeyUtils.getAppKey(stagingClosedChannel);
String appSecret = ChannelAttributeKeyUtils.getAppSecret(stagingClosedChannel);
String originalIp = ChannelAttributeKeyUtils.getOriginalIp(stagingClosedChannel);
byte[] clientIdBytes = msg.getClientId();
// 获取所有通道
List<Channel> stagingOpenedClientChannel = ChannelContext.get(clientIdBytes);
if (stagingOpenedClientChannel != null) {
String clientId = new String(clientIdBytes);
// 存储当前客户端暂存关闭
LazyNettyClientLoginCommand lazyNettyClientLoginCommand = new LazyNettyClientLoginCommand();
lazyNettyClientLoginCommand.setClientId(clientId);
lazyNettyClientLoginCommand.setAppKey(appKey);
lazyNettyClientLoginCommand.setAppSecret(appSecret);
lazyNettyClientLoginCommand.setOriginalIp(originalIp);
lazyClientStatsChangeApplication.stagingClosed(lazyNettyClientLoginCommand);
ChannelContext.getChannels().forEach((existClientId, channels) -> {
for (Channel channel : channels) {
// 告诉他们 当前参数这个通道 暂存关闭了
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_STAGING_CLOSED_NOTIFICATION);
nettyMsg.setData((clientId
.getBytes(StandardCharsets.UTF_8)));
nettyMsg.setClientId((clientId
.getBytes(StandardCharsets.UTF_8)));
channel.writeAndFlush(nettyMsg);
}
});
}
}
}

View File

@ -0,0 +1,77 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.udp.server.AbstractHandleUdpReportStagingOpenedTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.LazyClientStatsChangeApplication;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.state.LazyNettyClientLoginCommand;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 服务端处理上报的暂存开启
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Component
public class ServerHandleUdpReportStagingOpenedTypeAdvanced extends AbstractHandleUdpReportStagingOpenedTypeAdvanced<NettyProxyMsg> {
private final LazyClientStatsChangeApplication lazyClientStatsChangeApplication;
public ServerHandleUdpReportStagingOpenedTypeAdvanced(LazyClientStatsChangeApplication lazyClientStatsChangeApplication) {
this.lazyClientStatsChangeApplication = lazyClientStatsChangeApplication;
}
/**
* 处理当前数据
*
* @param stagingOpenedChannel 开启暂存的通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel stagingOpenedChannel, NettyProxyMsg msg) {
// 获取所有通道
byte[] clientIdBytes = msg.getClientId();
String appKey = ChannelAttributeKeyUtils.getAppKey(stagingOpenedChannel);
String appSecret = ChannelAttributeKeyUtils.getAppSecret(stagingOpenedChannel);
String originalIp = ChannelAttributeKeyUtils.getOriginalIp(stagingOpenedChannel);
List<Channel> stagingOpenedClientChannel = ChannelContext.get(clientIdBytes);
// 存储当前客户端暂存关闭
String clientId = new String(clientIdBytes);
LazyNettyClientLoginCommand lazyNettyClientLoginCommand = new LazyNettyClientLoginCommand();
lazyNettyClientLoginCommand.setClientId(clientId);
lazyNettyClientLoginCommand.setAppKey(appKey);
lazyNettyClientLoginCommand.setAppSecret(appSecret);
lazyNettyClientLoginCommand.setOriginalIp(originalIp);
lazyNettyClientLoginCommand.setOnLineState(NettyClientStatus.OFF_LINE);
lazyClientStatsChangeApplication.stagingOpened(lazyNettyClientLoginCommand);
if (stagingOpenedClientChannel != null) {
ChannelContext.getChannels().forEach((existClientId, channels) -> {
for (Channel channel : channels) {
// 告诉他们 当前参数这个通道 暂存开启了
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_STAGING_OPENED_NOTIFICATION);
nettyMsg.setData((clientId
.getBytes(StandardCharsets.UTF_8)));
nettyMsg.setClientId((clientId
.getBytes(StandardCharsets.UTF_8)));
channel.writeAndFlush(nettyMsg);
}
});
}
}
}

View File

@ -0,0 +1,29 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.TransferDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.TransferEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.filter.DebugChannelInitializer;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler.NettyUdpClientPermeateServerRealHandler;
/**
* 客户端渗透服务端
*/
public class NettyUdpClientPermeateServerRealFilter extends DebugChannelInitializer<SocketChannel> {
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
*/
@Override
protected void initChannel0(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
// 解码、编码
pipeline.addLast(new TransferDecoder(Integer.MAX_VALUE, 1024 * 1024*10));
pipeline.addLast(new TransferEncoder());
pipeline.addLast(new NettyUdpClientPermeateServerRealHandler());
}
}

View File

@ -0,0 +1,55 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.NettyProxyMsgDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.NettyProxyMsgEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.filter.DebugChannelInitializer;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler.NettyUdpServerHandler;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* description
*
* @author 吴佳伟
* @date 2023/09/13 10:26
*/
@Component
public class NettyUdpServerFilter extends DebugChannelInitializer<SocketChannel> {
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList;
public NettyUdpServerFilter(List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
}
@Override
protected void initChannel0(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 以("\n")为结尾分割的 解码器
// 解码、编码
pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
pipeline.addLast(new NettyProxyMsgEncoder());
// ph.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// 解码和编码,应和客户端一致
//入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式
pipeline.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// 类型处理器适配器
ChannelTypeAdapter channelTypeAdapter = new ChannelTypeAdapter(handleChannelTypeAdvancedList);
pipeline.addLast("doHandler", new NettyUdpServerHandler(channelTypeAdapter));// 服务端业务逻辑
}
}

View File

@ -0,0 +1,37 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkPenetrationRealClient;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.filter.DebugChannelInitializer;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler.NettyUdpServerPermeateClientVisitorHandler;
public class NettyUdpServerPermeateClientVisitorFilter extends DebugChannelInitializer<SocketChannel> {
private final InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient;
private final ChannelFlowAdapter channelFlowAdapter;
public NettyUdpServerPermeateClientVisitorFilter(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient, ChannelFlowAdapter channelFlowAdapter) {
this.internalNetworkPenetrationRealClient = internalNetworkPenetrationRealClient;
this.channelFlowAdapter = channelFlowAdapter;
}
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
* @throws Exception is thrown if an error occurs. In that case it will be handled by
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
* the {@link Channel}.
*/
@Override
protected void initChannel0(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ChannelDuplexHandler());
pipeline.addLast(new NettyUdpServerPermeateClientVisitorHandler(internalNetworkPenetrationRealClient, channelFlowAdapter));
}
}

View File

@ -0,0 +1,54 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.TransferDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.TransferEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.filter.DebugChannelInitializer;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler.NettyUdpServerPermeateServerRealHandler;
@Slf4j
public class NettyUdpServerPermeateServerRealFilter extends DebugChannelInitializer<SocketChannel> {
private final InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer;
public NettyUdpServerPermeateServerRealFilter(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer) {
this.internalNetworkServerPermeateServerRealServer = internalNetworkServerPermeateServerRealServer;
}
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
*/
@Override
protected void initChannel0(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
Boolean isSsl = internalNetworkServerPermeateServerRealServer.getIsSsl();
if(isSsl!=null && isSsl) {
log.info("init channel0 ssl");
String targetIp = internalNetworkServerPermeateServerRealServer.getClientTargetIp();
Integer targetPort = internalNetworkServerPermeateServerRealServer.getClientTargetPort();
// 适配https
try {
SslContext sslContext = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
pipeline.addLast(sslContext.newHandler(ch.alloc()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 解码、编码
pipeline.addLast(new TransferDecoder(Integer.MAX_VALUE, 1024 * 1024*10));
pipeline.addLast(new TransferEncoder());
pipeline.addLast(new NettyUdpServerPermeateServerRealHandler());
}
}

View File

@ -0,0 +1,37 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.filter.DebugChannelInitializer;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler.NettyUdpServerPermeateServerVisitorHandler;
public class NettyUdpServerPermeateServerVisitorFilter extends DebugChannelInitializer<SocketChannel> {
private final InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer;
private final ChannelFlowAdapter channelFlowAdapter;
public NettyUdpServerPermeateServerVisitorFilter(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer, ChannelFlowAdapter channelFlowAdapter) {
this.internalNetworkServerPermeateServerRealServer = internalNetworkServerPermeateServerRealServer;
this.channelFlowAdapter = channelFlowAdapter;
}
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
* @throws Exception is thrown if an error occurs. In that case it will be handled by
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
* the {@link Channel}.
*/
@Override
protected void initChannel0(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ChannelDuplexHandler());
pipeline.addLast(new NettyUdpServerPermeateServerVisitorHandler(internalNetworkServerPermeateServerRealServer, channelFlowAdapter));
}
}

View File

@ -0,0 +1,537 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.handler.timeout.*;
import io.netty.util.concurrent.Future;
import io.netty.util.internal.ObjectUtil;
import java.util.concurrent.TimeUnit;
/**
* Raises a {@link ReadTimeoutException} when no data was read within a certain
* period of time.
*
* <pre>
* // The connection is closed when there is no inbound traffic
* // for 30 seconds.
*
* public class MyChannelInitializer extends {@link ChannelInitializer}&lt;{@link Channel}&gt; {
* public void initChannel({@link Channel} channel) {
* channel.pipeline().addLast("readTimeoutHandler", new {@link LazyUdpServerIdleStateHandler}(30));
* channel.pipeline().addLast("myHandler", new MyHandler());
* }
* }
*
* // Handler should handle the {@link ReadTimeoutException}.
* public class MyHandler extends {@link ChannelDuplexHandler} {
* {@code @Override}
* public void exceptionCaught({@link ChannelHandlerContext} ctx, {@link Throwable} cause)
* throws {@link Exception} {
* if (cause instanceof {@link ReadTimeoutException}) {
* // do something
* } else {
* super.exceptionCaught(ctx, cause);
* }
* }
* }
*
* {@link ServerBootstrap} bootstrap = ...;
* ...
* bootstrap.childHandler(new MyChannelInitializer());
* ...
* </pre>
*
* @see WriteTimeoutHandler
* @see IdleStateHandler
*/
public class LazyUdpServerIdleStateHandler extends ChannelDuplexHandler {
private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1);
private final boolean observeOutput;
private final long readerIdleTimeNanos;
private final long writerIdleTimeNanos;
private final long allIdleTimeNanos;
private Future<?> readerIdleTimeout;
private long lastReadTime;
private boolean firstReaderIdleEvent = true;
private Future<?> writerIdleTimeout;
private long lastWriteTime;
private boolean firstWriterIdleEvent = true;
private Future<?> allIdleTimeout;
private boolean firstAllIdleEvent = true;
// Not create a new ChannelFutureListener per write operation to reduce GC pressure.
private final ChannelFutureListener writeListener = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
lastWriteTime = ticksInNanos();
firstWriterIdleEvent = firstAllIdleEvent = true;
}
};
private byte state; // 0 - none, 1 - initialized, 2 - destroyed
private boolean reading;
private long lastChangeCheckTimeStamp;
private int lastMessageHashCode;
private long lastPendingWriteBytes;
private long lastFlushProgress;
/**
* Creates a new instance firing {@link IdleStateEvent}s.
*
* @param readerIdleTimeSeconds an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE}
* will be triggered when no read was performed for the specified
* period of time. Specify {@code 0} to disable.
* @param writerIdleTimeSeconds an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE}
* will be triggered when no write was performed for the specified
* period of time. Specify {@code 0} to disable.
* @param allIdleTimeSeconds an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE}
* will be triggered when neither read nor write was performed for
* the specified period of time. Specify {@code 0} to disable.
*/
public LazyUdpServerIdleStateHandler(
int readerIdleTimeSeconds,
int writerIdleTimeSeconds,
int allIdleTimeSeconds) {
this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds,
TimeUnit.SECONDS);
}
/**
* @see #LazyUdpServerIdleStateHandler(boolean, long, long, long, TimeUnit)
*/
public LazyUdpServerIdleStateHandler(
long readerIdleTime, long writerIdleTime, long allIdleTime,
TimeUnit unit) {
this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}
/**
* Creates a new instance firing {@link IdleStateEvent}s.
*
* @param observeOutput whether or not the consumption of {@code bytes} should be taken into
* consideration when assessing write idleness. The default is {@code false}.
* @param readerIdleTime an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE}
* will be triggered when no read was performed for the specified
* period of time. Specify {@code 0} to disable.
* @param writerIdleTime an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE}
* will be triggered when no write was performed for the specified
* period of time. Specify {@code 0} to disable.
* @param allIdleTime an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE}
* will be triggered when neither read nor write was performed for
* the specified period of time. Specify {@code 0} to disable.
* @param unit the {@link TimeUnit} of {@code readerIdleTime},
* {@code writeIdleTime}, and {@code allIdleTime}
*/
public LazyUdpServerIdleStateHandler(boolean observeOutput,
long readerIdleTime, long writerIdleTime, long allIdleTime,
TimeUnit unit) {
ObjectUtil.checkNotNull(unit, "unit");
this.observeOutput = observeOutput;
if (readerIdleTime <= 0) {
readerIdleTimeNanos = 0;
} else {
readerIdleTimeNanos = Math.max(unit.toNanos(readerIdleTime), MIN_TIMEOUT_NANOS);
}
if (writerIdleTime <= 0) {
writerIdleTimeNanos = 0;
} else {
writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS);
}
if (allIdleTime <= 0) {
allIdleTimeNanos = 0;
} else {
allIdleTimeNanos = Math.max(unit.toNanos(allIdleTime), MIN_TIMEOUT_NANOS);
}
}
/**
* Return the readerIdleTime that was given when instance this class in milliseconds.
*/
public long getReaderIdleTimeInMillis() {
return TimeUnit.NANOSECONDS.toMillis(readerIdleTimeNanos);
}
/**
* Return the writerIdleTime that was given when instance this class in milliseconds.
*/
public long getWriterIdleTimeInMillis() {
return TimeUnit.NANOSECONDS.toMillis(writerIdleTimeNanos);
}
/**
* Return the allIdleTime that was given when instance this class in milliseconds.
*/
public long getAllIdleTimeInMillis() {
return TimeUnit.NANOSECONDS.toMillis(allIdleTimeNanos);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isActive() && ctx.channel().isRegistered()) {
// channelActive() event has been fired already, which means this.channelActive() will
// not be invoked. We have to initialize here instead.
initialize(ctx);
} else {
// channelActive() event has not been fired yet. this.channelActive() will be invoked
// and initialization will occur there.
}
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
destroy();
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// Initialize early if channel is active already.
if (ctx.channel().isActive()) {
initialize(ctx);
}
super.channelRegistered(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// This method will be invoked only if this doHandler was added
// before channelActive() event is fired. If a user adds this doHandler
// after the channelActive() event, initialize() will be called by beforeAdd().
initialize(ctx);
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
destroy();
super.channelInactive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (readerIdleTimeNanos > 0 || allIdleTimeNanos > 0) {
reading = true;
firstReaderIdleEvent = firstAllIdleEvent = true;
}
ctx.fireChannelRead(msg);
System.out.println("channelRead");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
if ((readerIdleTimeNanos > 0 || allIdleTimeNanos > 0) && reading) {
lastReadTime = ticksInNanos();
reading = false;
}
ctx.fireChannelReadComplete();
System.out.println("channelReadComplete");
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
// Allow writing with void promise if doHandler is only configured for read timeout events.
if (writerIdleTimeNanos > 0 || allIdleTimeNanos > 0) {
ctx.write(msg, promise.unvoid()).addListener(writeListener);
} else {
ctx.write(msg, promise);
}
System.out.println("write");
}
private void initialize(ChannelHandlerContext ctx) {
// Avoid the case where destroy() is called before scheduling timeouts.
// See: https://github.com/netty/netty/issues/143
switch (state) {
case 1:
case 2:
return;
default:
break;
}
state = 1;
initOutputChanged(ctx);
lastReadTime = lastWriteTime = ticksInNanos();
if (readerIdleTimeNanos > 0) {
readerIdleTimeout = schedule(ctx, new ReaderIdleTimeoutTask(ctx),
readerIdleTimeNanos, TimeUnit.NANOSECONDS);
}
if (writerIdleTimeNanos > 0) {
writerIdleTimeout = schedule(ctx, new WriterIdleTimeoutTask(ctx),
writerIdleTimeNanos, TimeUnit.NANOSECONDS);
}
if (allIdleTimeNanos > 0) {
allIdleTimeout = schedule(ctx, new AllIdleTimeoutTask(ctx),
allIdleTimeNanos, TimeUnit.NANOSECONDS);
}
}
/**
* This method is visible for testing!
*/
long ticksInNanos() {
return System.nanoTime();
}
/**
* This method is visible for testing!
*/
Future<?> schedule(ChannelHandlerContext ctx, Runnable task, long delay, TimeUnit unit) {
return ctx.executor().schedule(task, delay, unit);
}
private void destroy() {
state = 2;
if (readerIdleTimeout != null) {
readerIdleTimeout.cancel(false);
readerIdleTimeout = null;
}
if (writerIdleTimeout != null) {
writerIdleTimeout.cancel(false);
writerIdleTimeout = null;
}
if (allIdleTimeout != null) {
allIdleTimeout.cancel(false);
allIdleTimeout = null;
}
}
/**
* Is called when an {@link IdleStateEvent} should be fired. This implementation calls
* {@link ChannelHandlerContext#fireUserEventTriggered(Object)}.
*/
protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
ctx.fireUserEventTriggered(evt);
}
/**
* Returns a {@link IdleStateEvent}.
*/
protected IdleStateEvent newIdleStateEvent(IdleState state, boolean first) {
switch (state) {
case ALL_IDLE:
return first ? IdleStateEvent.FIRST_ALL_IDLE_STATE_EVENT : IdleStateEvent.ALL_IDLE_STATE_EVENT;
case READER_IDLE:
return first ? IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT : IdleStateEvent.READER_IDLE_STATE_EVENT;
case WRITER_IDLE:
return first ? IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT : IdleStateEvent.WRITER_IDLE_STATE_EVENT;
default:
throw new IllegalArgumentException("Unhandled: state=" + state + ", first=" + first);
}
}
/**
* @see #hasOutputChanged(ChannelHandlerContext, boolean)
*/
private void initOutputChanged(ChannelHandlerContext ctx) {
if (observeOutput) {
Channel channel = ctx.channel();
Channel.Unsafe unsafe = channel.unsafe();
ChannelOutboundBuffer buf = unsafe.outboundBuffer();
if (buf != null) {
lastMessageHashCode = System.identityHashCode(buf.current());
lastPendingWriteBytes = buf.totalPendingWriteBytes();
lastFlushProgress = buf.currentProgress();
}
}
}
/**
* Returns {@code true} if and only if the {@link IdleStateHandler} was constructed
* with {@link #observeOutput} enabled and there has been an observed change in the
* {@link ChannelOutboundBuffer} between two consecutive calls of this method.
* <p>
* https://github.com/netty/netty/issues/6150
*/
private boolean hasOutputChanged(ChannelHandlerContext ctx, boolean first) {
if (observeOutput) {
// We can take this shortcut if the ChannelPromises that got passed into write()
// appear to complete. It indicates "change" on message level and we simply assume
// that there's change happening on byte level. If the user doesn't observe channel
// writability events then they'll eventually OOME and there's clearly a different
// problem and idleness is least of their concerns.
if (lastChangeCheckTimeStamp != lastWriteTime) {
lastChangeCheckTimeStamp = lastWriteTime;
// But this applies only if it's the non-first call.
if (!first) {
return true;
}
}
Channel channel = ctx.channel();
Channel.Unsafe unsafe = channel.unsafe();
ChannelOutboundBuffer buf = unsafe.outboundBuffer();
if (buf != null) {
int messageHashCode = System.identityHashCode(buf.current());
long pendingWriteBytes = buf.totalPendingWriteBytes();
if (messageHashCode != lastMessageHashCode || pendingWriteBytes != lastPendingWriteBytes) {
lastMessageHashCode = messageHashCode;
lastPendingWriteBytes = pendingWriteBytes;
if (!first) {
return true;
}
}
long flushProgress = buf.currentProgress();
if (flushProgress != lastFlushProgress) {
lastFlushProgress = flushProgress;
return !first;
}
}
}
return false;
}
private abstract static class AbstractIdleTask implements Runnable {
private final ChannelHandlerContext ctx;
AbstractIdleTask(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
@Override
public void run() {
if (!ctx.channel().isOpen()) {
return;
}
run(ctx);
}
protected abstract void run(ChannelHandlerContext ctx);
}
private final class ReaderIdleTimeoutTask extends AbstractIdleTask {
ReaderIdleTimeoutTask(ChannelHandlerContext ctx) {
super(ctx);
}
@Override
protected void run(ChannelHandlerContext ctx) {
long nextDelay = readerIdleTimeNanos;
if (!reading) {
nextDelay -= ticksInNanos() - lastReadTime;
}
if (nextDelay <= 0) {
// Reader is idle - set a new timeout and notify the callback.
readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);
boolean first = firstReaderIdleEvent;
firstReaderIdleEvent = false;
try {
IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first);
channelIdle(ctx, event);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
} else {
// Read occurred before the timeout - set a new timeout with shorter delay.
readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
}
}
}
private final class WriterIdleTimeoutTask extends AbstractIdleTask {
WriterIdleTimeoutTask(ChannelHandlerContext ctx) {
super(ctx);
}
@Override
protected void run(ChannelHandlerContext ctx) {
long lastWriteTime = LazyUdpServerIdleStateHandler.this.lastWriteTime;
long nextDelay = writerIdleTimeNanos - (ticksInNanos() - lastWriteTime);
if (nextDelay <= 0) {
// Writer is idle - set a new timeout and notify the callback.
writerIdleTimeout = schedule(ctx, this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);
boolean first = firstWriterIdleEvent;
firstWriterIdleEvent = false;
try {
if (hasOutputChanged(ctx, first)) {
return;
}
IdleStateEvent event = newIdleStateEvent(IdleState.WRITER_IDLE, first);
channelIdle(ctx, event);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
} else {
// Write occurred before the timeout - set a new timeout with shorter delay.
writerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
}
}
}
private final class AllIdleTimeoutTask extends AbstractIdleTask {
AllIdleTimeoutTask(ChannelHandlerContext ctx) {
super(ctx);
}
@Override
protected void run(ChannelHandlerContext ctx) {
long nextDelay = allIdleTimeNanos;
if (!reading) {
nextDelay -= ticksInNanos() - Math.max(lastReadTime, lastWriteTime);
}
if (nextDelay <= 0) {
// Both reader and writer are idle - set a new timeout and
// notify the callback.
allIdleTimeout = schedule(ctx, this, allIdleTimeNanos, TimeUnit.NANOSECONDS);
boolean first = firstAllIdleEvent;
firstAllIdleEvent = false;
try {
if (hasOutputChanged(ctx, first)) {
return;
}
IdleStateEvent event = newIdleStateEvent(IdleState.ALL_IDLE, first);
channelIdle(ctx, event);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
} else {
// Either read or write occurred before the timeout - set a new
// timeout with shorter delay.
allIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
}
}
}
}

View File

@ -0,0 +1,101 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyByteBuf;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.wu.framework.spring.utils.SpringContextHolder;
/**
* 客户端渗透服务端
*/
@Slf4j
public class NettyUdpClientPermeateServerRealHandler extends SimpleChannelInboundHandler<NettyByteBuf> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 根据访客ID 确认真实通道 读写打开
Channel channel = ctx.channel();
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
channel.config().setOption(ChannelOption.AUTO_READ, true);
super.channelActive(ctx);
}
@Override
public void channelRead0(ChannelHandlerContext ctx,NettyByteBuf nettyByteBuf) {
Channel channel = ctx.channel();
byte[] bytes = nettyByteBuf.getData();
log.debug("bytes.length:{}",bytes.length);
log.debug("【客户端渗透服务端】服务端真实服务数据:{}", new String(bytes));
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
// 消息下发到客户端
String clientId = ChannelAttributeKeyUtils.getClientId(channel);
Integer visitorPort = ChannelAttributeKeyUtils.getVisitorPort(channel);
if (nextChannel != null) {
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_SERVER_TRANSFER);
nettyMsg.setData(bytes);
nextChannel.writeAndFlush(nettyMsg);
ChannelFlowAdapter channelFlowAdapter = SpringContextHolder.getBean(ChannelFlowAdapter.class);
// 记录出口数据
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.OUT_FLOW)
.port(visitorPort)
.clientId(clientId)
.flow(nettyMsg.getData().length)
.build();
channelFlowAdapter.asyncHandler(channel, serverChannelFlow);
} else {
log.error("we can not find next channel for transfer with client permeate server user client_id:{} ", clientId);
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// 客户端真实通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
log.info("【客户端渗透服务端】服务端真实连接断开");
// 下发关闭这个客户端的访客通道
NettyProxyMsg closeVisitorMsg = new NettyProxyMsg();
closeVisitorMsg.setType(MessageType.DISTRIBUTE_CLIENT_PERMEATE_SERVER_TRANSFER_CLOSE);
nextChannel.writeAndFlush(closeVisitorMsg);
}
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
log.info("channelWritabilityChanged");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.info("exceptionCaught:{}", cause.getMessage());
super.exceptionCaught(ctx, cause);
}
}

View File

@ -0,0 +1,165 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyRealIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.wu.framework.core.utils.ObjectUtils;
/**
* description 服务端数据处理器
*
* @author 吴佳伟
* @date 2023/09/13 10:27
*/
@Slf4j
public class NettyUdpServerHandler extends SimpleChannelInboundHandler<NettyProxyMsg> {
private final ChannelTypeAdapter channelTypeAdapter;
/**
* 空闲次数
*/
private int idle_count = 1;
/**
* 传出数据延迟次数* 心跳时间作为关闭时间
*/
private int transfer_count = 1;
public NettyUdpServerHandler(ChannelTypeAdapter channelTypeAdapter) {
this.channelTypeAdapter = channelTypeAdapter;
}
/**
* Is called for each message of type {@link I}.
*
* @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
* belongs to
* @param nettyMsg the message to handle
* @throws Exception is thrown if an error occurred
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, NettyProxyMsg nettyMsg) throws Exception {
// 客户端读取到代理过来的数据了
Channel channel = ctx.channel();
byte type = nettyMsg.getType();
// byte[] data = nettyMsg.getData();
// log.info("客户端发送数据类型:{},发送数据:{}", type, new String(data));
channelTypeAdapter.handler(channel, nettyMsg);
}
/**
* 超时处理 * 如果5秒没有接受客户端的心跳就触发; * 如果超过两次,则直接关闭;
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
Channel channel = ctx.channel();
if (obj instanceof IdleStateEvent event) {
if (IdleState.READER_IDLE.equals(event.state())) { //如果读通道处于空闲状态,说明没有接收到心跳命令
String clientId = ChannelAttributeKeyUtils.getClientId(channel);
String visitorId = ChannelAttributeKeyUtils.getVisitorId(channel);
if (ObjectUtils.isEmpty(visitorId)) {
// 已经5秒没有接收到客户端{}的信息了
log.warn("I haven't received any information from client: {} with channel:{} for 5 seconds", clientId, channel.id().toString());
// 关闭这个不活跃的channel client:{}
log.warn("close this inactive channel client:{} with no visitor", clientId);
// 给所有客户端发送 这个客户端离线了
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setClientId(clientId);
nettyMsg.setType(MessageType.TCP_REPORT_CLIENT_DISCONNECTION);
channelTypeAdapter.handler(channel, nettyMsg);
channel.close();
} else {
// 访客通道数据 5*100秒后关闭
if (transfer_count > 100) {
log.warn("close client:{} visitor: [{}]'s connection", clientId, visitorId);
NettyCommunicationIdContext.clear(visitorId);
NettyRealIdContext.clear(visitorId);
// 关闭通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
Channel transferNextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
channel.close();
nextChannel.close();
transferNextChannel.close();
}
transfer_count++;
}
}
} else {
super.userEventTriggered(ctx, obj);
}
}
/**
* Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward
* to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
* <p>
* Sub-classes may override this method to change behavior.
*
* @param ctx
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
boolean open = channel.isOpen();
// 下发当前客户端通道断开连接
String clientId = ChannelAttributeKeyUtils.getClientId(channel);
String visitorId = ChannelAttributeKeyUtils.getVisitorId(channel);
if (!ObjectUtils.isEmpty(visitorId)) {
// 客户端:{},断开访客的连接:{}
log.warn("client: {} channel:{}, disconnect with visitorId:{}", clientId, channel.id().toString(), visitorId);
// 访客通道 关闭访客通道
NettyCommunicationIdContext.clear(visitorId);
// 关闭通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
Channel transferNextChannel = ChannelAttributeKeyUtils.getTransferNextChannel(channel);
channel.close();
nextChannel.close();
transferNextChannel.close();
super.channelInactive(ctx);
} else if (!ObjectUtils.isEmpty(clientId)) {
// 断开客户端的连接:{}
log.warn("Disconnect client:{}", clientId);
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.TCP_REPORT_CLIENT_DISCONNECTION);
nettyMsg.setClientId(clientId);
channelTypeAdapter.handler(channel, nettyMsg);
super.channelInactive(ctx);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// super.exceptionCaught(ctx, cause);
Channel channel = ctx.channel();
//……
if (channel.isActive()) ctx.close();
}
/**
* Calls {@link ChannelHandlerContext#fireChannelWritabilityChanged()} to forward
* to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
* <p>
* Sub-classes may override this method to change behavior.
*
* @param ctx
*/
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
log.info("netty server handler channel writability changed: {}", ctx.channel());
super.channelWritabilityChanged(ctx);
}
}

View File

@ -0,0 +1,205 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.*;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.wu.framework.core.utils.ObjectUtils;
import java.util.UUID;
@Slf4j
public class NettyUdpServerPermeateClientVisitorHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient;
private final ChannelFlowAdapter channelFlowAdapter;// 流量适配器
// private final NettyChannelPool nettyChannelPool = new DefaultNettyChannelPool(10);
public NettyUdpServerPermeateClientVisitorHandler(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient, ChannelFlowAdapter channelFlowAdapter) {
this.internalNetworkPenetrationRealClient = internalNetworkPenetrationRealClient;
this.channelFlowAdapter = channelFlowAdapter;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 访客连接上代理服务器了
Channel visitorChannel = ctx.channel();
// 先不读取访客数据
visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);
// 生成访客ID
String visitorId = UUID.randomUUID().toString();
String clientId = internalNetworkPenetrationRealClient.getClientId();
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
// 绑定访客真实通道
NettyRealIdContext.pushReal(visitorChannel, visitorId);
// 当前通道绑定访客ID
ChannelAttributeKeyUtils.buildVisitorId(visitorChannel, visitorId);
ChannelAttributeKeyUtils.buildClientId(visitorChannel, clientId);
NettyProxyMsg nettyProxyMsg = new NettyProxyMsg();
nettyProxyMsg.setType(MessageType.DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT);
nettyProxyMsg.setClientId(clientId);
nettyProxyMsg.setVisitorPort(visitorPort);
nettyProxyMsg.setClientTargetIp(clientTargetIp);
nettyProxyMsg.setClientTargetPort(clientTargetPort);
nettyProxyMsg.setVisitorId(visitorId);
// 判断是否有可用的通道 如果没有创建新的通道
// Channel transferChannel = nettyChannelPool.availableChannel(visitorId);
// if (transferChannel == null) {
// 客户端心跳通道
Channel clientChannel = ChannelContext.getLoadBalance(clientId);
if (clientChannel != null) {
log.info("通过客户端:{},获取通道而后创建连接", clientId);
clientChannel.writeAndFlush(nettyProxyMsg);
} else {
log.error("客户端:【{}】已经下线无法通过客户端ID获取客户端通道", clientId);
}
// }
// 等待访客ID传输到客户端后绑定客户端真实服务后开启
log.info("服务端访客端口连接成功了");
super.channelActive(ctx);
}
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) {
// 访客通道
Channel visitorChannel = ctx.channel();
String clientId = internalNetworkPenetrationRealClient.getClientId();
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
String visitorId = ChannelAttributeKeyUtils.getVisitorId(visitorChannel);
if (StringUtil.isNullOrEmpty(clientId)) {
return;
}
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
// 获取客户端通道,而后进行数据下发
log.debug("【服务端】访客端口成功接收数据:{}", new String(bytes));
// 使用访客的通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(visitorChannel);
// 绑定数据流量
ChannelAttributeKeyUtils.buildInFlow(nextChannel, bytes.length);
NettyProxyMsg nettyProxyMsg = new NettyProxyMsg();
nettyProxyMsg.setType(MessageType.DISTRIBUTE_CLIENT_TRANSFER);
nettyProxyMsg.setClientId(clientId);
nettyProxyMsg.setClientTargetIp(clientTargetIp);
nettyProxyMsg.setClientTargetPort(clientTargetPort);
nettyProxyMsg.setVisitorPort(visitorPort);
nettyProxyMsg.setVisitorId(visitorId);
nettyProxyMsg.setData(bytes);
nextChannel.writeAndFlush(nettyProxyMsg);
// 处理访客流量
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.channelFlowEnum(ChannelFlowEnum.IN_FLOW)
.port(visitorPort)
.clientId(clientId)
.flow(bytes.length)
.build();
channelFlowAdapter.asyncHandler(visitorChannel, serverChannelFlow);
log.debug("服务端访客端口成功发送数据了");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
if (StringUtil.isNullOrEmpty(visitorId)) {
super.channelInactive(ctx);
return;
}
// 通信通道自动读写打开 ,然后关闭通信通道
// Channel visitorChannel = NettyCommunicationIdContext.getVisitorChannel(visitorId);
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null && nextChannel.isActive()) {
nextChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 通知服务端 关闭访问通道、真实通道
NettyProxyMsg myMsg = new NettyProxyMsg();
myMsg.setType(MessageType.DISTRIBUTE_SERVER_PERMEATE_CLIENT_REAL_CLOSE_VISITOR);
myMsg.setVisitorId(visitorId);
nextChannel.writeAndFlush(myMsg);
}
// 关闭 访客通信通道、访客真实通道
NettyRealIdContext.clear(visitorId);
NettyCommunicationIdContext.clear(visitorId);
log.warn("服务端访客端口断开连接");
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
// 获取访客的传输通道
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
if(ObjectUtils.isEmpty(visitorId)) {
super.channelWritabilityChanged(ctx);
return;
}
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
log.debug("visitorId:{} transfer AUTO_READ:{} ",visitorId,ctx.channel().isWritable());
nextChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
}
// Channel visitorChannel = ctx.channel();
// String vid = visitorChannel.attr(Constant.VID).get();
// if (StringUtil.isNullOrEmpty(vid)) {
// super.channelWritabilityChanged(ctx);
// return;
// }
// Channel clientChannel = Constant.vcc.get(vid);
// if (clientChannel != null) {
// clientChannel.config().setOption(ChannelOption.AUTO_READ, visitorChannel.isWritable());
// }
if (ctx.channel().isWritable()) {
log.debug("Channel is writable again");
// 恢复之前暂停的操作,如写入数据
} else {
log.debug("Channel is not writable");
// 暂停写入操作,等待可写状态
}
log.info("visitorId:{} channelWritabilityChanged!",visitorId);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.error("exceptionCaught");
Channel channel = ctx.channel();
String clientId = ChannelAttributeKeyUtils.getClientId(channel);
String visitorId = ChannelAttributeKeyUtils.getVisitorId(channel);
// 使用通信通道 下发关闭访客
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
// 下发关闭访客
NettyProxyMsg closeRealClient = new NettyProxyMsg();
closeRealClient.setType(MessageType.DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT_AUTO_READ);
closeRealClient.setClientId(clientId);
closeRealClient.setVisitorId(visitorId);
nextChannel.writeAndFlush(closeRealClient);
}
ctx.close();
}
}

View File

@ -0,0 +1,77 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyByteBuf;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
/**
* 来自客户端 真实服务器返回的数据请求
*/
@Slf4j
public class NettyUdpServerPermeateServerRealHandler extends SimpleChannelInboundHandler<NettyByteBuf> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 根据访客ID 确认真实通道 读写打开
Channel channel = ctx.channel();
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
channel.config().setOption(ChannelOption.AUTO_READ, true);
super.channelActive(ctx);
}
@Override
public void channelRead0(ChannelHandlerContext ctx,NettyByteBuf nettyByteBuf) {
Channel channel = ctx.channel();
byte[] bytes = nettyByteBuf.getData();
log.debug("bytes.length:{}",bytes.length);
log.debug("接收客户端真实服务数据:{}", new String(bytes));
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
// 将二进制数组转换成 ByteBuf 然后进行发送
ByteBuf realBuf = nextChannel.config().getAllocator().buffer(bytes.length);
realBuf.writeBytes(bytes);
nextChannel.writeAndFlush(realBuf);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// 客户端真实通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
// 上报关闭这个客户端的访客通道
nextChannel.close();
}
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
// 获取访客的传输通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
log.debug("transfer AUTO_READ:{} ",ctx.channel().isWritable());
nextChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
}
}

View File

@ -0,0 +1,137 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket.NettyUdpServerPermeateServerConnectRealSocket;
import java.util.UUID;
@Slf4j
public class NettyUdpServerPermeateServerVisitorHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer;
private final ChannelFlowAdapter channelFlowAdapter;// 流量适配器
// private final NettyChannelPool nettyChannelPool = new DefaultNettyChannelPool(10);
public NettyUdpServerPermeateServerVisitorHandler(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer, ChannelFlowAdapter channelFlowAdapter) {
this.internalNetworkServerPermeateServerRealServer = internalNetworkServerPermeateServerRealServer;
this.channelFlowAdapter = channelFlowAdapter;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 访客连接上代理服务器了
Channel visitorChannel = ctx.channel();
// 先不读取访客数据
visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);
// 生成访客ID
String visitorId = UUID.randomUUID().toString();
// 当前通道绑定访客ID
ChannelAttributeKeyUtils.buildVisitorId(visitorChannel, visitorId);
// 判断是否有可用的通道 如果没有创建新的通道
log.info("开始准备绑定渗透真实通道: {}", internalNetworkServerPermeateServerRealServer.getVisitorPort());
// 创建这是客户端通道池
NettyUdpServerPermeateServerConnectRealSocket.buildRealServer(internalNetworkServerPermeateServerRealServer, visitorChannel, visitorId);
log.info("内网渗透 服务端访客端口连接成功了");
super.channelActive(ctx);
}
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) {
// 访客通道
Channel visitorChannel = ctx.channel();
Integer visitorPort = internalNetworkServerPermeateServerRealServer.getVisitorPort();
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
// 获取客户端通道,而后进行数据下发
log.debug("【服务端】访客端口成功接收数据:{}", new String(bytes));
// 使用访客的通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(visitorChannel);
// 下一个通道开启自动读写
log.info("write data to channelId:{}",nextChannel.id().asLongText());
nextChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 绑定数据流量
ChannelAttributeKeyUtils.buildInFlow(nextChannel, bytes.length);
// 将二进制数组转换成 ByteBuf 然后进行发送
ByteBuf visitorBuf = visitorChannel.config().getAllocator().buffer(bytes.length);
visitorBuf.writeBytes(bytes);
nextChannel.writeAndFlush(visitorBuf);
// 处理访客流量
ServerChannelFlow serverChannelFlow = ServerChannelFlow
.builder()
.clientId("server_id")
.channelFlowEnum(ChannelFlowEnum.IN_FLOW)
.port(visitorPort)
.flow(bytes.length)
.build();
channelFlowAdapter.asyncHandler(visitorChannel, serverChannelFlow);
log.debug("服务端访客端口成功发送数据了");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// 通信通道自动读写打开 ,然后关闭通信通道
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null && nextChannel.isActive()) {
nextChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 通知服务端 关闭访问通道、真实通道
nextChannel.close();
}
log.warn("服务端访客端口断开连接");
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
log.debug("transfer AUTO_READ:{} ", ctx.channel().isWritable());
nextChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
}
if (ctx.channel().isWritable()) {
log.debug("Channel is writable again");
// 恢复之前暂停的操作,如写入数据
} else {
log.debug("Channel is not writable");
// 暂停写入操作,等待可写状态
}
log.info("visitorId:{} channelWritabilityChanged!");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.error("exceptionCaught");
// 使用通信通道 下发关闭访客
Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
if (nextChannel != null) {
// 下发关闭访客
nextChannel.close();
}
ctx.close();
}
}

View File

@ -0,0 +1,90 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.MessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpClientPermeateServerRealFilter;
import java.util.concurrent.TimeUnit;
/**
* 客户端渗透服务端 连接真实通道
*/
@Slf4j
public class NettyUdpClientPermeateServerConnectRealSocket {
private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
/**
* 连接真实服务
*/
public static void buildNewRealServer(
String visitorId, int visitorPort, String targetIp, int targetPort, Channel transferChannel) {
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
// 设置读缓冲区为2M
.option(ChannelOption.SO_RCVBUF, 2048 * 1024)
// 设置写缓冲区为1M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024)
// .option(ChannelOption.TCP_NODELAY, false)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
// .option(ChannelOption.SO_BACKLOG, 128)//务端接受连接的队列长度 默认128
// .option(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认AdaptiveRecvByteBufAllocator.DEFAULT
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))
.handler(new NettyUdpClientPermeateServerRealFilter())
;
bootstrap
.connect(targetIp, targetPort)
.sync()
.addListener((ChannelFutureListener) channelFuture -> {
if (channelFuture.isSuccess()) {
// 客户端链接真实服务成功 设置自动读写false 等待访客连接成功后设置成true
Channel realChannel = channelFuture.channel();
log.info("服务端内网渗透通过,绑定本地服务,IP:{},端口:{} channelID:{} 新建通道成功", targetIp, targetPort,realChannel.id().asLongText());
ChannelAttributeKeyUtils.buildVisitorPort(realChannel, visitorPort);
// 缓存当前端口对应的通道、通道池
ChannelAttributeKeyUtils.buildNextChannel(realChannel, transferChannel);
ChannelAttributeKeyUtils.buildNextChannel(transferChannel, realChannel);
ChannelAttributeKeyUtils.buildVisitorId(realChannel, visitorId);
String clientId = ChannelAttributeKeyUtils.getClientId(transferChannel);
ChannelAttributeKeyUtils.buildClientId(realChannel, clientId);
NettyProxyMsg myMsg = new NettyProxyMsg();
myMsg.setType(MessageType.DISTRIBUTE_CLIENT_TRANSFER_SERVER_PERMEATE_CHANNEL_CONNECTION_SUCCESSFUL);
myMsg.setVisitorId(visitorId);
myMsg.setVisitorPort(visitorPort);
myMsg.setClientTargetIp(targetIp);
myMsg.setClientTargetPort(targetPort);
transferChannel.writeAndFlush(myMsg);
} else {
log.error("服务端内网渗透 无法连接当前网络内的目标IP【{}】,目标端口:【{}】", targetIp, targetPort);
eventLoopGroup.schedule(() -> {
buildNewRealServer(visitorId, visitorPort, targetIp, targetPort, transferChannel);
}, 2, TimeUnit.SECONDS);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,242 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkPenetrationRealClient;
import org.framework.lazy.cloud.network.heartbeat.common.NettyClientVisitorContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyVisitorPortContext;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.socket.PermeateVisitorSocket;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpServerPermeateClientVisitorFilter;
/**
* 内网穿透服务端访客通道
*
* @see NettyVisitorPortContext
* @see NettyClientVisitorContext
*/
@Slf4j
public class NettyUdpServerPermeateClientVisitorSocket implements PermeateVisitorSocket {
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private final NettyUdpServerPermeateClientVisitorFilter nettyUdpServerPermeateClientVisitorFilter;
@Getter
private final String clientId;
@Getter
private final int visitorPort;
public NettyUdpServerPermeateClientVisitorSocket(NettyUdpServerPermeateClientVisitorFilter nettyUdpServerPermeateClientVisitorFilter, String clientId, int visitorPort) {
this.nettyUdpServerPermeateClientVisitorFilter = nettyUdpServerPermeateClientVisitorFilter;
this.clientId = clientId;
this.visitorPort = visitorPort;
}
/**
* 启动服务代理
*
* @throws Exception
*/
@Override
public void start() {
Channel visitor = NettyVisitorPortContext.getVisitorChannel(visitorPort);
if (visitor == null) {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// 设置读缓冲区为2M
.childOption(ChannelOption.SO_RCVBUF, 2048 * 1024)
// 设置写缓冲区为1M
.childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
// .childOption(ChannelOption.TCP_NODELAY, false)
.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
// .childOption(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认 AdaptiveRecvByteBufAllocator.DEFAULT
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))
.childHandler(nettyUdpServerPermeateClientVisitorFilter);
try {
bootstrap.bind(visitorPort).sync().addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
// 这里时异步处理
log.info("客户端:[{}]访客端口:[{}] 开启", clientId, visitorPort);
NettyVisitorPortContext.pushVisitorChannel(visitorPort, future.channel());
} else {
log.error("客户端:[{}]访客端口:[{}]绑定失败", clientId, visitorPort);
}
});
NettyClientVisitorContext.pushVisitorSocket(clientId, this);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
log.warn("客户端:[{}]访客端口:[{}] 重复启动", clientId, visitorPort);
}
}
@Override
public void close() {
if (!bossGroup.isShutdown()) {
bossGroup.shutdownGracefully();
}
if (!workerGroup.isShutdown()) {
workerGroup.shutdownGracefully();
}
Channel visitor = NettyVisitorPortContext.getVisitorChannel(visitorPort);
if (visitor != null) {
// close channel
visitor.close();
// remove visitor
NettyVisitorPortContext.removeVisitorChannel(visitorPort);
log.warn("关闭客户端 :【{}】 访客户端口:【{}】", clientId, visitorPort);
} else {
log.warn("关闭访客端口失败 未找到客户端通道 客户端 :【{}】 访客户端口:【{}】", clientId, visitorPort);
}
}
public static final class NettyVisitorSocketBuilder {
/**
* 客户端ID
*/
private String clientId;
/**
* 客户端目标地址
*/
private String clientTargetIp;
/**
* 客户端目标端口
*/
private Integer clientTargetPort;
/**
* 访问端口
*/
private Integer visitorPort;
/**
* 访客ID
*/
private String visitorId;
/**
* 流量适配器
*/
private ChannelFlowAdapter channelFlowAdapter;
public static NettyVisitorSocketBuilder builder() {
return new NettyVisitorSocketBuilder();
}
/**
* 填充客户端
*
* @param clientId 客户端
* @return 返回当前对象
*/
public NettyVisitorSocketBuilder builderClientId(String clientId) {
this.clientId = clientId;
return this;
}
/**
* 绑定客户端目标IP
*
* @param clientTargetIp 客户端目标IP
* @return 当前对象
*/
public NettyVisitorSocketBuilder builderClientTargetIp(String clientTargetIp) {
this.clientTargetIp = clientTargetIp;
return this;
}
/**
* 绑定客户端目标端口
*
* @param clientTargetPort 客户端目标端口
* @return 当前对象
*/
public NettyVisitorSocketBuilder builderClientTargetPort(Integer clientTargetPort) {
this.clientTargetPort = clientTargetPort;
return this;
}
/**
* 绑定访客端口
*
* @param visitorPort 访客端口
* @return 当前对象
*/
public NettyVisitorSocketBuilder builderVisitorPort(Integer visitorPort) {
this.visitorPort = visitorPort;
return this;
}
/**
* 绑定流量适配器
*
* @param channelFlowAdapter 流量适配器
* @return 当前对象
*/
public NettyVisitorSocketBuilder builderChannelFlowAdapter(ChannelFlowAdapter channelFlowAdapter) {
this.channelFlowAdapter = channelFlowAdapter;
return this;
}
/**
* 绑定访客ID
*
* @param visitorId 访客ID
* @return 当前对象
*/
public NettyVisitorSocketBuilder builderVisitorId(String visitorId) {
this.visitorId = visitorId;
return this;
}
public NettyUdpServerPermeateClientVisitorSocket build() {
if (clientId == null) {
throw new IllegalArgumentException("clientId must not null");
}
if (clientTargetIp == null) {
throw new IllegalArgumentException("clientTargetIp must not null");
}
if (clientTargetPort == null) {
throw new IllegalArgumentException("clientTargetPort must not null");
}
if (visitorPort == null) {
throw new IllegalArgumentException("visitorPort must not null");
}
InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient = InternalNetworkPenetrationRealClient
.builder()
.clientId(clientId)
.clientTargetIp(clientTargetIp)
.clientTargetPort(clientTargetPort)
.visitorPort(visitorPort)
.visitorId(visitorId).build();
NettyUdpServerPermeateClientVisitorFilter nettyUdpServerPermeateClientVisitorFilter = new NettyUdpServerPermeateClientVisitorFilter(internalNetworkPenetrationRealClient, channelFlowAdapter);
return new NettyUdpServerPermeateClientVisitorSocket(nettyUdpServerPermeateClientVisitorFilter, clientId, visitorPort);
}
}
}

View File

@ -0,0 +1,92 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpServerPermeateServerRealFilter;
import java.util.concurrent.TimeUnit;
/**
* 服务端渗透服务端 连接真实通道
*/
@Slf4j
public class NettyUdpServerPermeateServerConnectRealSocket {
private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
/**
* 连接真实服务
*
* @param internalNetworkServerPermeateServerRealServer 访客信息
*/
public static void buildRealServer(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer, Channel visitorChannel , String visitorId) {
buildNewRealServer(internalNetworkServerPermeateServerRealServer,visitorChannel,visitorId);
}
/**
* @param internalNetworkServerPermeateServerRealServer 访客信息
* @param visitorChannel
* @param visitorId
*/
private static void buildNewRealServer(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer,
Channel visitorChannel, String visitorId) {
try {
String clientTargetIp = internalNetworkServerPermeateServerRealServer.getClientTargetIp();
Integer clientTargetPort = internalNetworkServerPermeateServerRealServer.getClientTargetPort();
Integer visitorPort = internalNetworkServerPermeateServerRealServer.getVisitorPort();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
// 设置读缓冲区为2M
.option(ChannelOption.SO_RCVBUF, 2048 * 1024)
// 设置写缓冲区为1M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024)
// .option(ChannelOption.TCP_NODELAY, false)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
// .option(ChannelOption.SO_BACKLOG, 128)//务端接受连接的队列长度 默认128
// .option(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认AdaptiveRecvByteBufAllocator.DEFAULT
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))
.handler(new NettyUdpServerPermeateServerRealFilter(internalNetworkServerPermeateServerRealServer))
;
bootstrap
.connect(clientTargetIp, clientTargetPort)
.sync()
.addListener((ChannelFutureListener) channelFuture -> {
if (channelFuture.isSuccess()) {
// 客户端链接真实服务成功 设置自动读写false 等待访客连接成功后设置成true
Channel realChannel = channelFuture.channel();
realChannel.config().setOption(ChannelOption.AUTO_READ, false);
log.info("服务端内网渗透通过,绑定本地服务,IP:{},端口:{} channelID:{} 新建通道成功", clientTargetIp, clientTargetPort,realChannel.id().asLongText());
ChannelAttributeKeyUtils.buildVisitorPort(realChannel, visitorPort);
// 缓存当前端口对应的通道、通道池
ChannelAttributeKeyUtils.buildNextChannel(realChannel, visitorChannel);
ChannelAttributeKeyUtils.buildNextChannel(visitorChannel, realChannel);
ChannelAttributeKeyUtils.buildVisitorId(realChannel, visitorId);
visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);
} else {
log.error("服务端内网渗透 无法连接当前网络内的目标IP【{}】,目标端口:【{}】", clientTargetIp, clientTargetPort);
eventLoopGroup.schedule(() -> {
buildNewRealServer(internalNetworkServerPermeateServerRealServer, visitorChannel, visitorId);
}, 2, TimeUnit.SECONDS);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,218 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.NettyServerPermeateServerVisitorContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyVisitorPortContext;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpServerPermeateServerVisitorFilter;
import java.io.IOException;
/**
* 服务端渗透服务端 访客端口
*/
@Slf4j
public class NettyUdpServerPermeateServerConnectVisitorSocket {
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private final NettyUdpServerPermeateServerVisitorFilter nettyUdpServerPermeateServerVisitorFilter;
@Getter
private final int visitorPort;
public NettyUdpServerPermeateServerConnectVisitorSocket(NettyUdpServerPermeateServerVisitorFilter nettyUdpServerPermeateServerVisitorFilter,
int visitorPort) {
this.nettyUdpServerPermeateServerVisitorFilter = nettyUdpServerPermeateServerVisitorFilter;
this.visitorPort = visitorPort;
}
/**
* 启动服务代理
*
* @throws Exception
*/
public void start() throws Exception {
NettyUdpServerPermeateServerConnectVisitorSocket nettyUdpServerPermeateServerConnectVisitorSocket = NettyServerPermeateServerVisitorContext.getServerPermeateServerVisitorSocket(visitorPort);
if (nettyUdpServerPermeateServerConnectVisitorSocket == null) {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// 设置读缓冲区为2M
.childOption(ChannelOption.SO_RCVBUF, 2048 * 1024)
// 设置写缓冲区为1M
.childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
// .childOption(ChannelOption.TCP_NODELAY, false)
.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
// .childOption(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认 AdaptiveRecvByteBufAllocator.DEFAULT
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))
.childHandler(nettyUdpServerPermeateServerVisitorFilter);
ChannelFuture sync = bootstrap.bind(visitorPort).sync();
sync.addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
// 这里时异步处理
log.info("服务端渗透服务端:[{}] 开启", visitorPort);
} else {
log.error("服务端渗透服务端:[{}] 开启失败", visitorPort);
}
});
NettyServerPermeateServerVisitorContext.pushServerPermeateServerVisitorSocket(visitorPort,this);
} else {
log.warn("内网渗透服务端端口:[{}] 重复启动", visitorPort);
}
}
public void close() throws IOException, InterruptedException {
if (!bossGroup.isShutdown()) {
bossGroup.shutdownGracefully();
}
if (!workerGroup.isShutdown()) {
workerGroup.shutdownGracefully();
}
Channel visitor = NettyVisitorPortContext.getVisitorChannel(visitorPort);
if (visitor != null) {
// close channel
visitor.close();
NettyServerPermeateServerVisitorContext.removeServerPermeateServerVisitorSockets(visitorPort);
// log.warn("关闭客户端 :【{}】 访客户端口:【{}】", clientId, visitorPort);
} else {
log.warn("关闭内网渗透端口失败 渗透端口:【{}】", visitorPort);
}
}
public static final class NettyPermeateVisitorSocketBuilder {
/**
* 客户端目标地址
*/
private String clientTargetIp;
/**
* 客户端目标端口
*/
private Integer clientTargetPort;
/**
* 访问端口
*/
private Integer permeateVisitorPort;
/**
* 是否是ssl
*/
private Boolean isSsl;
/**
* 流量适配器
*/
private ChannelFlowAdapter channelFlowAdapter;
public static NettyPermeateVisitorSocketBuilder builder() {
return new NettyPermeateVisitorSocketBuilder();
}
/**
* 绑定客户端目标IP
*
* @param clientTargetIp 客户端目标IP
* @return 当前对象
*/
public NettyPermeateVisitorSocketBuilder builderClientTargetIp(String clientTargetIp) {
this.clientTargetIp = clientTargetIp;
return this;
}
/**
* 绑定客户端目标端口
*
* @param clientTargetPort 客户端目标端口
* @return 当前对象
*/
public NettyPermeateVisitorSocketBuilder builderClientTargetPort(Integer clientTargetPort) {
this.clientTargetPort = clientTargetPort;
return this;
}
/**
* 绑定访客端口
*
* @param permeateVisitorPort 访客端口
* @return 当前对象
*/
public NettyPermeateVisitorSocketBuilder builderVisitorPort(Integer permeateVisitorPort) {
this.permeateVisitorPort = permeateVisitorPort;
return this;
}
/**
* 绑定流量适配器
*
* @param channelFlowAdapter 流量适配器
* @return 当前对象
*/
public NettyPermeateVisitorSocketBuilder builderChannelFlowAdapter(ChannelFlowAdapter channelFlowAdapter) {
this.channelFlowAdapter = channelFlowAdapter;
return this;
}
/**
* 是否是ssl
*
* @param isSsl 是否是ssl
* @return 当前对象
*/
public NettyPermeateVisitorSocketBuilder builderIsSsl(Boolean isSsl) {
this.isSsl = isSsl;
return this;
}
public NettyUdpServerPermeateServerConnectVisitorSocket build() {
if (clientTargetIp == null) {
throw new IllegalArgumentException("clientTargetIp must not null");
}
if (clientTargetPort == null) {
throw new IllegalArgumentException("clientTargetPort must not null");
}
if (permeateVisitorPort == null) {
throw new IllegalArgumentException("visitorPort must not null");
}
InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer = InternalNetworkServerPermeateServerRealServer
.builder()
.clientTargetIp(clientTargetIp)
.clientTargetPort(clientTargetPort)
.visitorPort(permeateVisitorPort)
.isSsl(isSsl)
.build();
NettyUdpServerPermeateServerVisitorFilter nettyUdpServerPermeateServerVisitorFilter = new NettyUdpServerPermeateServerVisitorFilter(internalNetworkServerPermeateServerRealServer, channelFlowAdapter);
return new NettyUdpServerPermeateServerConnectVisitorSocket(nettyUdpServerPermeateServerVisitorFilter, permeateVisitorPort);
}
}
}

View File

@ -1,4 +0,0 @@
package org.framework.lazy.cloud.network.heartbeat.server.netty.udp;
public class xx {
}

View File

@ -59,7 +59,7 @@ public class LazyNettyClientBlacklistApplicationImpl implements LazyNettyClientB
// 模拟客户端发送下线通知
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setClientId(clientId);
nettyMsg.setType(MessageType.REPORT_CLIENT_DISCONNECTION);
nettyMsg.setType(MessageType.TCP_REPORT_CLIENT_DISCONNECTION);
clientChannel.writeAndFlush(nettyMsg);
}

View File

@ -1,7 +1,7 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.framework.lazy.cloud.network.heartbeat.server.EnableHeartbeatServerAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.server.config.HeartbeatServerConfiguration,\
org.framework.lazy.cloud.network.heartbeat.server.config.ServerAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.server.init.InitServerSocket,\
org.framework.lazy.cloud.network.heartbeat.server.init.InitClusterNode,\
org.framework.lazy.cloud.network.heartbeat.server.config.ServerFlowConfiguration,\

View File

@ -1,5 +1,5 @@
org.framework.lazy.cloud.network.heartbeat.server.EnableHeartbeatServerAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.server.config.HeartbeatServerConfiguration
org.framework.lazy.cloud.network.heartbeat.server.config.ServerAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.server.init.InitServerSocket
org.framework.lazy.cloud.network.heartbeat.server.init.InitClusterNode
org.framework.lazy.cloud.network.heartbeat.server.config.ServerFlowConfiguration