Can HTTP/2 CONNECT be used as a reverse tunnel?

176 views Asked by At

Is it possible to use HTTP/2 CONNECT or HTTP/3 QUIC CONNECT connection as a reverse tunnel such that the server end can multiplex HTTP requests back down the tunnel to the connection initiator?

This would require the HTTP server to be able to create new streams on a client-initiated connection.

Or are HTTP/2 CONNECT streams strictly client-initiated and client-controlled?


Context:

I'm looking to expose services on a NAT'd host to a central control hub. Both the edge services and the control hub are on separate, independent k8s clusters. Only the central hub has a public-routable IP address.

Most of the k8s-native east-west-routing and service mesh options that support service discovery and virtual services cannot be used because tools like Istio and Consul require mutual reachability.

I'm aware of the typical options such as ssh -R, wireguard VPN, etc, but for a variety of reasons they're going to be awkward and difficult to use in this environment. Something based on HTTP+TLS will work a lot better. I could possibly tunnel tunnel ssh over HTTP CONNECT then use ssh to reverse-tunnel the requests, for example, but the layering is probably going to do ugly things to TCP.

I've been looking into whether it's possible to configure the Envoy proxy to accept inbound HTTP/2 CONNECT from an external service, then use that inbound connection as a listener to route other requests through. But I can't find any hint that it's even possible.

(Based on a quick reading of the Teleport code, Teleport Proxy uses the ssh protocol for reverse tunnels to the Teleport Agent. There's an "inlets pro" tool that does something similar over HTTPs but it looks like it's 1:1 tunnels only. I haven't been able to find anything like a simple tool to expose a SOCKS proxy over a client-initiated HTTP tunnel, or do remote-port-forwarding (ssh -R style) over a client-initiated HTTP tunnel.)

1

There are 1 answers

0
Craig Ringer On BEST ANSWER

The answer seems to be "no, it can't". You need a command-and-control channel where client-side long-polls the "server" side. The server makes requests for new channels over the control channel, and the client initiates them.

It's unclear if this is possible server-side with HTTP/3 over QUIC, or over WebSockets, but for HTTP/2 it looks like a "no".