A lightweight reverse TCP tunnel server + client in Go — like ngrok
Expose your local services running on localhost to the public internet via a single public server.
- Single binary client and server
- Reverse tunneling with no authentication
- Simple protocol using TCP
┌────────────┐ ┌──────────────┐
│ Client │ control (7835) │ Server │
│ (localhost)│◀────────────────────▶│ (public VPS) │
└────┬───────┘ └────┬─────────┘
│ │
│ data tunnel (7836) │
│◀──────────────────────────────────┤
│ │
┌────▼───────┐ ┌─────▼────────────┐
│ Local App │◀─── localhost:5000 ─│ External Request │
│ (e.g. API)│ │ (e.g. curl) │
└────────────┘ └──────────────────┘This connection is used for the initial setup and communication of connection requests.
Client Initiates:
-
The client sends an
EXPOSEcommand followed by the local port they want to expose.EXPOSE 5000
Server Responds:
-
Upon receiving the
EXPOSEcommand, the server acknowledges with anOKmessage and provides a publicly accessible port (<publicPort>).OK 12345
Server Notifies of Incoming Connection:
-
When an external user connects to the
<publicPort>on the server, the server sends aCONNECTIONmessage to the client, including a unique connection identifier (<id>).CONNECTION abcdef123
This connection is established to create a tunnel for the actual data transfer.
Client Connects Back:
-
Upon receiving the
CONNECTIONmessage, the client establishes a new connection to the server on a different port (:7836). -
Immediately after connecting, the client sends an
IDmessage containing the<id>received in theCONNECTIONmessage.ID abcdef123
Server Pipes Connections:
-
The server receives the
IDand identifies the waiting user connection associated with that<id>. -
The server then establishes a direct pipe between the client's Data Tunnel Connection and the waiting user's connection. Any data sent on one connection is directly forwarded to the other, creating a tunnel.
This two-step process allows the server to manage multiple exposed ports and efficiently connect incoming requests to the appropriate client.
Follow these steps to set up and use the TCP tunnel.
git clone https://github.com/your-username/go-tcp-tunnel.git
cd go-tcp-tunnelpython3 -m http.server 5000go run server/main.gogo run client/main.goIf successful, you’ll see responses like:
Server response: OK 9090
Server response: CONNECTION 12345
curl http://localhost:9090