feat(poller): add SSH relay server with WebSocket-to-PTY bridge

Implements the SSH relay server (Task 2.1) that validates single-use
Redis tokens via GETDEL, dials SSH to the target device with PTY,
and bridges WebSocket binary/text frames to SSH stdin/stdout/stderr
with idle timeout and per-user/per-device session limits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-12 15:33:48 -05:00
parent d3d3e36192
commit c73466c5e0
6 changed files with 550 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
package sshrelay
import (
"context"
"sync/atomic"
"time"
"golang.org/x/crypto/ssh"
)
type Session struct {
ID string
DeviceID string
TenantID string
UserID string
SourceIP string
StartTime time.Time
LastActive int64 // atomic, unix nanoseconds
sshClient *ssh.Client
sshSession *ssh.Session
ptyCols int
ptyRows int
cancel context.CancelFunc
}
func (s *Session) IdleDuration() time.Duration {
return time.Since(time.Unix(0, atomic.LoadInt64(&s.LastActive)))
}