目前主流的内网穿透技术是花生壳和神卓互联,都是基于C语言开发的,稳定性和性能都非常高,今天我用netty实现一个端口转发程序,代码如下:
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class PortForwarder {
private final int localPort; // 本地端口
private final String remoteHost; // 远程主机
private final int remotePort; // 远程端口
public PortForwarder(int localPort, String remoteHost, int remotePort) {
this.localPort = localPort;
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
public void start() throws Exception {
// 创建两个EventLoopGroup,一个用于接受连接,一个用于处理数据
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// 创建Bootstrap对象,用于启动客户端
Bootstrap b = new Bootstrap();
b.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ForwardHandler());
}
});
// 绑定本地端口,开始监听连接
Channel localChannel = b.bind(localPort).sync().channel();
System.out.println("PortForwarder started, listening on " + localChannel.localAddress());
// 连接远程主机
Channel remoteChannel = b.connect(remoteHost, remotePort).sync().channel();
System.out.println("Connected to " + remoteHost + ":" + remotePort);
// 等待本地端口关闭
localChannel.closeFuture().sync();
} finally {
// 关闭EventLoopGroup
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private class ForwardHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 将接收到的数据发送到远程主机
ByteBuf buf = (ByteBuf) msg;
ctx.writeAndFlush(buf.retain());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
public static void main(String[] args) throws Exception {
PortForwarder portForwarder = new PortForwarder(8080, "remote.host.com", 80);
portForwarder.start();
}
}
这个例子中,我们在本地8080端口启动了一个Netty服务端,然后连接到远程主机的80端口。当有数据从本地端口接收时,会将数据发送到远程主机,反之亦然。