h2tunnel – TCP over HTTP/2

1 day ago 2

The "tunneling" workflow (ngrok, ssh -R, etc.) is essential for exposing a local server to the internet.

Diagram

Dozens if not hundreds of tools exist to perform this networking setup, which of course inspired me to make my own. In this post I will share the trick that that makes my 500-LOC h2tunnel a compelling entry into the tunneling hall of fame.

Problem: shared connection

When talking about tunnels, we often hear about encryption, but this is trivially solved by TLS.

Diagram

However, once you have a secure TLS-encrypted tunnel, you face another problem.

Imagine two browser tabs simultaneously downloading two files through your tunnel. When the tunnel server receives a chunk of data, how does it know which browser tab to send it to? Typically parallel streams are identified by TCP connection, but in a tunneling scenario the connection is singular.

Solution: multiplexing

Multiplexing is a technique that uses a single connection to carry data for multiple simultaneous connections. It is achieved by letting simultaneous connections take turns sending chunks of data on the shared connection, each chunk wrapped in an envelope.

Diagram

TCP over HTTP/2

Turns out that the HTTP/2 protocol provides multiplexing for free and Node.js provides HTTP/2 for free as part of its standard library. Can we combine TLS and HTTP/2 to create a functional tunnel?

The answer is yes, simply send an HTTP/2 POST request through the newly established tunnel. When received by the other side, an HTTP/2 session is established, which provides a multiplexing API called HTTP/2 streams.

Diagram

Mapping TCP connections to HTTP/2 streams requires a lot of care, but with extensive testing I made sure it works correctly and even supports TCP edge cases like half-opened / half-closed connections.

Can you think of other uses for this technique?

Read Entire Article