mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 15:49:58 +00:00
TUN-3863: Consolidate header handling logic in the connection package; move headers definitions from h2mux to packages that manage them; cleanup header conversions
All header transformation code from h2mux has been consolidated in the connection package since it's used by both h2mux and http2 logic. Exported headers used by proxying between edge and cloudflared so then can be shared by tunnel service on the edge. Moved access-related headers to corresponding packages that have the code that sets/uses these headers. Removed tunnel hostname tracking from h2mux since it wasn't used by anything. We will continue to set the tunnel hostname header from the edge for backward compatibilty, but it's no longer used by cloudflared. Move bastion-related logic into carrier package, untangled dependencies between carrier, origin, and websocket packages.
This commit is contained in:
@@ -4,15 +4,11 @@ import (
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
)
|
||||
|
||||
var stripWebsocketHeaders = []string{
|
||||
@@ -47,80 +43,6 @@ func ClientConnect(req *http.Request, dialler *websocket.Dialer) (*websocket.Con
|
||||
return conn, response, nil
|
||||
}
|
||||
|
||||
// StartProxyServer will start a websocket server that will decode
|
||||
// the websocket data and write the resulting data to the provided
|
||||
func StartProxyServer(
|
||||
log *zerolog.Logger,
|
||||
listener net.Listener,
|
||||
staticHost string,
|
||||
shutdownC <-chan struct{},
|
||||
streamHandler func(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger),
|
||||
) error {
|
||||
upgrader := websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
h := handler{
|
||||
upgrader: upgrader,
|
||||
log: log,
|
||||
staticHost: staticHost,
|
||||
streamHandler: streamHandler,
|
||||
}
|
||||
|
||||
httpServer := &http.Server{Addr: listener.Addr().String(), Handler: &h}
|
||||
go func() {
|
||||
<-shutdownC
|
||||
_ = httpServer.Close()
|
||||
}()
|
||||
|
||||
return httpServer.Serve(listener)
|
||||
}
|
||||
|
||||
// HTTP handler for the websocket proxy.
|
||||
type handler struct {
|
||||
log *zerolog.Logger
|
||||
staticHost string
|
||||
upgrader websocket.Upgrader
|
||||
streamHandler func(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger)
|
||||
}
|
||||
|
||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// If remote is an empty string, get the destination from the client.
|
||||
finalDestination := h.staticHost
|
||||
if finalDestination == "" {
|
||||
if jumpDestination := r.Header.Get(h2mux.CFJumpDestinationHeader); jumpDestination == "" {
|
||||
h.log.Error().Msg("Did not receive final destination from client. The --destination flag is likely not set")
|
||||
return
|
||||
} else {
|
||||
finalDestination = jumpDestination
|
||||
}
|
||||
}
|
||||
|
||||
stream, err := net.Dial("tcp", finalDestination)
|
||||
if err != nil {
|
||||
h.log.Err(err).Msg("Cannot connect to remote")
|
||||
return
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
if !websocket.IsWebSocketUpgrade(r) {
|
||||
_, _ = w.Write(nonWebSocketRequestPage())
|
||||
return
|
||||
}
|
||||
conn, err := h.upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
h.log.Err(err).Msg("failed to upgrade")
|
||||
return
|
||||
}
|
||||
_ = conn.SetReadDeadline(time.Now().Add(pongWait))
|
||||
conn.SetPongHandler(func(string) error { _ = conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
gorillaConn := &GorillaConn{Conn: conn, log: h.log}
|
||||
go gorillaConn.pinger(r.Context())
|
||||
defer conn.Close()
|
||||
|
||||
h.streamHandler(gorillaConn, stream, h.log)
|
||||
}
|
||||
|
||||
// NewResponseHeader returns headers needed to return to origin for completing handshake
|
||||
func NewResponseHeader(req *http.Request) http.Header {
|
||||
header := http.Header{}
|
||||
@@ -174,3 +96,27 @@ func ChangeRequestScheme(reqURL *url.URL) string {
|
||||
return reqURL.Scheme
|
||||
}
|
||||
}
|
||||
|
||||
// Stream copies copy data to & from provided io.ReadWriters.
|
||||
func Stream(conn, backendConn io.ReadWriter, log *zerolog.Logger) {
|
||||
proxyDone := make(chan struct{}, 2)
|
||||
|
||||
go func() {
|
||||
_, err := io.Copy(conn, backendConn)
|
||||
if err != nil {
|
||||
log.Debug().Msgf("conn to backendConn copy: %v", err)
|
||||
}
|
||||
proxyDone <- struct{}{}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
_, err := io.Copy(backendConn, conn)
|
||||
if err != nil {
|
||||
log.Debug().Msgf("backendConn to conn copy: %v", err)
|
||||
}
|
||||
proxyDone <- struct{}{}
|
||||
}()
|
||||
|
||||
// If one side is done, we are done.
|
||||
<-proxyDone
|
||||
}
|
||||
|
@@ -151,41 +151,3 @@ func TestWebsocketWrapper(t *testing.T) {
|
||||
require.Equal(t, n, 2)
|
||||
require.Equal(t, "bc", string(buf[:n]))
|
||||
}
|
||||
|
||||
// func TestStartProxyServer(t *testing.T) {
|
||||
// var wg sync.WaitGroup
|
||||
// remoteAddress := "localhost:1113"
|
||||
// listenerAddress := "localhost:1112"
|
||||
// message := "Good morning Austin! Time for another sunny day in the great state of Texas."
|
||||
// logger := zerolog.Nop()
|
||||
// shutdownC := make(chan struct{})
|
||||
|
||||
// listener, err := net.Listen("tcp", listenerAddress)
|
||||
// assert.NoError(t, err)
|
||||
// defer listener.Close()
|
||||
|
||||
// remoteListener, err := net.Listen("tcp", remoteAddress)
|
||||
// assert.NoError(t, err)
|
||||
// defer remoteListener.Close()
|
||||
|
||||
// wg.Add(1)
|
||||
// go func() {
|
||||
// defer wg.Done()
|
||||
// conn, err := remoteListener.Accept()
|
||||
// assert.NoError(t, err)
|
||||
// buf := make([]byte, len(message))
|
||||
// conn.Read(buf)
|
||||
// assert.Equal(t, string(buf), message)
|
||||
// }()
|
||||
|
||||
// go func() {
|
||||
// StartProxyServer(logger, listener, remoteAddress, shutdownC)
|
||||
// }()
|
||||
|
||||
// req := testRequest(t, fmt.Sprintf("http://%s/", listenerAddress), nil)
|
||||
// conn, _, err := ClientConnect(req, nil)
|
||||
// assert.NoError(t, err)
|
||||
// err = conn.WriteMessage(1, []byte(message))
|
||||
// assert.NoError(t, err)
|
||||
// wg.Wait()
|
||||
// }
|
||||
|
Reference in New Issue
Block a user