Android 端 DNS 查询错误

Android 端 DNS 查询错误

下面这段代码在 Android 端执行会抛错:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package main

import (
	"log"
	"net"
)

func main() {
	ip, err := net.LookupIP("baidu.com")
	if err != nil {
		return
	}
	log.Println(ip)
}

错误信息:read udp [::1]:46548->[::1]:53: read: connection refused

通过分析后发现错误原因是 Go 在 linux 环境下是默认通过 /etc/resolve.conf 文件获取的系统 DNS 服务器地址,但是在 Android 端没有这个文件,会导致 Go 获取不到本机 DNS 服务器,然后 Go 就会使用默认设置的本机 DNS 服务器地址。

相关代码:

1
2
3
4
5
6
// net/dnsclient_unix.go

func getSystemDNSConfig() *dnsConfig {
	resolvConf.tryUpdate("/etc/resolv.conf")
	return resolvConf.dnsConfig.Load()
}
1
2
3
4
// net/dnsconfig.go
var (
	defaultNS   = []string{"127.0.0.1:53", "[::1]:53"}
)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// net/dnsconfig_unix.go
// See resolv.conf(5) on a Linux machine.
func dnsReadConfig(filename string) *dnsConfig {
	...
	file, err := open(filename)
	if err != nil {
		conf.servers = defaultNS
		conf.search = dnsDefaultSearch()
		conf.err = err
		return conf
	}
	...
}

为了解决这个问题,需要自行设置 DNS 服务器地址。可通过修改全局变量 net.DefaultResolver 实现效果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
&net.Resolver{
    Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
    	dial := net.Dialer{}
    	var dns []string
    	for _, server := range custom.DNSServers {
    		if _, _, err := net.SplitHostPort(server); err != nil {
    			dns = append(dns, net.JoinHostPort(server, defaultDNSPort))
    		} else {
    			dns = append(dns, server)
    		}
    	}
    	return dial.DialContext(ctx, network, dns[rand.Intn(len(dns))])
    },
}
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计