Implementing Internal Network Penetration (Port Forwarding) with Java AIO Asynchronous Sockets
This article explains the principle of internal network penetration, describes how to build a Java AIO‑based client‑service tunnel with separate modules for registration and data exchange, and provides complete source code and testing steps for remote access to locally deployed services.
Idea
Internal network penetration (also known as port forwarding) is a technique that enables remote access to services deployed on a private‑IP machine by routing traffic through a public‑IP server. The private host initiates a connection to the public server, which then mediates inbound requests.
Implementation Overview
Two Maven modules are created: client (runs locally) and service (runs on the cloud server). Both use Java NIO AsynchronousSocketChannel (AIO) for non‑blocking communication. The service opens two ServerSocketChannels: one listening on port 16000 for external requests and another on port 16088 for client connections.
The external listener checks whether a registration channel ( registerChannel ) exists; if not, it closes the incoming connection. When a registration channel is present, the listener notifies it of an incoming request by sending a byte 1, then retrieves a client channel from channelQueue and swaps data between the two connections.
private static final int extPort = 16000;
private static final int clintPort = 16088;
private static AsynchronousSocketChannel registerChannel;
static BlockingQueue<AsynchronousSocketChannel> channelQueue = new LinkedBlockingQueue<>();
public static void main(String[] args) throws IOException {
// ... (listener setup omitted for brevity) ...
}The clintHandle method processes bytes received from the client: 0 marks the channel as the registration channel, 1 puts the channel into channelQueue for data exchange, and any other value signals an error.
private static void clintHandle(AsynchronousSocketChannel ch) {
final ByteBuffer buffer = ByteBuffer.allocate(1);
ch.read(buffer, null, new CompletionHandler<Integer, Void>() {
public void completed(Integer result, Void attachment) {
buffer.flip();
byte b = buffer.get();
if (b == 0) {
registerChannel = ch;
} else if(b == 1){
channelQueue.offer(ch);
} else {
channelQueue.add(null);
}
}
public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); }
});
}The client module connects to the service, registers itself by sending byte 0, then waits for a byte 1 indicating that the external request has arrived. Upon receiving 1, it creates a new client connection to the target local service (e.g., RDP on port 3389) and starts bidirectional data transfer.
private static void createNewClient() throws IOException {
// ... (connection logic) ...
// on success send byte 1, on failure send byte 2
}The core data‑exchange routine exchangeData continuously reads from one channel and writes to the other, handling partial writes and connection closures.
private static void exchangeData(AsynchronousSocketChannel ch1, AsynchronousSocketChannel ch2) {
// ... (asynchronous read/write loop) ...
}Testing
A simple Python HTTP server is used to serve compiled class files to a Windows 10 VM, where the Java program is executed with java -cp . org.example.Main . The VM can then be accessed remotely via the tunneled RDP port.
if __name__ == '__main__':
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
os.chdir("C:\netTunnlDemo\client\target")
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"服务启动在端口 {PORT}")
httpd.serve_forever()Result
The final screenshot shows a successful remote desktop session through the tunnel.
Conclusion
Although using Java AIO makes the code lengthy, the underlying logic is straightforward; the complete source is available at the Gitee repository netTunnlDemo for personal learning.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.