func (s *Server) handleDirectTCPIPRequest(sconn *ssh.ServerConn, ch ssh.Channel, req *sshutils.DirectTCPIPReq) {
	// ctx holds the connection context and keeps track of the associated resources
	ctx := newCtx(s, sconn)
	ctx.isTestStub = s.isTestStub
	ctx.addCloser(ch)
	defer ctx.Debugf("direct-tcp closed")
	defer ctx.Close()

	addr := fmt.Sprintf("%v:%d", req.Host, req.Port)
	ctx.Infof("direct-tcpip channel: %#v to --> %v", req, addr)
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		ctx.Infof("failed to connect to: %v, err: %v", addr, err)
		return
	}
	defer conn.Close()
	// audit event:
	s.EmitAuditEvent(events.PortForwardEvent, events.EventFields{
		events.PortForwardAddr: addr,
		events.EventLogin:      ctx.login,
		events.LocalAddr:       sconn.LocalAddr().String(),
		events.RemoteAddr:      sconn.RemoteAddr().String(),
	})
	wg := &sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		io.Copy(ch, conn)
		ch.Close()
	}()
	wg.Add(1)
	go func() {
		defer wg.Done()
		io.Copy(conn, ch)
		conn.Close()
	}()
	wg.Wait()
}
// handleDirectTCPIPRequest does the port forwarding
handleDirectTCPIPRequest does the port forwarding
// handleDirectTCPIPRequest does the port forwarding
func (s *Server) handleDirectTCPIPRequest(sconn *ssh.ServerConn, ch ssh.Channel, req *sshutils.DirectTCPIPReq) {
	ctx := newCtx(s, sconn)
	ctx.isTestStub = s.isTestStub
	ctx.addCloser(ch)
	defer ctx.Debugf("direct-tcp closed")
	defer ctx.Close()
	addr := fmt.Sprintf("%v:%d", req.Host, req.Port)
	ctx.Infof("direct-tcpip channel: %#v to --> %v", req, addr)
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		ctx.Infof("failed to connect to: %v, err: %v", addr, err)
		return
	}
	defer conn.Close()
	s.EmitAuditEvent(events.PortForwardEvent, events.EventFields{
		events.PortForwardAddr: addr,
		events.EventLogin:      ctx.login,
		events.LocalAddr:       sconn.LocalAddr().String(),
		events.RemoteAddr:      sconn.RemoteAddr().String(),
	})
	wg := &sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		io.Copy(ch, conn)
		ch.Close()
	}()
	wg.Add(1)
	go func() {
		defer wg.Done()
		io.Copy(conn, ch)
		conn.Close()
	}()
	wg.Wait()
}
func ( s * Server ) handleDirectTCPIPRequest ( sconn * ssh . ServerConn , ch ssh . Channel , req * sshutils . DirectTCPIPReq ) { ctx := newCtx ( s , sconn ) ctx . isTestStub = s . isTestStub ctx . addCloser ( ch ) defer ctx . Debugf ( " " ) defer ctx . Close ( ) addr := fmt . Sprintf ( " " , req . Host , req . Port ) ctx . Infof ( " " , req , addr ) conn , err := net . Dial ( " " , addr ) if err != nil { ctx . Infof ( " " , addr , err ) return } defer conn . Close ( ) s . EmitAuditEvent ( events . PortForwardEvent , events . EventFields { events . PortForwardAddr : addr , events . EventLogin : ctx . login , events . LocalAddr : sconn . LocalAddr ( ) . String ( ) , events . RemoteAddr : sconn . RemoteAddr ( ) . String ( ) , } ) wg := & sync . WaitGroup { } wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) io . Copy ( ch , conn ) ch . Close ( ) } ( ) wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) io . Copy ( conn , ch ) conn . Close ( ) } ( ) wg . Wait ( ) }
handleDirectTCPIPRequest does the port forwarding
handleDirectTCPIPRequest does the port forwarding
// ctx holds the connection context and keeps track of the associated resources // audit event: