Golang:在websocket上转发ssh

时间:2015-05-26 08:06:02

标签: ssh go websocket

我已经能够使用golang将telnet转发到websocket,使用类似

的东西
func forwardtcp(wsconn *websocket.Conn, conn *telnet.Conn) {
    connbuf := bufio.NewReader(conn)
    tcpbuffer := make([]byte, 128)

    for {
        n, err := connbuf.Read(tcpbuffer)

        if err != nil {
            log.Println("TCP Read failed")
            break
        }
        if err == nil {
            wsconn.WriteMessage(websocket.BinaryMessage, tcpbuffer[:n])
        }
    }
}

但是我无法用SSH或shell会话做类似的事情。我不理解使用

的基本概念
targetStdout, _ := session.StdoutPipe()
targetStdin, _ := session.StdinPipe()

件。

我可以使用io.Copy,但不知道如何将这些格式化为可以与websocket连接一起发送的数据报。

是否可以以可以使用字节读取和写入的方式处理targetStdin和targetStdout管道,例如从websocket连接接收的那些? 或者有更好的方法从SSH连接获取io吗?

2 个答案:

答案 0 :(得分:1)

如果要将SSH用于远程shell会话,则不应使用websocket包,而应使用golang.org/x/crypto/ssh包。 godoc.org有一个很好的例子,我在此重复一遍:

// An SSH client is represented with a ClientConn. Currently only
// the "password" authentication method is supported.
//
// To authenticate with the remote server you must pass at least one
// implementation of AuthMethod via the Auth field in ClientConfig.
config := &ssh.ClientConfig{
    User: "username",
    Auth: []ssh.AuthMethod{
        ssh.Password("yourpassword"),
    },
}
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
if err != nil {
    panic("Failed to dial: " + err.Error())
}

// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
session, err := client.NewSession()
if err != nil {
    panic("Failed to create session: " + err.Error())
}
defer session.Close()

// Once a Session is created, you can execute a single command on
// the remote side using the Run method.
var b bytes.Buffer
session.Stdout = &b
if err := session.Run("/usr/bin/whoami"); err != nil {
    panic("Failed to run: " + err.Error())
}
fmt.Println(b.String())

您可能希望使用ssh.Session结构的字段,而不是使用StdoutPipe()

type Session struct {
    Stdin io.Reader
    Stdout io.Writer
    Stderr io.Writer
}

示例session.Stdout = &b中的行表示远程进程的stdout将写入b。同样,您可以将任何io.Reader分配给session.Stdin,这将由远程进程读取为stdin。 ssh.Session的详细行为可以在godoc.org

找到

答案 1 :(得分:1)

websocket.ConnReadWriter,因此它可以是io.Copy的来源和目的地。 Cmd.StdoutPipeSession.StdoutPipe都是io.ReaderStdin版本是io.Writer。所以一切都应该粘在一起就好了。你只需要双向复制。

go io.Copy(targetStdin, wsconn)
io.Copy(wsconn, targetStdout)