github.com/devops-filetransfer/sshego@v7.0.4+incompatible/direct.go (about)

     1  package sshego
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"net"
     8  
     9  	ssh "github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh"
    10  )
    11  
    12  // see also dev.justinjudd.org/justin/easyssh for examples
    13  // of multiplexing ssh channels.
    14  
    15  // channelOpenDirectMsg is the structure for RFC 4254 7.2. It can be
    16  // used for "forwarded-tcpip" and "direct-tcpip"
    17  type channelOpenDirectMsg struct {
    18  	Rhost string
    19  	Rport uint32
    20  	Lhost string
    21  	Lport uint32
    22  }
    23  
    24  const minus2_uint32 uint32 = 0xFFFFFFFE
    25  const minus10_uint32 uint32 = 0xFFFFFFF6
    26  
    27  // server side: handle channel type "direct-tcpip"  - RFC 4254 7.2
    28  // ca can be nil.
    29  func handleDirectTcp(ctx context.Context, parentHalt *ssh.Halter, newChannel ssh.NewChannel, ca *ConnectionAlert) {
    30  	pp("handleDirectTcp called!")
    31  
    32  	p := &channelOpenDirectMsg{}
    33  	ssh.Unmarshal(newChannel.ExtraData(), p)
    34  	targetAddr := fmt.Sprintf("%s:%d", p.Rhost, p.Rport)
    35  	log.Printf("direct-tcpip got channelOpenDirectMsg request to destination %s",
    36  		targetAddr)
    37  
    38  	channel, req, err := newChannel.Accept() // (Channel, <-chan *Request, error)
    39  	panicOn(err)
    40  	go ssh.DiscardRequests(ctx, req, parentHalt)
    41  
    42  	go func(ch ssh.Channel, host string, port uint32) {
    43  
    44  		var targetConn net.Conn
    45  		var err error
    46  		addr := fmt.Sprintf("%s:%d", p.Rhost, p.Rport)
    47  		switch port {
    48  		case minus2_uint32:
    49  			// unix domain request
    50  			//pp("direct.go has unix domain forwarding request")
    51  			targetConn, err = net.Dial("unix", host)
    52  		case 1:
    53  			//pp("direct.go has port 1 forwarding request. ca = %#v", ca)
    54  			if ca != nil && ca.PortOne != nil {
    55  				//pp("handleDirectTcp sees a port one request with a live ca.PortOne")
    56  				select {
    57  				case ca.PortOne <- ch:
    58  				case <-ca.ShutDown:
    59  				}
    60  				return
    61  			}
    62  			panic("wat?")
    63  			fallthrough
    64  		default:
    65  			targetConn, err = net.Dial("tcp", targetAddr)
    66  		}
    67  		if err != nil {
    68  			log.Printf("sshd direct.go could not forward connection to addr: '%s'", addr)
    69  			return
    70  		}
    71  		log.Printf("sshd direct.go forwarding direct connection to addr: '%s'", addr)
    72  
    73  		sp := newShovelPair(false)
    74  		parentHalt.AddDownstream(sp.Halt)
    75  		sp.Start(targetConn, ch, "targetBehindSshd<-fromDirectClient", "fromDirectClient<-targetBehindSshd")
    76  	}(channel, p.Rhost, p.Rport)
    77  }
    78  
    79  // client side
    80  func dialDirect(ctx context.Context, c *ssh.Client, laddr string, lport int, raddr string, rport int, parentHalt *ssh.Halter) (ssh.Channel, error) {
    81  	msg := channelOpenDirectMsg{
    82  		Rhost: raddr,
    83  		Rport: uint32(rport),
    84  		Lhost: laddr,
    85  		Lport: uint32(lport),
    86  	}
    87  	ch, in, err := c.OpenChannel(ctx, "direct-tcpip", ssh.Marshal(&msg), parentHalt)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	go ssh.DiscardRequests(ctx, in, nil)
    92  	return ch, err
    93  }