Skip to content

Commit

Permalink
Add ssh keep alive to ssh tunnel to workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
janekbaraniewski committed Nov 26, 2024
1 parent 188cadc commit c37f170
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions cmd/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ import (
"golang.org/x/crypto/ssh"
)

const (
DisableSSHKeepAlive time.Duration = 0 * time.Second
)

// SSHCmd holds the ssh cmd flags
type SSHCmd struct {
*flags.GlobalFlags
Expand All @@ -49,6 +53,9 @@ type SSHCmd struct {
GPGAgentForwarding bool
GitSSHSignatureForwarding bool

// ssh keepalive options
SSHKeepAliveInterval time.Duration `json:"sshKeepAliveInterval,omitempty"`

StartServices bool

Proxy bool
Expand Down Expand Up @@ -103,6 +110,7 @@ func NewSSHCmd(f *flags.GlobalFlags) *cobra.Command {
sshCmd.Flags().BoolVar(&cmd.GPGAgentForwarding, "gpg-agent-forwarding", false, "If true forward the local gpg-agent to the remote machine")
sshCmd.Flags().BoolVar(&cmd.Stdio, "stdio", false, "If true will tunnel connection through stdout and stdin")
sshCmd.Flags().BoolVar(&cmd.StartServices, "start-services", true, "If false will not start any port-forwarding or git / docker credentials helper")
sshCmd.Flags().DurationVar(&cmd.SSHKeepAliveInterval, "ssh-keepalive-interval", 55*time.Second, "How often should keepalive request be made (55s)")

return sshCmd
}
Expand Down Expand Up @@ -434,6 +442,10 @@ func (cmd *SSHCmd) startTunnel(ctx context.Context, devPodConfig *config.Config,
// Traffic is coming in from the outside, we need to forward it to the container
if cmd.Proxy || cmd.Stdio {
if cmd.Proxy {
if cmd.SSHKeepAliveInterval != DisableSSHKeepAlive {
go startSSHKeepAlive(ctx, containerClient, cmd.SSHKeepAliveInterval, log)
}

go func() {
if err := cmd.startRunnerServices(ctx, devPodConfig, containerClient, log); err != nil {
log.Error(err)
Expand All @@ -451,6 +463,9 @@ func (cmd *SSHCmd) startTunnel(ctx context.Context, devPodConfig *config.Config,
!cmd.Proxy && cmd.AgentForwarding &&
devPodConfig.ContextOption(config.ContextOptionSSHAgentForwarding) == "true",
func(ctx context.Context, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
if cmd.SSHKeepAliveInterval != DisableSSHKeepAlive {
go startSSHKeepAlive(ctx, containerClient, cmd.SSHKeepAliveInterval, log)
}
return devssh.Run(ctx, containerClient, command, stdin, stdout, stderr, envVars)
},
writer,
Expand Down Expand Up @@ -659,3 +674,20 @@ func preparePipes() (io.Reader, io.WriteCloser, io.Reader, io.WriteCloser, error

return stdoutReader, stdoutWriter, stdinReader, stdinWriter, nil
}

func startSSHKeepAlive(ctx context.Context, client *ssh.Client, interval time.Duration, log log.Logger) {
ticker := time.NewTicker(interval)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
return
case <-ticker.C:
_, _, err := client.SendRequest("[email protected]", true, nil)
if err != nil {
log.Errorf("Failed to send keepalive: %w", err)
}
}
}
}

0 comments on commit c37f170

Please sign in to comment.