Repository: go
Issue: net: Resolver doesn't use provided Dial function in all cases
Labels: NeedsInvestigation

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.20.3 linux/arm64
</pre>

### Does this issue reproduce with the latest release?

Yes.

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/tmp/go"
GOENV="/home/ubuntu/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/usr/local/lib/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/usr/local/lib/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go-1.20"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.20/pkg/tool/linux_arm64"
GOVCS=""
GOVERSION="go1.20.3"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1714904807=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

The [`net.Resolver`](https://github.com/golang/go/blob/5e9b76fe2a1c6709e710c985ae82dff90c847c54/src/net/lookup.go#L123) accepts an optional [`Dial`](https://github.com/golang/go/blob/5e9b76fe2a1c6709e710c985ae82dff90c847c54/src/net/lookup.go#L139-L150) function that says the following:

```go
type Resolver struct {
	// Dial optionally specifies an alternate dialer for use by
	// Go's built-in DNS resolver to make TCP and UDP connections
	// to DNS services. The host in the address parameter will
	// always be a literal IP address and not a host name, and the
	// port in the address parameter will be a literal port number
	// and not a service name.
	// If the Conn returned is also a PacketConn, sent and received DNS
	// messages must adhere to RFC 1035 section 4.2.1, "UDP usage".
	// Otherwise, DNS messages transmitted over Conn must adhere
	// to RFC 7766 section 5, "Transport Protocol Selection".
	// If nil, the default dialer is used.
	Dial func(ctx context.Context, network, address string) (Conn, error)
}
```

I created a script that logs `Dial` calls when using the pure Go resolver: https://go.dev/play/p/0O_ARZyK2eG

If I run this script locally, I see something like this:

```
$ ./resolve
Dial(udp, 127.0.0.53:53)
Dial(udp, 127.0.0.53:53)
{172.217.24.46 }
{2404:6800:4006:804::200e }
```

However, if I run the script with strace, I see that Go is making additional connections some other way:

```
$ strace ./resolve 2>&1 | grep '^connect'
connect(7, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(9), sin_addr=inet_addr("172.217.24.46")}, 16) = 0
connect(3, {sa_family=AF_INET6, sin6_port=htons(9), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "2404:6800:4006:804::200e", &sin6_addr), sin6_scope_id=0}, 28) = -1 ENETUNREACH (Network is unreachable)
```

There's is one hardcoded call to `net.DialUDP` [here](https://github.com/golang/go/blob/5e9b76fe2a1c6709e710c985ae82dff90c847c54/src/net/addrselect.go#L49) which appears to be the source of the additional connections.

### What did you expect to see?

I expect to see the `Dial` function used for all connections made by the pure Go resolver.

### What did you see instead?

I see that the `Dial` function is only used in some cases. 

### Additional context

[CL 500576](https://go-review.googlesource.com/c/go/+/500576) fixes the issue by using `net.Resolver.Dial` in all cases.

For context, this change is important for targets with limited networking capabilities (e.g. `GOOS=wasip1`). It means that users can provide their own `Dial` function to make use of the pure Go resolver. At the moment the hardcoded `net.DialUDP` call makes the pure Go resolver off limits for these targets.

There was some concern in the CL about whether making this change for all targets would break code in the wild. I'm submitting it as a bug report so we can discuss here instead.

cc `GOOS=wasip1` maintainers: @achille-roussel @johanbrandhorst @Pryz 

cc those that commented on [CL 500576](https://go-review.googlesource.com/c/go/+/500576): @mateusz834 @ianlancetaylor