Go binds the unspecified IPv6 address (::) to its IPv4 equivalent (0.0.0.0) because of questionable software in the ecosystem and the fact that OpenBSD does not support dual-family sockets; (incomplete) history:
- https://github.com/golang/go/issues/18806 - https://go-review.googlesource.com/c/go/+/47554 So net.Listen("tcp", "[::]:1234") won't use IPv6 unless you use "tcp6". Ports I use do not expose a knob for the address family ("network" in Go), so using ":1234" or "[::]:1234" never uses IPv6 and specific IPv6 addresses lack the catch-all semantic often required. net.Dial() to connect to a remote socket has the same problem. See the links above for why Go behaves that way. I'd like to fix that such that configs like "[::]:1234" on OpenBSD allow me to listen on all IPv6 addresses, like it should. With multimedia/dms I ran into https://github.com/anacrolix/dms/pull/171, where we made dms flip the network to "tcp6" in case of the unspecified address to fix this, but that is an application hack for a runtime problem on a niche OS and not viable. Below is a test program (expects, e.g. httpd(8) listening on *, 80/tcp) demonstrating Dial() and Listen() across all networks and addresses: - tcp, :: now listens on :: instead of 0.0.0.0 - tcp4, :: now errors instead of connects to/listens on 127.0.0.1/0.0.0.0 - rest remains unchanged Neither the patch, nor the final behaviour is perfect, but it fixes two things while, seemingly, not breaking others. Feedback? $ netstat -na | grep -w 80 tcp 0 0 *.80 *.* LISTEN tcp6 0 0 *.80 *.* LISTEN $ cat test.go package main import ( "fmt" "net" ) func main() { fmt.Printf("%4s %9s %9s %9s\n\n", "net", "addr", "Dial()", "Listen()") for _, n := range []string{"tcp", "tcp4", "tcp6"} { for _, a := range []string{"", "0.0.0.0", "127.0.0.1", "[::]", "[::1]", "localhost"} { fmt.Printf("%4s %9s", n, a) d, dErr := net.Dial(n, a+":80") if dErr == nil { fmt.Printf(" %9s", d.RemoteAddr().(*net.TCPAddr).IP) d.Close() } l, lErr := net.Listen(n, a+":") if lErr == nil { fmt.Printf(" %9s", l.Addr().(*net.TCPAddr).IP) l.Close() } fmt.Printf("\n") if dErr != nil { fmt.Printf("%80s\n", dErr) } if lErr != nil { fmt.Printf("%80s\n", lErr) } } } } $ go run test.go | tee current net addr Dial() Listen() tcp 127.0.0.1 0.0.0.0 tcp 0.0.0.0 127.0.0.1 0.0.0.0 tcp 127.0.0.1 127.0.0.1 127.0.0.1 tcp [::] 127.0.0.1 0.0.0.0 tcp [::1] ::1 ::1 tcp localhost 127.0.0.1 127.0.0.1 tcp4 127.0.0.1 0.0.0.0 tcp4 0.0.0.0 127.0.0.1 0.0.0.0 tcp4 127.0.0.1 127.0.0.1 127.0.0.1 tcp4 [::] 127.0.0.1 0.0.0.0 tcp4 [::1] dial tcp4: address ::1: no suitable address found listen tcp4: address ::1: no suitable address found tcp4 localhost 127.0.0.1 127.0.0.1 tcp6 ::1 :: tcp6 0.0.0.0 dial tcp6: address 0.0.0.0: no suitable address found listen tcp6: address 0.0.0.0: no suitable address found tcp6 127.0.0.1 dial tcp6: address 127.0.0.1: no suitable address found listen tcp6: address 127.0.0.1: no suitable address found tcp6 [::] ::1 :: tcp6 [::1] ::1 ::1 tcp6 localhost ::1 ::1 $ make update [...] go-1.27.1->1.27.1p0: ok $ go run test.go | tee patch net addr Dial() Listen() tcp 127.0.0.1 0.0.0.0 tcp 0.0.0.0 127.0.0.1 0.0.0.0 tcp 127.0.0.1 127.0.0.1 127.0.0.1 tcp [::] 127.0.0.1 :: tcp [::1] ::1 ::1 tcp localhost 127.0.0.1 127.0.0.1 tcp4 127.0.0.1 0.0.0.0 tcp4 0.0.0.0 127.0.0.1 0.0.0.0 tcp4 127.0.0.1 127.0.0.1 127.0.0.1 tcp4 [::] dial tcp4: address ::: no suitable address found listen tcp4: address ::: no suitable address found tcp4 [::1] dial tcp4: address ::1: no suitable address found listen tcp4: address ::1: no suitable address found tcp4 localhost 127.0.0.1 127.0.0.1 tcp6 ::1 :: tcp6 0.0.0.0 dial tcp6: address 0.0.0.0: no suitable address found listen tcp6: address 0.0.0.0: no suitable address found tcp6 127.0.0.1 dial tcp6: address 127.0.0.1: no suitable address found listen tcp6: address 127.0.0.1: no suitable address found tcp6 [::] ::1 :: tcp6 [::1] ::1 ::1 tcp6 localhost ::1 ::1 Index: Makefile =================================================================== RCS file: /cvs/ports/lang/go/Makefile,v diff -u -p -r1.184 Makefile --- Makefile 16 Sep 2026 16:16:51 -0000 1.184 +++ Makefile 20 Sep 2026 22:01:26 -0000 @@ -8,6 +8,7 @@ COMMENT = Go programming language # increment _MODGO_SYSTEM_VERSION in go.port.mk after updating to a new # version, to trigger updates of go-compiled ports VERSION = 1.27.1 +REVISION = 0 DISTNAME = go${VERSION}.src PKGNAME = go-${VERSION} PKGSPEC = ${FULLPKGNAME:S/go-/go-=/} Index: patches/patch-src_net_ipsock_go =================================================================== RCS file: patches/patch-src_net_ipsock_go diff -N patches/patch-src_net_ipsock_go --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_net_ipsock_go 20 Sep 2026 22:02:22 -0000 @@ -0,0 +1,19 @@ +cause :: to resolve to IPv6 sockets + +Index: src/net/ipsock.go +--- src/net/ipsock.go.orig ++++ src/net/ipsock.go +@@ -290,13 +290,6 @@ func (r *Resolver) internetAddrList(ctx context.Contex + if err != nil { + return nil, err + } +- // Issue 18806: if the machine has halfway configured +- // IPv6 such that it can bind on "::" (IPv6unspecified) +- // but not connect back to that same address, fall +- // back to dialing 0.0.0.0. +- if len(ips) == 1 && ips[0].IP.Equal(IPv6unspecified) { +- ips = append(ips, IPAddr{IP: IPv4zero}) +- } + + var filter func(IPAddr) bool + if net != "" && net[len(net)-1] == '4' {
