TUN-3615: added support to proxy tcp streams

added ingress.DefaultStreamHandler and a basic test for tcp stream proxy
moved websocket.Stream to ingress
cloudflared no longer picks tcpstream host from header
This commit is contained in:
Sudarsan Reddy
2021-01-11 19:59:45 +00:00
committed by Nuno Diegues
parent e2262085e5
commit 368066a966
14 changed files with 256 additions and 96 deletions

View File

@@ -50,8 +50,17 @@ func (c *ClassicTunnelConfig) IsTrialZone() bool {
return c.Hostname == ""
}
// Type indicates the connection type of the connection.
type Type int
const (
TypeWebsocket Type = iota
TypeTCP
TypeHTTP
)
type OriginProxy interface {
Proxy(w ResponseWriter, req *http.Request, isWebsocket bool) error
Proxy(w ResponseWriter, req *http.Request, sourceConnectionType Type) error
}
type ResponseWriter interface {

View File

@@ -41,8 +41,8 @@ type testRequest struct {
type mockOriginProxy struct {
}
func (moc *mockOriginProxy) Proxy(w ResponseWriter, r *http.Request, isWebsocket bool) error {
if isWebsocket {
func (moc *mockOriginProxy) Proxy(w ResponseWriter, r *http.Request, sourceConnectionType Type) error {
if sourceConnectionType == TypeWebsocket {
return wsEndpoint(w, r)
}
switch r.URL.Path {

View File

@@ -216,7 +216,12 @@ func (h *h2muxConnection) ServeStream(stream *h2mux.MuxedStream) error {
return reqErr
}
err := h.config.OriginProxy.Proxy(respWriter, req, websocket.IsWebSocketUpgrade(req))
var sourceConnectionType = TypeHTTP
if websocket.IsWebSocketUpgrade(req) {
sourceConnectionType = TypeWebsocket
}
err := h.config.OriginProxy.Proxy(respWriter, req, sourceConnectionType)
if err != nil {
respWriter.WriteErrorResponse()
return err

View File

@@ -19,6 +19,7 @@ import (
const (
internalUpgradeHeader = "Cf-Cloudflared-Proxy-Connection-Upgrade"
tcpStreamHeader = "Cf-Cloudflared-Proxy-Src"
websocketUpgrade = "websocket"
controlStreamUpgrade = "control-stream"
)
@@ -107,21 +108,33 @@ func (c *http2Connection) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
respWriter.flusher = flusher
var err error
if isControlStreamUpgrade(r) {
switch {
case isControlStreamUpgrade(r):
respWriter.shouldFlush = true
err = c.serveControlStream(r.Context(), respWriter)
c.controlStreamErr = err
} else if isWebsocketUpgrade(r) {
if err := c.serveControlStream(r.Context(), respWriter); err != nil {
respWriter.WriteErrorResponse()
}
return
case isWebsocketUpgrade(r):
respWriter.shouldFlush = true
stripWebsocketUpgradeHeader(r)
err = c.config.OriginProxy.Proxy(respWriter, r, true)
} else {
err = c.config.OriginProxy.Proxy(respWriter, r, false)
}
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeWebsocket); err != nil {
respWriter.WriteErrorResponse()
}
return
if err != nil {
respWriter.WriteErrorResponse()
case IsTCPStream(r):
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeTCP); err != nil {
respWriter.WriteErrorResponse()
}
return
default:
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeHTTP); err != nil {
respWriter.WriteErrorResponse()
}
}
}
@@ -231,11 +244,16 @@ func (rp *http2RespWriter) Close() error {
}
func isControlStreamUpgrade(r *http.Request) bool {
return strings.ToLower(r.Header.Get(internalUpgradeHeader)) == controlStreamUpgrade
return r.Header.Get(internalUpgradeHeader) == controlStreamUpgrade
}
func isWebsocketUpgrade(r *http.Request) bool {
return strings.ToLower(r.Header.Get(internalUpgradeHeader)) == websocketUpgrade
return r.Header.Get(internalUpgradeHeader) == websocketUpgrade
}
// IsTCPStream discerns if the connection request needs a tcp stream proxy.
func IsTCPStream(r *http.Request) bool {
return r.Header.Get(tcpStreamHeader) != ""
}
func stripWebsocketUpgradeHeader(r *http.Request) {