When two devices are behind NAT or strict firewalls and cannot “see” each other directly, a VPN seems to be the standard solution. But a full-fledged L3 tunnel (like WireGuard or OpenVPN) is often redundant: it requires root rights, setting up virtual interfaces, and can conflict with existing routes.
In such cases, it is convenient to use Chisel – a TCP/UDP tunnel that runs on top of HTTP and uses WebSockets for data transfer. In this note I will show how to “forward” a port from one client to another through an intermediate server.
How does it work?
Imagine the situation: you have Client A (for example, your home server), Client B (your work laptop) and a VPS with a public IP address. Clients A and B can access the VPS, but not each other.
The forwarding scheme will look like this:
1. Client A connects to the VPS and opens a “reverse” port on the server. Now everything that comes to port X of the server goes to port Y of Client A.
2. Client B connects to the VPS and forwards port Z from its local machine to port X of the server.
3. As a result, Client B accesses localhost:Z and ends up on Client A:Y.
This approach is one of the solutions in cases where communication with a VPS does not implement the L3 layer or there is no ability to configure routing between clients. We work exclusively at the application and port level.
Step 1: Start the server
On your VPS, just run Chisel in server mode. The --reverse flag is required to allow clients to open ports on the server side.
chisel server --port 8080 --reverse
Step 2: Connecting Client A (Source)
Let’s say Client A wants to open access to his local web server on port 3000. He connects to the VPS and says: “reserve port 2000 on the server and forward it to me to 3000.”
chisel client vps-ip:8080 R:2000:127.0.0.1:3000
Now port 2000 on the VPS (on the loopback interface) leads to Client A.
Step 3: Connecting Client B (Consumer)
Now Client B wants to access this resource. It connects to the same VPS and forwards its local port 8080 to port 2000 of the server.
chisel client vps-ip:8080 8080:127.0.0.1:2000
Ready! Now, when you open http://localhost:8080 on Client B, you will see the service running on Client A.
Safety and nuances
Chisel supports authentication via the --auth flag, which is highly recommended when working through public servers. You can also use TLS certificates to encrypt traffic.
The main advantage of this approach is that there is no need for TUN/TAP devices and complex routing tables. This is a stripped-down tunnel that does exactly one thing: binds ports via a WebSocket connection. This even works through corporate proxies if you configure Chisel to work through port 443.
Output
Chisel is a utility for specific network tasks. When you need to forward ports between isolated nodes without setting up a full-fledged VPN, a combination of forward and reverse tunnels through a relay server turns out to be a completely viable solution.
Links
https://github.com/jpillora/chisel