英文:
Parsing type dns.RR
问题
我是Go语言的新手,正在尝试编写一个小型的DNS程序,用于解析返回的A和CNAME记录。我使用了github.com/miekg/dns包。
我在理解如何正确解析返回的A或CNAME资源记录方面遇到了困难。对于A记录,我想获取IP地址并将其存储在一个变量中。对于返回多个RR的CNAME,我想解析Name和Address字段并存储在变量中。
我尝试将结构体转换为字符串或解包,但都没有成功。如果有人能提供任何见解,我将非常感激。
以下是代码。文本文件包含一行内容:“www”:
package main
import (
"bufio"
"fmt"
"log"
"os"
"github.com/miekg/dns"
)
func dns_request_fwd(s string) []dns.RR {
//fmt.Println(s, " : started processing DNS request")
m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{s, dns.TypeA, dns.ClassINET}
in, err := dns.Exchange(m1, "8.8.8.8:53")
if err != nil {
log.Fatal(err)
}
if len(in.Answer) > 0 {
//fmt.Println("Response greater than 0 - got something!")
//fmt.Println(in.Answer)
} else {
//fmt.Println("Empty DNS Response")
return nil
}
if _, ok := in.Answer[0].(*dns.A); ok {
//fmt.Println("Detected an 'A' record Answer. Returning RR!")
return in.Answer
} else if _, ok := in.Answer[0].(*dns.CNAME); ok {
//fmt.Println("Detected a 'CNAME' record Answer. Returning RR!")
return in.Answer
} else {
fmt.Println("Returning nil")
return nil
}
}
func main() {
f, err := os.Open("list4.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
domain := "acme.com"
domain_lookup := "." + domain + "."
scanner := bufio.NewScanner(f)
for scanner.Scan() {
a_record := scanner.Text()
lookup := a_record+domain_lookup
fmt.Println("Looking up: ", lookup)
dreq := dns_request_fwd(lookup)
if len(dreq) > 0 {
fmt.Println(" [+] Forward Lookup answer")
if _, ok := dreq[0].(*dns.CNAME); ok {
fmt.Println(" [+] Type is CNAME")
//fmt.Println(dreq[0].(*dns.CNAME))
//fmt.Println(dreq[1].(*dns.A))
fmt.Println(" [+] Alias records: ", len(dreq) -1)
// Iterate through returned alias A records
for i, s := range dreq {
if i == 0{
//Do nothing because first record is repeat of request
} else {
// Need to parse the below RR to get the Name + IP address returned
fmt.Println(" [+] Returned",i, s)
fmt.Println(s[0])
}
}
} else if _, ok := dreq[0].(*dns.A); ok {
fmt.Println(" [+] Type is A")
// Need to parse the below RR to get the IP address returned
fmt.Println(" [+] Answer: ", dreq[0])
}
} else {
fmt.Println(" [-] We Got Nothing")
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
希望对你有帮助!
英文:
I'm new to Go and trying to get a small DNS program working that parses returned A and CNAME records. This is using github.com/miekg/dns package.
I'm having trouble understanding how to properly parse the returned resource record for A or CNAME. For the A record, I want to get the IP address and store it in a variable. For the CNAME that has multiple RRs returned, I'd like to parse the Name and Address fields and store in variables.
I've tried converting the structure to a string or unpacking it to no avail. Anyone can lend any insight, greatly appreciate it.
Here is the code below. Text file contains a single line with 'www':
package main
import (
"bufio"
"fmt"
"log"
"os"
"github.com/miekg/dns"
)
func dns_request_fwd(s string) []dns.RR {
//fmt.Println(s, " : started processing DNS request")
m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{s, dns.TypeA, dns.ClassINET}
in, err := dns.Exchange(m1, "8.8.8.8:53")
if err != nil {
log.Fatal(err)
}
if len(in.Answer) > 0 {
//fmt.Println("Response greater than 0 - got something!")
//fmt.Println(in.Answer)
} else {
//fmt.Println("Empty DNS Response")
return nil
}
if _, ok := in.Answer[0].(*dns.A); ok {
//fmt.Println("Detected an 'A' record Answer. Returning RR!")
return in.Answer
} else if _, ok := in.Answer[0].(*dns.CNAME); ok {
//fmt.Println("Detected a 'CNAME' record Answer. Returning RR!")
return in.Answer
} else {
fmt.Println("Returning nil")
return nil
}
}
func main() {
f, err := os.Open("list4.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
domain := "acme.com"
domain_lookup := "." + domain + "."
scanner := bufio.NewScanner(f)
for scanner.Scan() {
a_record := scanner.Text()
lookup := a_record+domain_lookup
fmt.Println("Looking up: ", lookup)
dreq := dns_request_fwd(lookup)
if len(dreq) > 0 {
fmt.Println(" [+] Forward Lookup answer")
if _, ok := dreq[0].(*dns.CNAME); ok {
fmt.Println(" [+] Type is CNAME")
//fmt.Println(dreq[0].(*dns.CNAME))
//fmt.Println(dreq[1].(*dns.A))
fmt.Println(" [+] Alias records: ", len(dreq) -1)
// Iterate through returned alias A records
for i, s := range dreq {
if i == 0{
//Do nothing because first record is repeat of request
} else {
// Need to parse the below RR to get the Name + IP address returned
fmt.Println(" [+] Returned",i, s)
fmt.Println(s[0])
}
}
} else if _, ok := dreq[0].(*dns.A); ok {
fmt.Println(" [+] Type is A")
// Need to parse the below RR to get the IP address returned
fmt.Println(" [+] Answer: ", dreq[0])
}
} else {
fmt.Println(" [-] We Got Nothing")
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
答案1
得分: 1
你不需要“解析”一个结构体。库已经解析了响应,以便为你提供结构体。只需使用结构体中包含你想要的数据的字段,比如 dns.A.A
是一个 net.IP
,或者 dns.CNAME.Target
是一个 string
。更多详细信息请参阅包文档。
if arec, ok := dreq[0].(*dns.A); ok {
fmt.Println(" [+] 类型是 A")
fmt.Println(" [+] 答案:", arec.A)
}
英文:
You don't need to "parse" a struct. The library parsed the response already in order to give you the struct. Just use the fields in the struct which have the data you want, like dns.A.A
which is a net.IP
or dns.CNAME.Target
which is a string
. See the package documentation for more details.
if arec, ok := dreq[0].(*dns.A); ok {
fmt.Println(" [+] Type is A")
fmt.Println(" [+] Answer: ", arec.A)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论