]> Cypherpunks repositories - gostls13.git/commitdiff
net: avoid opening an external port in TestDialListenerAddr
authorBryan C. Mills <bcmills@google.com>
Mon, 10 Apr 2023 13:59:12 +0000 (13:59 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 10 Apr 2023 22:52:22 +0000 (22:52 +0000)
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 <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>

src/net/dial_test.go

index b04607e48f150996bc9cfdf5749ebc886bb5e1b2..d25a642a0ad7e7a1a3d973745c2043b879fd947a 100644 (file)
@@ -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) {