AUTH-2369: RDP Bastion prototype

This commit is contained in:
Michael Borkenstein
2020-05-04 15:15:17 -05:00
parent 6a7418e1af
commit b89cc22896
8 changed files with 78 additions and 33 deletions

View File

@@ -13,6 +13,7 @@ import (
"net/http"
"time"
"github.com/cloudflare/cloudflared/h2mux"
"github.com/cloudflare/cloudflared/sshserver"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
@@ -118,13 +119,13 @@ func Stream(conn, backendConn io.ReadWriter) {
// DefaultStreamHandler is provided to the the standard websocket to origin stream
// This exist to allow SOCKS to deframe data before it gets to the origin
func DefaultStreamHandler(wsConn *Conn, remoteConn net.Conn) {
func DefaultStreamHandler(wsConn *Conn, remoteConn net.Conn, _ http.Header) {
Stream(wsConn, remoteConn)
}
// StartProxyServer will start a websocket server that will decode
// the websocket data and write the resulting data to the provided
func StartProxyServer(logger *logrus.Logger, listener net.Listener, remote string, shutdownC <-chan struct{}, streamHandler func(wsConn *Conn, remoteConn net.Conn)) error {
func StartProxyServer(logger *logrus.Logger, listener net.Listener, staticHost string, shutdownC <-chan struct{}, streamHandler func(wsConn *Conn, remoteConn net.Conn, requestHeaders http.Header)) error {
upgrader := websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
@@ -137,7 +138,18 @@ func StartProxyServer(logger *logrus.Logger, listener net.Listener, remote strin
}()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
stream, err := net.Dial("tcp", remote)
// If remote is an empty string, get the destination from the client.
finalDestination := staticHost
if finalDestination == "" {
if jumpDestination := r.Header.Get(h2mux.CFJumpDestinationHeader); jumpDestination == "" {
logger.Error("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 {
logger.WithError(err).Error("Cannot connect to remote.")
return
@@ -162,24 +174,17 @@ func StartProxyServer(logger *logrus.Logger, listener net.Listener, remote strin
conn.Close()
}()
token := r.Header.Get("cf-access-token")
if destination := r.Header.Get("CF-Access-SSH-Destination"); destination != "" {
if err := sendSSHPreamble(stream, destination, token); err != nil {
logger.WithError(err).Error("Failed to send SSH preamble")
return
}
}
streamHandler(&Conn{conn}, stream)
streamHandler(&Conn{conn}, stream, r.Header)
})
return httpServer.Serve(listener)
}
// sendSSHPreamble sends the final SSH destination address to the cloudflared SSH proxy
// SendSSHPreamble sends the final SSH destination address to the cloudflared SSH proxy
// The destination is preceded by its length
func sendSSHPreamble(stream net.Conn, destination, token string) error {
preamble := &sshserver.SSHPreamble{Destination: destination, JWT: token}
// Not part of sshserver module to fix compilation for incompatible operating systems
func SendSSHPreamble(stream net.Conn, destination, token string) error {
preamble := sshserver.SSHPreamble{Destination: destination, JWT: token}
payload, err := json.Marshal(preamble)
if err != nil {
return err