Skip to content

Commit d668992

Browse files
committed
Reject out-of-range ports in the TCP benchmark proxy
A netstack listen or forwarding port of 65537 wraps to port 1. A bad forwarding address can also leave the proxy retrying a connection that cannot succeed. Parse the listen port at its 16-bit width and the netstack destination as a numeric address and port before opening network devices. Keep the native dialer's DNS and service-name lookup on each connection attempt.
1 parent 7bffefa commit d668992

1 file changed

Lines changed: 47 additions & 54 deletions

File tree

‎test/benchmarks/tcp/tcp_proxy.go‎

Lines changed: 47 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"io"
2323
"log"
2424
"net"
25+
"net/netip"
2526
"os"
2627
"os/signal"
2728
"regexp"
@@ -48,10 +49,10 @@ import (
4849
)
4950

5051
var (
51-
port = flag.Int("port", 0, "bind port (all addresses)")
52+
portArg = flag.String("port", "0", "bind port (all addresses)")
5253
forward = flag.String("forward", "", "forwarding target")
53-
client = flag.Bool("client", false, "use netstack for listen")
54-
server = flag.Bool("server", false, "use netstack for dial")
54+
client = flag.Bool("client", false, "use netstack for dial")
55+
server = flag.Bool("server", false, "use netstack for listen")
5556

5657
// Netstack-specific options.
5758
mtu = flag.Int("mtu", 1280, "mtu for network stack")
@@ -78,22 +79,17 @@ var (
7879
)
7980

8081
type impl interface {
81-
dial(address string) (net.Conn, error)
82-
listen(port int) (net.Listener, error)
82+
listen(port uint16) (net.Listener, error)
8383
printStats()
8484
}
8585

8686
type netImpl struct{}
8787

88-
func (netImpl) dial(address string) (net.Conn, error) {
89-
return net.Dial("tcp", address)
90-
}
91-
92-
func (netImpl) listen(port int) (net.Listener, error) {
88+
func (*netImpl) listen(port uint16) (net.Listener, error) {
9389
return net.Listen("tcp", fmt.Sprintf(":%d", port))
9490
}
9591

96-
func (netImpl) printStats() {
92+
func (*netImpl) printStats() {
9793
}
9894

9995
const (
@@ -159,7 +155,7 @@ func setupNetwork(ifaceName string, numChannels int) (fds []int, err error) {
159155
return nil, fmt.Errorf("failed to find interface: %v", ifaceName)
160156
}
161157

162-
func newNetstackImpl(mode, probeFileName string) (impl, func() error, error) {
158+
func newNetstackImpl(mode, probeFileName string) (*netstackImpl, func() error, error) {
163159
// Parse details.
164160
var parsedAddr tcpip.Address
165161
if *useIpv6 {
@@ -327,30 +323,18 @@ func newNetstackImpl(mode, probeFileName string) (impl, func() error, error) {
327323
}
328324
}
329325

330-
return netstackImpl{
326+
return &netstackImpl{
331327
s: s,
332328
addr: parsedAddr,
333329
mode: mode,
334330
}, probeFile.Close, nil
335331
}
336332

337-
func (n netstackImpl) dial(address string) (net.Conn, error) {
338-
host, port, err := net.SplitHostPort(address)
339-
if err != nil {
340-
return nil, err
341-
}
342-
if host == "" {
343-
// A host must be provided for the dial.
344-
return nil, fmt.Errorf("no host provided")
345-
}
346-
portNumber, err := strconv.Atoi(port)
347-
if err != nil {
348-
return nil, err
349-
}
333+
func (n *netstackImpl) dial(remote netip.AddrPort) (net.Conn, error) {
350334
addr := tcpip.FullAddress{
351335
NIC: nicID,
352-
Addr: tcpip.AddrFromSlice(net.ParseIP(host)),
353-
Port: uint16(portNumber),
336+
Addr: tcpip.AddrFrom16(remote.Addr().As16()),
337+
Port: remote.Port(),
354338
}
355339
proto := ipv4.ProtocolNumber
356340
if *useIpv6 {
@@ -363,10 +347,10 @@ func (n netstackImpl) dial(address string) (net.Conn, error) {
363347
return conn, nil
364348
}
365349

366-
func (n netstackImpl) listen(port int) (net.Listener, error) {
350+
func (n *netstackImpl) listen(port uint16) (net.Listener, error) {
367351
addr := tcpip.FullAddress{
368352
NIC: nicID,
369-
Port: uint16(port),
353+
Port: port,
370354
}
371355
proto := ipv4.ProtocolNumber
372356
if *useIpv6 {
@@ -381,20 +365,34 @@ func (n netstackImpl) listen(port int) (net.Listener, error) {
381365

382366
var zeroFieldsRegexp = regexp.MustCompile(`\s*[a-zA-Z0-9]*:0`)
383367

384-
func (n netstackImpl) printStats() {
368+
func (n *netstackImpl) printStats() {
385369
// Don't show zero fields.
386370
stats := zeroFieldsRegexp.ReplaceAllString(fmt.Sprintf("%+v", n.s.Stats()), "")
387371
log.Printf("netstack %s Stats: %+v\n", n.mode, stats)
388372
}
389373

390374
func main() {
391375
flag.Parse()
392-
if *port == 0 {
376+
port, err := strconv.ParseUint(*portArg, 0, 16)
377+
if err != nil {
378+
log.Fatalf("invalid listen port: %v", err)
379+
}
380+
if port == 0 {
393381
log.Fatalf("no port provided")
394382
}
395383
if *forward == "" {
396384
log.Fatalf("no forward provided")
397385
}
386+
var target netip.AddrPort
387+
if *client {
388+
target, err = netip.ParseAddrPort(*forward)
389+
if err != nil {
390+
log.Fatalf("invalid forwarding target: %v", err)
391+
}
392+
if target.Addr().Zone() != "" {
393+
log.Fatalf("netstack forwarding uses -iface; omit the zone in %q", *forward)
394+
}
395+
}
398396
if *cpuprofile != "" {
399397
f, err := os.Create(*cpuprofile)
400398
if err != nil {
@@ -440,36 +438,31 @@ func main() {
440438
runtime.SetBlockProfileRate(1000)
441439
}
442440

443-
var (
444-
in impl
445-
out impl
446-
err error
447-
cleanup func() error
448-
)
441+
var in impl = &netImpl{}
449442
if *server {
450-
in, cleanup, err = newNetstackImpl("server", *serverTCPProbeFile)
443+
n, cleanup, err := newNetstackImpl("server", *serverTCPProbeFile)
444+
if err != nil {
445+
log.Fatalf("netstack error: %v", err)
446+
}
451447
defer cleanup()
452-
453-
} else {
454-
in = netImpl{}
455-
}
456-
if err != nil {
457-
log.Fatalf("netstack error: %v", err)
448+
in = n
458449
}
450+
var out impl = &netImpl{}
451+
dial := func() (net.Conn, error) { return net.Dial("tcp", *forward) }
459452
if *client {
460-
out, cleanup, err = newNetstackImpl("client", *clientTCPProbeFile)
453+
n, cleanup, err := newNetstackImpl("client", *clientTCPProbeFile)
454+
if err != nil {
455+
log.Fatalf("netstack error: %v", err)
456+
}
461457
defer cleanup()
462-
} else {
463-
out = netImpl{}
464-
}
465-
if err != nil {
466-
log.Fatalf("netstack error: %v", err)
458+
out = n
459+
dial = func() (net.Conn, error) { return n.dial(target) }
467460
}
468461

469462
// Dial forward before binding.
470463
var next net.Conn
471464
for {
472-
next, err = out.dial(*forward)
465+
next, err = dial()
473466
if err == nil {
474467
break
475468
}
@@ -478,7 +471,7 @@ func main() {
478471
}
479472

480473
// Bind once to the server socket.
481-
listener, err := in.listen(*port)
474+
listener, err := in.listen(uint16(port))
482475
if err != nil {
483476
// Should not happen, everything must be bound by this time
484477
// this proxy is started.
@@ -523,7 +516,7 @@ func main() {
523516

524517
for {
525518
// Dial again.
526-
next, err = out.dial(*forward)
519+
next, err = dial()
527520
if err == nil {
528521
break
529522
}

0 commit comments

Comments
 (0)