我正在寻找一种方法(在Go中),以获取给定主机的CNAME(如果有),无论该主机的DNS解析是否失败。
主机的DNS解析可能会失败并产生结果NXDOMAIN,但有问题的主机可能仍具有CNAME记录。在撰写此问题时,tst1crmapps.starbucks.com是这样一个主机的示例:
$ dig tst1crmapps.starbucks.com | grep -E 'NXDOMAIN|CNAME'
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 50444
tst1crmapps.starbucks.com. 86400 IN CNAME bigip-tst1crmapps-starbucks.oracle.com.
Run Code Online (Sandbox Code Playgroud)
(在macOS上运行)
功能net.LookupCNAME似乎就在我的小巷,但是如果主机的DNS解析失败,它将无法返回CNAME。跑步
package main
import (
"log"
"net"
)
func main() {
cname, err := net.LookupCNAME("tst1crmapps.starbucks.com")
if err != nil {
log.Fatal(err)
}
log.Println(cname)
}
Run Code Online (Sandbox Code Playgroud)
产量
yyyy/MM/dd hh:mm:ss lookup tst1crmapps.starbucks.com: no such host
Run Code Online (Sandbox Code Playgroud)
我误会了net.LookupCNAME吗?还是我使用了错误的功能?
Go's LookupCNAME function tries to follow a CNAME chain all the way to its end. This means it considers a DNS name without both CNAME and A records an error:
A canonical name is the final name after following zero or more CNAME records. LookupCNAME does not return an error if host does not contain DNS "CNAME" records, as long as host resolves to address records.
Go does not provide a low-level DNS API in the standard library. The de-facto standard package to use for that is github.com/miekg/dns (error handling and type checking elided for brevity):
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
c := new(dns.Client)
m := new(dns.Msg)
// Note the trailing dot. miekg/dns is very low-level and expects canonical names.
m.SetQuestion("tst1crmapps.starbucks.com.", dns.TypeCNAME)
m.RecursionDesired = true
r, _, _ := c.Exchange(m, config.Servers[0]+":"+config.Port)
fmt.Println(r.Answer[0].(*dns.CNAME).Target) // bigip-tst1crmapps-starbucks.oracle.com.
}
Run Code Online (Sandbox Code Playgroud)