【fix】 添加协议解析处理

This commit is contained in:
wujiawei
2025-03-21 20:57:44 +08:00
parent cf9438a7da
commit 3321e0dd7b
41 changed files with 2162 additions and 23 deletions

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns;
package org.framework.lazy.cloud.network.heartbeat.protocol;
import org.springframework.context.annotation.ComponentScan;
import org.wu.framework.lazy.orm.core.stereotype.LazyScan;
@ -7,6 +7,6 @@ import org.wu.framework.lazy.orm.core.stereotype.LazyScan;
"org.framework.lazy.cloud.network.heartbeat.dns.standalone.infrastructure.entity",
"org.framework.lazy.cloud.network.heartbeat.dns.cluster.infrastructure.entity"
})
@ComponentScan(basePackages = "org.framework.lazy.cloud.network.heartbeat.dns")
@ComponentScan(basePackages = "org.framework.lazy.cloud.network.heartbeat.protocol")
public class EnableDnsAutoConfiguration {
}

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns.config;
package org.framework.lazy.cloud.network.heartbeat.protocol.config;
import org.springframework.beans.factory.config.BeanDefinition;

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns.config;
package org.framework.lazy.cloud.network.heartbeat.protocol.config;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.flow.HandleChannelFlowAdvanced;

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns.context;
package org.framework.lazy.cloud.network.heartbeat.protocol.context;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.context.SocketApplicationListener;

View File

@ -1,8 +1,8 @@
package org.framework.lazy.cloud.network.heartbeat.dns.init;
package org.framework.lazy.cloud.network.heartbeat.protocol.init;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.dns.context.NettyDnsSocketApplicationListener;
import org.framework.lazy.cloud.network.heartbeat.protocol.context.NettyDnsSocketApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

View File

@ -1,6 +1,6 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.framework.lazy.cloud.network.heartbeat.dns.EnableDnsAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.dns.config.DnsAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.dns.init.InitDnsSocket,\
org.framework.lazy.cloud.network.heartbeat.dns.config.DnsFlowConfiguration
org.framework.lazy.cloud.network.heartbeat.protocol.EnableProtocolProxyAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.protocol.config.ProtocolProxyAutoConfiguration,\
org.framework.lazy.cloud.network.heartbeat.protocol.init.InitProtocolProxySocket,\
org.framework.lazy.cloud.network.heartbeat.protocol.config.ProtocolProxyFlowConfiguration

View File

@ -1,4 +1,4 @@
org.framework.lazy.cloud.network.heartbeat.dns.EnableDnsAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.dns.config.DnsAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.dns.init.InitDnsSocket
org.framework.lazy.cloud.network.heartbeat.dns.config.DnsFlowConfiguration
org.framework.lazy.cloud.network.heartbeat.protocol.EnableProtocolProxyAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.protocol.config.ProtocolProxyAutoConfiguration
org.framework.lazy.cloud.network.heartbeat.protocol.init.InitProtocolProxySocket
org.framework.lazy.cloud.network.heartbeat.protocol.config.ProtocolProxyFlowConfiguration

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns;
package org.framework.lazy.cloud.network.heartbeat.protocol;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns;
package org.framework.lazy.cloud.network.heartbeat.protocol;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
@ -62,6 +62,7 @@ public class DnsServerHandler extends SimpleChannelInboundHandler<DatagramDnsQue
response.addRecord(DnsSection.ANSWER, new DefaultDnsRawRecord(
domain, DnsRecordType.A, 3600, Unpooled.wrappedBuffer(address.getAddress())));
}
// log.info("response:{}",response.toString());
ctx.writeAndFlush(response);
} catch (Exception e) {
e.printStackTrace();

View File

@ -0,0 +1,146 @@
package org.framework.lazy.cloud.network.heartbeat.protocol;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.URI;
public class HttpProxyServer {
private static final int PORT = 8080;
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new HttpClientCodec(),
new HttpObjectAggregator(1048576),
new HttpProxyServerHandler()
);
}
});
ChannelFuture f = b.bind(PORT).sync();
System.out.println("Proxy server started and listening on port " + PORT);
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static class HttpProxyServerHandler extends ChannelInboundHandlerAdapter {
private Channel outboundChannel;
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
FullHttpRequest request = (FullHttpRequest) msg;
URI uri = new URI(request.uri());
String host = uri.getHost();
int port = uri.getPort();
if (port == -1) {
port = 80;
}
Bootstrap b = new Bootstrap();
b.group(ctx.channel().eventLoop())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new HttpClientCodec(),
new HttpObjectAggregator(1048576),
new ProxyBackendHandler(ctx.channel())
);
}
});
ChannelFuture f = b.connect(host, port);
outboundChannel = f.channel();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
// 连接成功,将客户端请求转发到目标服务器
outboundChannel.writeAndFlush(request.retain());
} else {
// 连接失败,关闭客户端通道
ctx.channel().close();
}
}
});
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (outboundChannel != null) {
closeOnFlush(outboundChannel);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
private static class ProxyBackendHandler extends ChannelInboundHandlerAdapter {
private final Channel inboundChannel;
ProxyBackendHandler(Channel inboundChannel) {
this.inboundChannel = inboundChannel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 将目标服务器的响应转发给客户端
inboundChannel.writeAndFlush(msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
closeOnFlush(inboundChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
}

View File

@ -0,0 +1,312 @@
package org.framework.lazy.cloud.network.heartbeat.protocol;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
import java.net.URI;
public class MultiProtocolProxyServer {
private static final int HTTP_PORT = 8080;
private static final int TCP_PORT = 9090;
private static final int UDP_PORT = 10000;
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// 启动 HTTP 代理服务器
startHttpProxy(bossGroup, workerGroup);
// 启动 TCP 代理服务器
startTcpProxy(bossGroup, workerGroup);
// 启动 UDP 代理服务器
startUdpProxy(workerGroup);
System.out.println("Proxy servers started.");
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static void startHttpProxy(EventLoopGroup bossGroup, EventLoopGroup workerGroup) throws InterruptedException {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new HttpClientCodec(),
new HttpObjectAggregator(1048576),
new HttpProxyServerHandler()
);
}
});
b.bind(HTTP_PORT).sync();
System.out.println("HTTP proxy server started on port " + HTTP_PORT);
}
private static void startTcpProxy(EventLoopGroup bossGroup, EventLoopGroup workerGroup) throws InterruptedException {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TcpProxyServerHandler());
}
});
b.bind(TCP_PORT).sync();
System.out.println("TCP proxy server started on port " + TCP_PORT);
}
private static void startUdpProxy(EventLoopGroup workerGroup) throws InterruptedException {
Bootstrap b = new Bootstrap();
b.group(workerGroup)
.channel(NioDatagramChannel.class)
.handler(new UdpProxyServerHandler());
b.bind(UDP_PORT).sync();
System.out.println("UDP proxy server started on port " + UDP_PORT);
}
private static class HttpProxyServerHandler extends ChannelInboundHandlerAdapter {
private Channel outboundChannel;
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
FullHttpRequest request = (FullHttpRequest) msg;
URI uri = new URI(request.uri());
String host = uri.getHost();
int port = uri.getPort();
if (port == -1) {
port = 80;
}
Bootstrap b = new Bootstrap();
b.group(ctx.channel().eventLoop())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new HttpClientCodec(),
new HttpObjectAggregator(1048576),
new HttpProxyBackendHandler(ctx.channel())
);
}
});
ChannelFuture f = b.connect(host, port);
outboundChannel = f.channel();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
outboundChannel.writeAndFlush(request.retain());
} else {
ctx.channel().close();
}
}
});
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (outboundChannel != null) {
closeOnFlush(outboundChannel);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
private static class HttpProxyBackendHandler extends ChannelInboundHandlerAdapter {
private final Channel inboundChannel;
HttpProxyBackendHandler(Channel inboundChannel) {
this.inboundChannel = inboundChannel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
inboundChannel.writeAndFlush(msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
closeOnFlush(inboundChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
private static class TcpProxyServerHandler extends ChannelInboundHandlerAdapter {
private Channel outboundChannel;
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
if (outboundChannel == null) {
// 假设目标服务器地址和端口
String targetHost = "example.com";
int targetPort = 80;
Bootstrap b = new Bootstrap();
b.group(ctx.channel().eventLoop())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TcpProxyBackendHandler(ctx.channel()));
}
});
ChannelFuture f = b.connect(targetHost, targetPort);
outboundChannel = f.channel();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
outboundChannel.writeAndFlush(msg);
} else {
ctx.channel().close();
}
}
});
} else {
outboundChannel.writeAndFlush(msg);
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (outboundChannel != null) {
closeOnFlush(outboundChannel);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
private static class TcpProxyBackendHandler extends ChannelInboundHandlerAdapter {
private final Channel inboundChannel;
TcpProxyBackendHandler(Channel inboundChannel) {
this.inboundChannel = inboundChannel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
inboundChannel.writeAndFlush(msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
closeOnFlush(inboundChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
private static class UdpProxyServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private InetSocketAddress targetAddress = new InetSocketAddress("example.com", 80);
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
Bootstrap b = new Bootstrap();
b.group(ctx.channel().eventLoop())
.channel(NioDatagramChannel.class)
.handler(new UdpProxyBackendHandler(ctx.channel(), packet.sender()));
Channel channel = b.bind(0).sync().channel();
channel.writeAndFlush(new DatagramPacket(packet.content().retain(), targetAddress));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
private static class UdpProxyBackendHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private final Channel inboundChannel;
private final InetSocketAddress clientAddress;
UdpProxyBackendHandler(Channel inboundChannel, InetSocketAddress clientAddress) {
this.inboundChannel = inboundChannel;
this.clientAddress = clientAddress;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
inboundChannel.writeAndFlush(new DatagramPacket(packet.content().retain(), clientAddress));
ctx.channel().close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
}

View File

@ -1,13 +1,11 @@
package org.framework.lazy.cloud.network.heartbeat.dns.demo;
package org.framework.lazy.cloud.network.heartbeat.protocol.demo;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.dns.*;
import io.netty.util.AttributeKey;
@ -16,6 +14,9 @@ import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
@ -75,10 +76,25 @@ public final class DnsServer {
DatagramDnsResponse dnsResponse = new DatagramDnsResponse(msg.recipient(), msg.sender(), id);
dnsResponse.addRecord(DnsSection.QUESTION, question);
InetAddress inetAddress = null;
try {
inetAddress = Inet4Address.getByName("www.baidu.com");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
byte[] ipBytes = inetAddress.getAddress();
// just print the IP after query
// DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(
// question.name(),
// DnsRecordType.A, 600, Unpooled.wrappedBuffer(new byte[]{(byte) 192, (byte) 168, 1, 1}));
DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(
question.name(),
DnsRecordType.A, 600, Unpooled.wrappedBuffer(new byte[]{(byte) 192, (byte) 168, 1, 1}));
DnsRecordType.A,
600,
Unpooled.wrappedBuffer(ipBytes)
);
dnsResponse.addRecord(DnsSection.ANSWER, queryAnswer);
return dnsResponse;
}

View File

@ -1,4 +1,4 @@
package org.framework.lazy.cloud.network.heartbeat.dns.demo;
package org.framework.lazy.cloud.network.heartbeat.protocol.demo;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBufUtil;