ssh/tailssh: add support for remote/reverse port forwarding

This basically allows running services on the SSH client and reaching
them from the SSH server during the session.

Updates #6575

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali
2023-06-08 18:39:27 -07:00
committed by Maisem Ali
parent 62130e6b68
commit 2e0aa151c9
4 changed files with 47 additions and 22 deletions

View File

@@ -99,7 +99,8 @@ type CapabilityVersion int
// - 60: 2023-04-06: Client understands IsWireGuardOnly
// - 61: 2023-04-18: Client understand SSHAction.SSHRecorderFailureAction
// - 62: 2023-05-05: Client can notify control over noise for SSHEventNotificationRequest recording failure events
const CurrentCapabilityVersion CapabilityVersion = 62
// - 63: 2023-06-08: Client understands SSHAction.AllowRemotePortForwarding.
const CurrentCapabilityVersion CapabilityVersion = 63
type StableID string
@@ -2048,6 +2049,10 @@ type SSHAction struct {
// to use local port forwarding if requested.
AllowLocalPortForwarding bool `json:"allowLocalPortForwarding,omitempty"`
// AllowRemotePortForwarding, if true, allows accepted connections
// to use remote port forwarding if requested.
AllowRemotePortForwarding bool `json:"allowRemotePortForwarding,omitempty"`
// Recorders defines the destinations of the SSH session recorders.
// The recording will be uploaded to http://addr:port/record.
Recorders []netip.AddrPort `json:"recorders,omitempty"`

View File

@@ -408,15 +408,16 @@ func (src *SSHAction) Clone() *SSHAction {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHActionCloneNeedsRegeneration = SSHAction(struct {
Message string
Reject bool
Accept bool
SessionDuration time.Duration
AllowAgentForwarding bool
HoldAndDelegate string
AllowLocalPortForwarding bool
Recorders []netip.AddrPort
OnRecordingFailure *SSHRecorderFailureAction
Message string
Reject bool
Accept bool
SessionDuration time.Duration
AllowAgentForwarding bool
HoldAndDelegate string
AllowLocalPortForwarding bool
AllowRemotePortForwarding bool
Recorders []netip.AddrPort
OnRecordingFailure *SSHRecorderFailureAction
}{})
// Clone makes a deep copy of SSHPrincipal.

View File

@@ -940,6 +940,7 @@ func (v SSHActionView) SessionDuration() time.Duration { return v.ж.Ses
func (v SSHActionView) AllowAgentForwarding() bool { return v.ж.AllowAgentForwarding }
func (v SSHActionView) HoldAndDelegate() string { return v.ж.HoldAndDelegate }
func (v SSHActionView) AllowLocalPortForwarding() bool { return v.ж.AllowLocalPortForwarding }
func (v SSHActionView) AllowRemotePortForwarding() bool { return v.ж.AllowRemotePortForwarding }
func (v SSHActionView) Recorders() views.Slice[netip.AddrPort] { return views.SliceOf(v.ж.Recorders) }
func (v SSHActionView) OnRecordingFailure() *SSHRecorderFailureAction {
if v.ж.OnRecordingFailure == nil {
@@ -951,15 +952,16 @@ func (v SSHActionView) OnRecordingFailure() *SSHRecorderFailureAction {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHActionViewNeedsRegeneration = SSHAction(struct {
Message string
Reject bool
Accept bool
SessionDuration time.Duration
AllowAgentForwarding bool
HoldAndDelegate string
AllowLocalPortForwarding bool
Recorders []netip.AddrPort
OnRecordingFailure *SSHRecorderFailureAction
Message string
Reject bool
Accept bool
SessionDuration time.Duration
AllowAgentForwarding bool
HoldAndDelegate string
AllowLocalPortForwarding bool
AllowRemotePortForwarding bool
Recorders []netip.AddrPort
OnRecordingFailure *SSHRecorderFailureAction
}{})
// View returns a readonly view of SSHPrincipal.