Skip to content

Commit

Permalink
Add the ability to cancel tunnel requests (#311)
Browse files Browse the repository at this point in the history
* Add the ability to cancel tunnel requests

* No need to check for session with cancellations
  • Loading branch information
antoniomika authored Jul 11, 2024
1 parent b59cd1e commit c31c49e
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 7 deletions.
2 changes: 2 additions & 0 deletions sshmuxer/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ func handleRequest(newRequest *ssh.Request, sshConn *utils.SSHConnection, state
case "tcpip-forward":
go checkSession(newRequest, sshConn, state)
handleRemoteForward(newRequest, sshConn, state)
case "cancel-tcpip-forward":
handleCancelRemoteForward(newRequest, sshConn, state)
case "[email protected]":
err := newRequest.Reply(true, nil)
if err != nil {
Expand Down
70 changes: 66 additions & 4 deletions sshmuxer/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,55 @@ type forwardedTCPPayload struct {
OriginPort uint32
}

// handleCancelRemoteForward will handle a remote forward cancellation
// request and remove the relevant listeners.
func handleCancelRemoteForward(newRequest *ssh.Request, sshConn *utils.SSHConnection, state *utils.State) {
check := &channelForwardMsg{}

err := ssh.Unmarshal(newRequest.Payload, check)
if err != nil {
log.Println("Error unmarshaling remote forward payload:", err)
err = newRequest.Reply(false, nil)
if err != nil {
log.Println("Error replying to request:", err)
}
return
}

closed := false

sshConn.Listeners.Range(func(remoteAddr string, listener net.Listener) bool {
holder, ok := listener.(*utils.ListenerHolder)
if !ok {
return false
}

if holder.OriginalAddr == check.Addr && holder.OriginalPort == check.Rport {
closed = true
holder.Close()
return false
}

return true
})

if !closed {
log.Println("Unable to close tunnel")

err = newRequest.Reply(false, nil)
if err != nil {
log.Println("Error replying to request:", err)
}

return
}

err = newRequest.Reply(true, nil)
if err != nil {
log.Println("Error replying to request:", err)
}
}

// handleRemoteForward will handle a remote forward request
// and stand up the relevant listeners.
func handleRemoteForward(newRequest *ssh.Request, sshConn *utils.SSHConnection, state *utils.State) {
Expand All @@ -56,6 +105,17 @@ func handleRemoteForward(newRequest *ssh.Request, sshConn *utils.SSHConnection,
err := ssh.Unmarshal(newRequest.Payload, check)
if err != nil {
log.Println("Error unmarshaling remote forward payload:", err)

err = newRequest.Reply(false, nil)
if err != nil {
log.Println("Error replying to socket request:", err)
}
return
}

originalCheck := &channelForwardMsg{
Addr: check.Addr,
Rport: check.Rport,
}

originalAddress := check.Addr
Expand Down Expand Up @@ -131,10 +191,12 @@ func handleRemoteForward(newRequest *ssh.Request, sshConn *utils.SSHConnection,
}

listenerHolder := &utils.ListenerHolder{
ListenAddr: listenAddr,
Listener: chanListener,
Type: listenerType,
SSHConn: sshConn,
ListenAddr: listenAddr,
Listener: chanListener,
Type: listenerType,
SSHConn: sshConn,
OriginalAddr: originalCheck.Addr,
OriginalPort: originalCheck.Rport,
}

state.Listeners.Store(listenAddr, listenerHolder)
Expand Down
8 changes: 5 additions & 3 deletions utils/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ func (w LogWriter) Write(bytes []byte) (int, error) {
// ListenerHolder represents a generic listener.
type ListenerHolder struct {
net.Listener
ListenAddr string
Type ListenerType
SSHConn *SSHConnection
ListenAddr string
Type ListenerType
SSHConn *SSHConnection
OriginalAddr string
OriginalPort uint32
}

// HTTPHolder holds proxy and connection info.
Expand Down

0 comments on commit c31c49e

Please sign in to comment.