【问题标题】:Why golang Lookup*** function can't provide a server parameter?为什么golang Lookup*** 函数不能提供服务器参数?
【发布时间】:2015-07-14 14:42:53
【问题描述】:

对于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)?

requirement: 1.不要更改默认/etc/resolv.conf

【问题讨论】:

  • 你可以试试这个库:github.com/miekg/dns
  • @Not_a_Golfer github.com/miekg/dns 对我来说太重了。

标签: go dns nslookup


【解决方案1】:

@holys

“github.com/miekg/dns 对我来说太重了”

没那么重:

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)
    }
}

运行时,您应该看到:

$ 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】:

@holys

你可以使用这个基于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"})

    // In case of i/o timeout
    resolver.RetryTimes = 5

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

【讨论】:

  • OP 说,“github.com/miekg/dns 对我来说太重了”但是这个,github.com/bogdanovich/dns_resolver,是建立在之上的 miekg/dns 的顶部,所以它添加了另一层,根本不是“简单”。
【解决方案3】:

Since a little while你可以为Resolver设置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")

【讨论】:

  • 我注意到这不能用来绕过hosts文件。如果您想从 Go 直接查询 DNS 服务器,似乎 github.com/miekg/dns 是最好的选择(如其他答案中所述)
  • 不在 Windows 10 上?
  • > 我注意到这不能用来绕过主机文件@0x574F4F54 这是什么来源?
【解决方案4】:

net.Lookup* 函数提供对本地解析器的访问。虽然许多请求都会通过来自 DNS 服务器的信息得到答复,但情况并非总是如此。

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

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

【讨论】:

  • 感谢您的建议。我为nslookup 做了一个简单的wrapper 命令以适合我的情况。
  • 如果您担心的是开销,那么使用 nslookup 可能比进程内 DNS 库更重量级。
【解决方案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")

【讨论】:

    猜你喜欢
    • 2020-02-14
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 2016-04-24
    • 2019-09-08
    • 2013-02-23
    相关资源
    最近更新 更多