为什么Golang的Lookup***函数不能提供服务器参数?

huangapple go评论88阅读模式
英文:

Why golang Lookup*** function can't provide a server parameter?

问题

对于nslookup命令,它的用法是nslookup somewhere.com some.dns.server

然而,似乎golang的dnsclient只从/etc/resolv.conf加载配置。

代码在这里:https://golang.org/src/net/dnsclient_unix.go#L225

golang标准库是否提供类似于func LookupTXT(name string, dnsServer string) (txt []string, err error)的功能?

要求:

  1. 不要更改默认的/etc/resolv.conf文件。
英文:

For nslookup command, it has nslookup somewhere.com some.dns.server.

However, it seems that golang dnsclient only load config from /etc/resolv.conf

code here: https://golang.org/src/net/dnsclient_unix.go#L225

Does the golang standard library provide something like
func LookupTXT(name string, dnsServer string) (txt []string, err error) ?

requirement:

  1. Don't change the default /etc/resolv.conf.

答案1

得分: 33

这段代码是一个使用github.com/miekg/dns包的Go语言程序,用于查询指定域名的IP地址。它并不重,运行后会输出查询结果。

英文:

@holys
> "github.com/miekg/dns is too heavy for me"

It's not that heavy:

package main

import (
	"log"

	"github.com/miekg/dns"
)

func main() {

	target := "microsoft.com"
	server := "8.8.8.8"

	c := dns.Client{}
	m := dns.Msg{}
	m.SetQuestion(target+".", dns.TypeA)
	r, t, err := c.Exchange(&m, server+":53")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Took %v", t)
	if len(r.Answer) == 0 {
		log.Fatal("No results")
	}
	for _, ans := range r.Answer {
		Arecord := ans.(*dns.A)
		log.Printf("%s", Arecord.A)
	}
}

When run, you should see:

$ go run dns.go
2015/07/26 00:24:46 Took 16.138928ms
2015/07/26 00:24:46 134.170.188.221
2015/07/26 00:24:46 134.170.185.46

答案2

得分: 12

你可以使用基于miekg/dns的简单dns_resolver来实现这个功能。

go get github.com/bogdanovich/dns_resolver

package main

import (
    "log"
    "github.com/bogdanovich/dns_resolver"
)

func main() {
    resolver := dns_resolver.New([]string{"8.8.8.8", "8.8.4.4"})
    
    // 在发生I/O超时的情况下进行重试
    resolver.RetryTimes = 5

    ip, err := resolver.LookupHost("google.com")
    if err != nil {
        log.Fatal(err.Error())
    }
    log.Println(ip)
    // 输出 [216.58.192.46]
}
英文:

@holys

You can use this simple dns_resolver based on miekg/dns

go get github.com/bogdanovich/dns_resolver

<!-- language: lang-golang -->

package main

import (
    &quot;log&quot;
    &quot;github.com/bogdanovich/dns_resolver&quot;
)

func main() {
    resolver := dns_resolver.New([]string{&quot;8.8.8.8&quot;, &quot;8.8.4.4&quot;})
    
    // In case of i/o timeout
    resolver.RetryTimes = 5

    ip, err := resolver.LookupHost(&quot;google.com&quot;)
    if err != nil {
        log.Fatal(err.Error())
    }
    log.Println(ip)
    // Output [216.58.192.46]
}

答案3

得分: 12

从一段时间开始,你可以为解析器设置Dial,其中你可以在DialContext中定义你的名称服务器。

var resolver *net.Resolver

if nameserver != "" {
    resolver = &net.Resolver{
        PreferGo: true,
        Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
            d := net.Dialer{}
            return d.DialContext(ctx, "udp", net.JoinHostPort(nameserver, "53"))
        },
    }
} else {
    resolver = net.DefaultResolver
}

之后,你可以像往常一样继续操作:

ips, err := resolver.LookupIPAddr(context.Background(), "www.example.com")
英文:

Since a little while you can set the Dial for the Resolver, where you can define your nameserver in the DialContext

<!-- language: golang -->

var resolver *net.Resolver

if nameserver != &quot;&quot; {
	resolver = &amp;net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			d := net.Dialer{}
			return d.DialContext(ctx, &quot;udp&quot;, net.JoinHostPort(nameserver, &quot;53&quot;))
		},
	}
} else {
	resolver = net.DefaultResolver
}

After that you can go as you're used to:

ips, err := resolver.LookupIPAddr(context.Background(), &quot;www.example.com&quot;)

答案4

得分: 5

自从Go 1.9版本以后,可以通过覆盖Resolver上的Dial函数来实现。例如,要忽略对本地解析器的UDP请求,并通过TCP连接到9.9.9.9,我们可以像这样做:

r := &net.Resolver{
    Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
        return net.Dial("tcp", "9.9.9.9")
    },
}
addrs, err := r.LookupIPAddr(context.TODO(), "example.net")
英文:

Since Go 1.9 this is possible by overriding the Dial function on a Resolver. For example, to ignore the request for the local resolver over UDP and connect to 9.9.9.9 via TCP we might do something like this:

r := &amp;net.Resolver{
	Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
		return net.Dial(&quot;tcp&quot;, &quot;9.9.9.9&quot;)
	},
}
addrs, err := r.LookupIPAddr(context.TODO(), &quot;example.net&quot;)

答案5

得分: 4

net.Lookup*函数提供对本地解析器的访问。虽然许多请求将使用来自DNS服务器的信息进行回答,但并非总是如此。

例如,LookupHost可能会从/etc/hosts文件返回一个名称。或者它可能使用mDNS来解析.local名称。

如果您想与任意DNS服务器通信而不是本地解析器,则应使用通用的DNS客户端库。如评论中建议的,https://github.com/miekg/dns 可能符合您的需求。

英文:

The net.Lookup* functions provide access to the local resolver. While many requests will be answered with information from a DNS server, this is not always the case.

For instance, LookupHost may return a name from the /etc/hosts file. Or it might use mDNS to resolve a .local name.

If you want to talk to an arbitrary DNS server rather than the local resolver, then you should use a general purpose DNS client library. As suggested in the comments, https://github.com/miekg/dns might fit your needs.

huangapple
  • 本文由 发表于 2015年5月5日 10:22:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/30043248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定