@@ -6,13 +6,10 @@ import (
6
6
"errors"
7
7
"fmt"
8
8
"io"
9
- "net"
10
9
"net/url"
11
10
"os"
12
11
"os/exec"
13
12
"path/filepath"
14
- "regexp"
15
- "strconv"
16
13
"strings"
17
14
"sync"
18
15
"time"
@@ -29,7 +26,6 @@ import (
29
26
"cdr.dev/slog"
30
27
"cdr.dev/slog/sloggers/sloghuman"
31
28
32
- "github.com/coder/coder/agent/agentssh"
33
29
"github.com/coder/coder/cli/clibase"
34
30
"github.com/coder/coder/cli/cliui"
35
31
"github.com/coder/coder/coderd/autobuild/notify"
@@ -42,8 +38,6 @@ import (
42
38
var (
43
39
workspacePollInterval = time .Minute
44
40
autostopNotifyCountdown = []time.Duration {30 * time .Minute }
45
-
46
- remoteForwardRegex = regexp .MustCompile (`^(\d+):(.+):(\d+)$` )
47
41
)
48
42
49
43
//nolint:gocyclo
@@ -128,7 +122,7 @@ func (r *RootCmd) ssh() *clibase.Cmd {
128
122
}
129
123
130
124
if remoteForward != "" {
131
- isValid := remoteForwardRegex . MatchString (remoteForward )
125
+ isValid := validateRemoteForward (remoteForward )
132
126
if ! isValid {
133
127
return xerrors .Errorf (`invalid format of remote-forward, expected: remote_port:local_address:local_port` )
134
128
}
@@ -317,31 +311,9 @@ func (r *RootCmd) ssh() *clibase.Cmd {
317
311
}
318
312
319
313
if remoteForward != "" {
320
- matches := remoteForwardRegex .FindStringSubmatch (remoteForward )
321
-
322
- // Format:
323
- // remote_port:local_address:local_port
324
- remotePort , err := strconv .Atoi (matches [1 ])
325
- if err != nil {
326
- return xerrors .Errorf ("remote port is invalid: %w" , err )
327
- }
328
- localAddress , err := net .ResolveIPAddr ("ip" , matches [2 ])
329
- if err != nil {
330
- return xerrors .Errorf ("local address is invalid: %w" , err )
331
- }
332
- localPort , err := strconv .Atoi (matches [3 ])
314
+ localAddr , remoteAddr , err := parseRemoteForward (remoteForward )
333
315
if err != nil {
334
- return xerrors .Errorf ("local port is invalid: %w" , err )
335
- }
336
-
337
- localAddr := & net.TCPAddr {
338
- IP : localAddress .IP ,
339
- Port : localPort ,
340
- }
341
-
342
- remoteAddr := & net.TCPAddr {
343
- IP : net .ParseIP ("127.0.0.1" ),
344
- Port : remotePort ,
316
+ return err
345
317
}
346
318
347
319
closer , err := sshRemoteForward (ctx , inv .Stderr , sshClient , localAddr , remoteAddr )
@@ -817,56 +789,3 @@ func remoteGPGAgentSocket(sshClient *gossh.Client) (string, error) {
817
789
818
790
return string (bytes .TrimSpace (remoteSocket )), nil
819
791
}
820
-
821
- // cookieAddr is a special net.Addr accepted by sshRemoteForward() which includes a
822
- // cookie which is written to the connection before forwarding.
823
- type cookieAddr struct {
824
- net.Addr
825
- cookie []byte
826
- }
827
-
828
- // sshRemoteForward starts forwarding connections from a remote listener to a
829
- // local address via SSH in a goroutine.
830
- //
831
- // Accepts a `cookieAddr` as the local address.
832
- func sshRemoteForward (ctx context.Context , stderr io.Writer , sshClient * gossh.Client , localAddr , remoteAddr net.Addr ) (io.Closer , error ) {
833
- listener , err := sshClient .Listen (remoteAddr .Network (), remoteAddr .String ())
834
- if err != nil {
835
- return nil , xerrors .Errorf ("listen on remote SSH address %s: %w" , remoteAddr .String (), err )
836
- }
837
-
838
- go func () {
839
- for {
840
- remoteConn , err := listener .Accept ()
841
- if err != nil {
842
- if ctx .Err () == nil {
843
- _ , _ = fmt .Fprintf (stderr , "Accept SSH listener connection: %+v\n " , err )
844
- }
845
- return
846
- }
847
-
848
- go func () {
849
- defer remoteConn .Close ()
850
-
851
- localConn , err := net .Dial (localAddr .Network (), localAddr .String ())
852
- if err != nil {
853
- _ , _ = fmt .Fprintf (stderr , "Dial local address %s: %+v\n " , localAddr .String (), err )
854
- return
855
- }
856
- defer localConn .Close ()
857
-
858
- if c , ok := localAddr .(cookieAddr ); ok {
859
- _ , err = localConn .Write (c .cookie )
860
- if err != nil {
861
- _ , _ = fmt .Fprintf (stderr , "Write cookie to local connection: %+v\n " , err )
862
- return
863
- }
864
- }
865
-
866
- agentssh .Bicopy (ctx , localConn , remoteConn )
867
- }()
868
- }
869
- }()
870
-
871
- return listener , nil
872
- }
0 commit comments