package worker import ( "context" "io" "net" "net/url" "sync" "nhooyr.io/websocket" pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services" ) func (w *Worker) handleTcpProxyV1(connCtx context.Context, clientAddr *net.TCPAddr, conn *websocket.Conn, si *sessionInfo, connectionId, endpoint string) { si.RLock() sessionId := si.lookupSessionResponse.GetAuthorization().GetSessionId() si.RUnlock() sessionUrl, err := url.Parse(endpoint) if err != nil { w.logger.Error("error parsing endpoint information", "error", err, "session_id", sessionId, "endpoint", endpoint) conn.Close(websocket.StatusInternalError, "cannot parse endpoint url") return } if sessionUrl.Scheme != "tcp" { w.logger.Error("invalid scheme for tcp proxy", "error", err, "session_id", sessionId, "endpoint", endpoint) conn.Close(websocket.StatusInternalError, "invalid scheme for type") return } remoteConn, err := net.Dial("tcp", sessionUrl.Host) if err != nil { w.logger.Error("error dialing endpoint", "error", err, "endpoint", endpoint) conn.Close(websocket.StatusInternalError, "endpoint dialing failed") return } // Assert this for better Go 1.11 splice support tcpRemoteConn := remoteConn.(*net.TCPConn) endpointAddr := tcpRemoteConn.RemoteAddr().(*net.TCPAddr) connectionInfo := &pbs.ConnectConnectionRequest{ ConnectionId: connectionId, ClientTcpAddress: clientAddr.IP.String(), ClientTcpPort: uint32(clientAddr.Port), EndpointTcpAddress: endpointAddr.IP.String(), EndpointTcpPort: uint32(endpointAddr.Port), Type: "tcp", } connStatus, err := w.connectConnection(connCtx, connectionInfo) if err != nil { w.logger.Error("error marking connection as connected", "error", err) conn.Close(websocket.StatusInternalError, "failed to mark connection as connected") return } si.Lock() si.connInfoMap[connectionId].status = connStatus si.Unlock() // Get a wrapped net.Conn so we can use io.Copy netConn := websocket.NetConn(connCtx, conn, websocket.MessageBinary) connWg := new(sync.WaitGroup) connWg.Add(2) go func() { defer connWg.Done() _, err := io.Copy(netConn, tcpRemoteConn) w.logger.Debug("copy from client to endpoint done", "error", err) }() go func() { defer connWg.Done() _, err := io.Copy(tcpRemoteConn, netConn) w.logger.Debug("copy from endpoint to client done", "error", err) }() connWg.Wait() }