Skip to content

Commit

Permalink
fix: missing ssh client closes
Browse files Browse the repository at this point in the history
The webssh backend forgets to close ssh connects created by Sftp & CheckSSH.
It can make tons of orphaned sshd processes exhausting a target host.

This commit fixes the closing mechanism.
  • Loading branch information
cdfmlr committed Nov 19, 2022
1 parent cd611d2 commit d4a7d64
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 10 deletions.
3 changes: 3 additions & 0 deletions controller/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ func CheckSSH(c *gin.Context) *ResponseBody {
responseBody.Msg = err.Error()
return &responseBody
}

err = sshClient.GenerateClient()
defer sshClient.Close()

if err != nil {
fmt.Println(err)
responseBody.Msg = err.Error()
Expand Down
6 changes: 3 additions & 3 deletions controller/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func UploadFile(c *gin.Context) *ResponseBody {
responseBody.Msg = err.Error()
return &responseBody
}
defer sshClient.Sftp.Close()
defer sshClient.Close()
file, header, err := c.Request.FormFile("file")
if err != nil {
responseBody.Msg = err.Error()
Expand Down Expand Up @@ -157,7 +157,7 @@ func DownloadFile(c *gin.Context) *ResponseBody {
responseBody.Msg = err.Error()
return &responseBody
}
defer sshClient.Sftp.Close()
defer sshClient.Close()
if sftpFile, err := sshClient.Download(path); err != nil {
fmt.Println(err)
responseBody.Msg = err.Error()
Expand Down Expand Up @@ -228,7 +228,7 @@ func FileList(c *gin.Context) *ResponseBody {
responseBody.Msg = err.Error()
return &responseBody
}
defer sshClient.Sftp.Close()
defer sshClient.Close()
files, err := sshClient.Sftp.ReadDir(path)
if err != nil {
if strings.Contains(err.Error(), "exist") {
Expand Down
29 changes: 29 additions & 0 deletions core/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"io"
"log"
"unicode/utf8"
)

Expand Down Expand Up @@ -67,3 +68,31 @@ func NewSSHClient() SSHClient {
client.Port = 22
return client
}

// Close all closable fields of SSHClient that is opened:
//
// StdinPipe, Session, Sftp, Client
func (sclient *SSHClient) Close() {
defer func() { // just in case
if err := recover(); err != nil {
log.Println("SSHClient Close recover from panic: ", err)
}
}()

if sclient.StdinPipe != nil {
sclient.StdinPipe.Close()
sclient.StdinPipe = nil
}
if sclient.Session != nil {
sclient.Session.Close()
sclient.Session = nil
}
if sclient.Sftp != nil {
sclient.Sftp.Close()
sclient.Sftp = nil
}
if sclient.Client != nil {
sclient.Client.Close()
sclient.Client = nil
}
}
10 changes: 3 additions & 7 deletions core/sshclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func (sclient *SSHClient) Connect(ws *websocket.Conn, timeout time.Duration, clo
err := sclient.Session.WindowChange(rows, cols)
if err != nil {
log.Println(err)
close(stopCh)
return
}
continue
Expand All @@ -135,13 +136,8 @@ func (sclient *SSHClient) Connect(ws *websocket.Conn, timeout time.Duration, clo

defer func() {
ws.Close()
if sclient.Session != nil {
sclient.StdinPipe.Close()
sclient.Session.Close()
sclient.Client.Close()
sclient.Session = nil
sclient.Client = nil
}
sclient.Close()

if err := recover(); err != nil {
log.Println(err)
}
Expand Down

0 comments on commit d4a7d64

Please sign in to comment.