能否利用HTTP/2 CONNECT或HTTP/3 QUIC CONNECT构建反向隧道,让服务器反向传输请求?
1. HTTP/2 CONNECT能否用作反向隧道?
HTTP/2的CONNECT机制本身不支持服务器主动在客户端发起的连接上创建新流。CONNECT流的设计是客户端发起,用于建立到目标服务器的隧道,之后该流的双向数据传输基于客户端的主动请求触发,服务器无法主动发起新的请求流反向传输给客户端。
不过存在变通方案:可以在已建立的CONNECT隧道之上,构建应用层的反向代理协议。比如客户端发起CONNECT连接到中心hub后,双方在这个隧道内维持长连接,中心hub收到外部请求时,通过该长连接将请求转发给客户端,客户端处理后再通过隧道回传响应。这种方式本质是在HTTP/2隧道之上封装了自定义的反向通信逻辑,而非直接利用HTTP/2的原生流机制。
2. HTTP/3 QUIC CONNECT的情况
HTTP/3基于QUIC协议,QUIC本身支持多路复用的流且连接是双向的,但CONNECT方法的语义依然是客户端发起隧道建立。不过借助QUIC的双向流特性,客户端发起CONNECT建立隧道后,服务器理论上可以在同一个QUIC连接上主动创建新的流来向客户端发送请求——但这需要双方实现自定义的应用层逻辑,因为HTTP/3的标准CONNECT并没有定义这种反向使用的模式,属于协议之上的扩展。
3. HTTP/2 CONNECT流的控制权
HTTP/2的CONNECT流严格由客户端发起并主导。服务器只能响应客户端的CONNECT请求,建立隧道后被动传输数据,无法主动发起新的流或请求。这是由HTTP/2的请求-响应模型决定的,所有流的发起权都在客户端。
结合你要暴露NAT后服务到中心hub的需求,以下是几个落地性较强的方案:
- 基于HTTP/2的自定义反向隧道:使用Envoy或自定义代理,让边缘客户端发起HTTP/2
CONNECT到中心hub,在隧道内实现简单的反向代理协议。比如中心hub收到外部请求时,将请求序列化后通过CONNECT隧道发送给边缘客户端,客户端处理后返回响应,可避免SSH嵌套带来的TCP性能问题。 - 使用成熟的HTTP反向隧道工具:除你提到的inlets pro外,开源工具
chisel支持HTTP/HTTPS反向隧道,可暴露多个端口,功能类似ssh -R;frp支持HTTP/HTTPS反向代理,配置灵活,这些工具已经封装了基于HTTP的反向隧道逻辑,无需自行从头实现。 - Envoy结合gRPC实现反向隧道:Envoy本身无原生反向隧道支持,但可通过自定义过滤器或结合gRPC长连接实现。比如边缘客户端通过gRPC连接中心hub的Envoy,中心hub将外部请求转发到gRPC流,边缘客户端再将请求转发至内部服务。
你提到的Teleport使用SSH协议做反向隧道,是因为SSH原生支持远程端口转发(ssh -R),但HTTP协议本身没有这个语义,需要在其之上构建额外逻辑。如果追求基于HTTP+TLS的方案,优先选择成熟的开源工具,可降低实现成本。
内容的提问来源于stack exchange,提问作者Craig Ringer

