diff --git a/README.md b/README.md index c71f942..bdcaa8b 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,17 @@ A simple TCP proxy. Currently used in [AppVenture](https://appventure.nushigh.ed $ ./forward -help Usage of ./forward: -connect string - forward to ip and port (default ":8080") + forward to address -listen string - listen on ip and port (default ":8081") + listen on address (default ":8000") + -ssh string + if set, will do basic introspection to forward SSH traffic to this address ``` +### Usage with SSH + +You can use `forward` to do multiplexing of SSH and HTTP in a quick and dirty way, using very simple protocol introspection. A more robust solution would be [sshttp](https://github.com/stealth/sshttp) + ## Usage on Windows `forward` is wrapped with [go-svc](https://github.com/judwhite/go-svc), enabling it to be run as a Windows service. To add with PowerShell: diff --git a/server.go b/server.go index 03c8e07..bc62bad 100644 --- a/server.go +++ b/server.go @@ -70,37 +70,53 @@ var magic = []byte{'S', 'S', 'H', '-'} var magicLen = len(magic) func handle(c net.Conn, count int) { - // read first four characters - readMagic := make([]byte, magicLen, magicLen) - n, err := c.Read(readMagic) - if n != magicLen { - log.Printf("warning! could not read header") - return - } - opError, ok := err.(*net.OpError) - if err != nil && (!ok || opError.Op != "readfrom") { - log.Printf("warning! %v", err) - return - } + if connSSH != nil { - connTo := conn - // if the header looks like SSH, forward to SSH connection - if bytes.Equal(readMagic, magic) { - connTo = connSSH - } + // read first four characters + readMagic := make([]byte, magicLen, magicLen) + n, err := c.Read(readMagic) + if n != magicLen { + log.Printf("warning! could not read header") + return + } + opError, ok := err.(*net.OpError) + if err != nil && (!ok || opError.Op != "readfrom") { + log.Printf("warning! %v", err) + return + } - cn, err := net.DialTCP("tcp", nil, connTo) - if err != nil { - c.Close() - log.Print(err) - return - } + connTo := conn + // if the header looks like SSH, forward to SSH connection + if bytes.Equal(readMagic, magic) { + connTo = connSSH + } - // write the first four characters - cn.Write(readMagic) + cn, err := net.DialTCP("tcp", nil, connTo) + if err != nil { + c.Close() + log.Print(err) + return + } + + // write the first four characters + cn.Write(readMagic) + + go pipe(c, cn, count) + go pipe(cn, c, count) + + } else { - go pipe(c, cn, count) - go pipe(cn, c, count) + cn, err := net.DialTCP("tcp", nil, conn) + if err != nil { + c.Close() + log.Print(err) + return + } + + go pipe(c, cn, count) + go pipe(cn, c, count) + + } } func pipe(w io.WriteCloser, r io.ReadCloser, count int) {