4
4
"context"
5
5
"fmt"
6
6
"net"
7
+ "net/netip"
7
8
"os"
8
9
"os/signal"
9
10
"strconv"
@@ -47,6 +48,10 @@ func (r *RootCmd) portForward() *clibase.Cmd {
47
48
Description : "Port forward multiple ports (TCP or UDP) in condensed syntax" ,
48
49
Command : "coder port-forward <workspace> --tcp 8080,9000:3000,9090-9092,10000-10002:10010-10012" ,
49
50
},
51
+ example {
52
+ Description : "Port forward specifying the local address to bind to" ,
53
+ Command : "coder port-forward <workspace> --tcp 1.2.3.4:8080:8080" ,
54
+ },
50
55
),
51
56
Middleware : clibase .Chain (
52
57
clibase .RequireNArgs (1 ),
@@ -255,9 +260,9 @@ func parsePortForwards(tcpSpecs, udpSpecs []string) ([]portForwardSpec, error) {
255
260
for _ , port := range ports {
256
261
specs = append (specs , portForwardSpec {
257
262
listenNetwork : "tcp" ,
258
- listenAddress : fmt . Sprintf ( "127.0.0.1:%v" , port .local ),
263
+ listenAddress : port .local . String ( ),
259
264
dialNetwork : "tcp" ,
260
- dialAddress : fmt . Sprintf ( "127.0.0.1:%v" , port .remote ),
265
+ dialAddress : port .remote . String ( ),
261
266
})
262
267
}
263
268
}
@@ -273,9 +278,9 @@ func parsePortForwards(tcpSpecs, udpSpecs []string) ([]portForwardSpec, error) {
273
278
for _ , port := range ports {
274
279
specs = append (specs , portForwardSpec {
275
280
listenNetwork : "udp" ,
276
- listenAddress : fmt . Sprintf ( "127.0.0.1:%v" , port .local ),
281
+ listenAddress : port .local . String ( ),
277
282
dialNetwork : "udp" ,
278
- dialAddress : fmt . Sprintf ( "127.0.0.1:%v" , port .remote ),
283
+ dialAddress : port .remote . String ( ),
279
284
})
280
285
}
281
286
}
@@ -307,29 +312,57 @@ func parsePort(in string) (uint16, error) {
307
312
}
308
313
309
314
type parsedSrcDestPort struct {
310
- local , remote uint16
315
+ local , remote netip. AddrPort
311
316
}
312
317
313
318
func parseSrcDestPorts (in string ) ([]parsedSrcDestPort , error ) {
314
- parts := strings .Split (in , ":" )
315
- if len (parts ) > 2 {
316
- return nil , xerrors .Errorf ("invalid port specification %q" , in )
317
- }
318
- if len (parts ) == 1 {
319
+ var (
320
+ err error
321
+ parts = strings .Split (in , ":" )
322
+ localAddr = netip .AddrFrom4 ([4 ]byte {127 , 0 , 0 , 1 })
323
+ remoteAddr = netip .AddrFrom4 ([4 ]byte {127 , 0 , 0 , 1 })
324
+ )
325
+
326
+ switch len (parts ) {
327
+ case 1 :
319
328
// Duplicate the single part
320
329
parts = append (parts , parts [0 ])
330
+ case 2 :
331
+ // Check to see if the first part is an IP address.
332
+ _localAddr , err := netip .ParseAddr (parts [0 ])
333
+ if err != nil {
334
+ break
335
+ }
336
+ // The first part is the local address, so duplicate the port.
337
+ localAddr = _localAddr
338
+ parts = []string {parts [1 ], parts [1 ]}
339
+
340
+ case 3 :
341
+ _localAddr , err := netip .ParseAddr (parts [0 ])
342
+ if err != nil {
343
+ return nil , xerrors .Errorf ("invalid port specification %q; invalid ip %q: %w" , in , parts [0 ], err )
344
+ }
345
+ localAddr = _localAddr
346
+ parts = parts [1 :]
347
+
348
+ default :
349
+ return nil , xerrors .Errorf ("invalid port specification %q" , in )
321
350
}
351
+
322
352
if ! strings .Contains (parts [0 ], "-" ) {
323
- local , err := parsePort (parts [0 ])
353
+ localPort , err := parsePort (parts [0 ])
324
354
if err != nil {
325
355
return nil , xerrors .Errorf ("parse local port from %q: %w" , in , err )
326
356
}
327
- remote , err := parsePort (parts [1 ])
357
+ remotePort , err := parsePort (parts [1 ])
328
358
if err != nil {
329
359
return nil , xerrors .Errorf ("parse remote port from %q: %w" , in , err )
330
360
}
331
361
332
- return []parsedSrcDestPort {{local : local , remote : remote }}, nil
362
+ return []parsedSrcDestPort {{
363
+ local : netip .AddrPortFrom (localAddr , localPort ),
364
+ remote : netip .AddrPortFrom (remoteAddr , remotePort ),
365
+ }}, nil
333
366
}
334
367
335
368
local , err := parsePortRange (parts [0 ])
@@ -346,8 +379,8 @@ func parseSrcDestPorts(in string) ([]parsedSrcDestPort, error) {
346
379
var out []parsedSrcDestPort
347
380
for i := range local {
348
381
out = append (out , parsedSrcDestPort {
349
- local : local [i ],
350
- remote : remote [i ],
382
+ local : netip . AddrPortFrom ( localAddr , local [i ]) ,
383
+ remote : netip . AddrPortFrom ( remoteAddr , remote [i ]) ,
351
384
})
352
385
}
353
386
return out , nil
0 commit comments