update working ssh shell

This commit is contained in:
2024-11-06 06:24:14 +00:00
parent acd843d31c
commit 86eb5eb4e6
12 changed files with 1789 additions and 2183 deletions
+7
View File
@@ -1,3 +1,10 @@
module rul.sh/vaulterm
go 1.21.1
require golang.org/x/crypto v0.28.0
require (
github.com/coder/websocket v1.8.12
golang.org/x/sys v0.26.0 // indirect
)
+8
View File
@@ -0,0 +1,8 @@
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
+155
View File
@@ -1,4 +1,159 @@
package main
import (
"context"
"io"
"log"
"net/http"
"strconv"
"strings"
"github.com/coder/websocket"
"golang.org/x/crypto/ssh"
)
// Replace with actual SSH server credentials
var sshHost = "10.0.0.102"
var sshUser = "root"
var sshPassword = "ausya2"
func sshWebSocketHandler(w http.ResponseWriter, r *http.Request) {
wsConn, err := websocket.Accept(w, r, &websocket.AcceptOptions{
OriginPatterns: []string{"*"}, // Adjust origin policy as needed
})
if err != nil {
log.Printf("failed to accept websocket: %v", err)
return
}
// Set up SSH client configuration
sshConfig := &ssh.ClientConfig{
User: sshUser,
Auth: []ssh.AuthMethod{
ssh.Password(sshPassword),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// Connect to SSH server
sshConn, err := ssh.Dial("tcp", sshHost+":22", sshConfig)
if err != nil {
wsConn.Write(context.Background(), websocket.MessageText, []byte(err.Error()))
wsConn.Close(websocket.StatusInternalError, "failed to connect to SSH")
return
}
defer sshConn.Close()
// Start an SSH shell session
session, err := sshConn.NewSession()
if err != nil {
wsConn.Write(context.Background(), websocket.MessageText, []byte(err.Error()))
wsConn.Close(websocket.StatusInternalError, "failed to start SSH session")
return
}
defer session.Close()
stdoutPipe, err := session.StdoutPipe()
if err != nil {
wsConn.Close(websocket.StatusInternalError, "failed to get stdout pipe")
return
}
stderrPipe, err := session.StderrPipe()
if err != nil {
wsConn.Close(websocket.StatusInternalError, "failed to get stderr pipe")
return
}
stdinPipe, err := session.StdinPipe()
if err != nil {
wsConn.Close(websocket.StatusInternalError, "failed to get stdin pipe")
return
}
err = session.RequestPty("xterm-256color", 80, 24, ssh.TerminalModes{})
if err != nil {
wsConn.Close(websocket.StatusInternalError, "failed to request pty")
return
}
if err := session.Shell(); err != nil {
wsConn.Close(websocket.StatusInternalError, "failed to start shell")
return
}
// Goroutine to send SSH stdout to WebSocket
go func() {
buf := make([]byte, 1024)
for {
n, err := stdoutPipe.Read(buf)
if err != nil {
if err != io.EOF {
log.Printf("error reading from SSH stdout: %v", err)
}
break
}
if writeErr := wsConn.Write(context.Background(), websocket.MessageBinary, buf[:n]); writeErr != nil {
log.Printf("error writing to websocket: %v", writeErr)
break
}
}
}()
// Goroutine to handle SSH stderr
go func() {
buf := make([]byte, 1024)
for {
n, err := stderrPipe.Read(buf)
if err != nil {
if err != io.EOF {
log.Printf("error reading from SSH stderr: %v", err)
}
break
}
if writeErr := wsConn.Write(context.Background(), websocket.MessageBinary, buf[:n]); writeErr != nil {
log.Printf("error writing to websocket: %v", writeErr)
break
}
}
}()
// Handle WebSocket to SSH data streaming
go func() {
for {
_, msg, err := wsConn.Read(context.Background())
if err != nil {
return
}
if strings.HasPrefix(string(msg), "\x01") {
parts := strings.Split(string(msg[1:]), ",")
if len(parts) == 2 {
width, _ := strconv.Atoi(parts[0])
height, _ := strconv.Atoi(parts[1])
session.WindowChange(height, width)
}
} else {
stdinPipe.Write(msg)
}
}
}()
// Wait for the SSH session to close
if err := session.Wait(); err != nil {
log.Printf("SSH session ended with error: %v", err)
wsConn.Write(context.Background(), websocket.MessageText, []byte(err.Error()))
} else {
log.Println("SSH session ended normally")
}
// Ensure WebSocket is closed after SSH logout
wsConn.Close(websocket.StatusNormalClosure, "SSH session closed")
}
func main() {
http.HandleFunc("/ws", sshWebSocketHandler)
log.Println("Server started on :3000")
log.Fatal(http.ListenAndServe(":3000", nil))
}