Customized DNS Resolver cannot return the proper error

Currently, the golang’s standard package, i.e. net, allows us to customize a DNS Resolver for DNS query targeting on specific DNS Server, as specified in the Dial field as following:

type Resolver struct {
        // PreferGo controls whether Go's built-in DNS resolver is preferred
        // on platforms where it's available. It is equivalent to setting
        // GODEBUG=netdns=go, but scoped to just this resolver.
        PreferGo bool

        // StrictErrors controls the behavior of temporary errors
        // (including timeout, socket errors, and SERVFAIL) when using
        // Go's built-in resolver. For a query composed of multiple
        // sub-queries (such as an A+AAAA address lookup, or walking the
        // DNS search list), this option causes such errors to abort the
        // whole query instead of returning a partial result. This is
        // not enabled by default because it may affect compatibility
        // with resolvers that process AAAA queries incorrectly.
        StrictErrors bool

        // 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)
        // contains filtered or unexported fields

However, since this solution modifies the very-low level function, all the upper invocation chains are unaware of the customized DNS Server’ address. If we use it to query a DNS A Record, and say, which ought not to be found. The error message returned by the upper function would be misleading.

A brief example is as following:

package main

import (

func main() {
	customR := net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			d := net.Dialer{}
			return d.DialContext(ctx, "udp", "")
	ips, err := customR.LookupHost(context.Background(), "")

	fmt.Println("ips:", ips)
	fmt.Println("err:", err)

The above code would return: ips: [] and
err: lookup on no such host, instead of err: lookup on no such host.
In fact, the is subject to the /etc/resolv.conf on local environment

Does anybody have better solution to make the above code return correct error instead of this misleading one?

Thanks :slight_smile:

I don’t, but I’d suggest that this is not a great way to change the resolver to use. For, amongst others, the reason you discovered.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.