From f00c54146ca0d9663f16f8ef2ea87862dc936ce3 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 10 Apr 2023 13:59:12 +0000 Subject: [PATCH] net: avoid opening an external port in TestDialListenerAddr The behavior in #18806 can be tested with a localhost-only port, provided that we're willing to assume what format the listener would report for an external dual-stack port. Fixes #59497. Change-Id: I171fb03eb46aee8e85480e04626a23f4f3b923e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/482163 Auto-Submit: Bryan Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Bryan Mills --- src/net/dial_test.go | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/net/dial_test.go b/src/net/dial_test.go index b04607e48f..d25a642a0a 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -884,17 +884,49 @@ func TestCancelAfterDial(t *testing.T) { // "::" not connect back to that same address. func TestDialListenerAddr(t *testing.T) { mustHaveExternalNetwork(t) - ln, err := Listen("tcp", ":0") + + if !testableNetwork("tcp4") { + t.Skipf("skipping: can't listen on tcp4") + } + + // The original issue report was for listening on just ":0" on a system that + // supports both tcp4 and tcp6 for external traffic but only tcp4 for loopback + // traffic. However, the port opened by ":0" is externally-accessible, and may + // trigger firewall alerts or otherwise be mistaken for malicious activity + // (see https://go.dev/issue/59497). Moreover, it often does not reproduce + // the scenario in the issue, in which the port *cannot* be dialed as tcp6. + // + // To address both of those problems, we open a tcp4-only localhost port, but + // then dial the address string that the listener would have reported for a + // dual-stack port. + ln, err := Listen("tcp4", "localhost:0") if err != nil { t.Fatal(err) } defer ln.Close() - addr := ln.Addr().String() - c, err := Dial("tcp", addr) + + t.Logf("listening on %q", ln.Addr()) + _, port, err := SplitHostPort(ln.Addr().String()) + if err != nil { + t.Fatal(err) + } + + // If we had opened a dual-stack port without an explicit "localhost" address, + // the Listener would arbitrarily report an empty tcp6 address in its Addr + // string. + // + // The documentation for Dial says ‘if the host is empty or a literal + // unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80" for TCP and + // UDP, "", "0.0.0.0" or "::" for IP, the local system is assumed.’ + // In #18806, it was decided that that should include the local tcp4 host + // even if the string is in the tcp6 format. + dialAddr := "[::]:" + port + c, err := Dial("tcp4", dialAddr) if err != nil { - t.Fatalf("for addr %q, dial error: %v", addr, err) + t.Fatalf(`Dial("tcp4", %q): %v`, dialAddr, err) } c.Close() + t.Logf(`Dial("tcp4", %q) succeeded`, dialAddr) } func TestDialerControl(t *testing.T) { -- 2.48.1