Idea
I wake up once and had an idea to write simple SSH to WebSocket repository with simple UI. Without anything else. A snippet, nothing too complicated.
xterm + gorilla websocket + crypto/ssh = solution
I quickly checked and realized that whole stack is here — gorilla websocket for mixing ssh tunnel with websocket, and crypto/ssh to establish connection. TIME TO CODE
Code is simpler than I expected
func sshHandler(w http.ResponseWriter, r *http.Request) {
 // ...
 wsConn, err := upgrader.Upgrade(w, r, nil)
 if err != nil {
  log.Println("Upgrade error:", err)
  return
 }
 defer wsConn.Close()
 config := &ssh.ClientConfig{
  User: user,
  Auth: []ssh.AuthMethod{
   ssh.Password(pass),
  },
  HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 }
 sshConn, err := ssh.Dial("tcp", hostport, config)
 if err != nil {
  log.Println("SSH dial error:", err)
  return
 }
 defer sshConn.Close()
 session, err := sshConn.NewSession()
 if err != nil {
  log.Println("SSH session error:", err)
  return
 }
 defer session.Close()
 sshOut, err := session.StdoutPipe()
 if err != nil {
  log.Println("STDOUT pipe error:", err)
  return
 }
 sshIn, err := session.StdinPipe()
 if err != nil {
  log.Println("STDIN pipe error:", err)
  return
 }
 // Here change 80 and 40 because it request this size of window
 if err := session.RequestPty("xterm", 80, 40, ssh.TerminalModes{}); err != nil {
  log.Println("Request PTY error:", err)
  return
 }
 if err := session.Shell(); err != nil {
  log.Println("Start shell error:", err)
  return
 }
 // Async reader and writer to websocket
 go func() {
  defer session.Close()
  buf := make([]byte, 1024)
  for {
   n, err := sshOut.Read(buf)
   if err != nil {
    if err != io.EOF {
     log.Println("Read from SSH stdout error:", err)
    }
    return
   }
   if n > 0 {
    err = wsConn.WriteMessage(websocket.BinaryMessage, buf[:n])
    if err != nil {
     log.Println("Write to WebSocket error:", err)
     return
    }
   }
  }
 }()
 // Sync websocket reader and writer to sshIn
 for {
  messageType, p, err := wsConn.ReadMessage()
  if err != nil {
   if err != io.EOF {
    log.Println("Read from WebSocket error:", err)
   }
   return
  }
  if messageType == websocket.BinaryMessage || messageType == websocket.TextMessage {
   _, err = sshIn.Write(p)
   if err != nil {
    log.Println("Write to SSH stdin error:", err)
    return
   }
  }
 }
}Summary
In this example there is no any authentication or selecting of SSH key. Treat is as an snipped. Hope its useful!
Check the full repository over there:
GitHub - Razikus/go-ssh-to-websocket: Super simple SSH to websocket written in GO. With XTERM…
Super simple SSH to websocket written in GO. With XTERM example to consume also - Razikus/go-ssh-to-websocketgithub.com


