我已经能够使用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吗?
答案 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.Conn
是ReadWriter
,因此它可以是io.Copy
的来源和目的地。 Cmd.StdoutPipe
和Session.StdoutPipe
都是io.Reader
,Stdin
版本是io.Writer
。所以一切都应该粘在一起就好了。你只需要双向复制。
go io.Copy(targetStdin, wsconn)
io.Copy(wsconn, targetStdout)