解析类型 dns.RR

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

Parsing type dns.RR

问题

我是Go语言的新手,正在尝试编写一个小型的DNS程序,用于解析返回的A和CNAME记录。我使用了github.com/miekg/dns包。

我在理解如何正确解析返回的A或CNAME资源记录方面遇到了困难。对于A记录,我想获取IP地址并将其存储在一个变量中。对于返回多个RR的CNAME,我想解析Name和Address字段并存储在变量中。

我尝试将结构体转换为字符串或解包,但都没有成功。如果有人能提供任何见解,我将非常感激。

以下是代码。文本文件包含一行内容:“www”:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "github.com/miekg/dns"
  8. )
  9. func dns_request_fwd(s string) []dns.RR {
  10. //fmt.Println(s, " : started processing DNS request")
  11. m1 := new(dns.Msg)
  12. m1.Id = dns.Id()
  13. m1.RecursionDesired = true
  14. m1.Question = make([]dns.Question, 1)
  15. m1.Question[0] = dns.Question{s, dns.TypeA, dns.ClassINET}
  16. in, err := dns.Exchange(m1, "8.8.8.8:53")
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. if len(in.Answer) > 0 {
  21. //fmt.Println("Response greater than 0 - got something!")
  22. //fmt.Println(in.Answer)
  23. } else {
  24. //fmt.Println("Empty DNS Response")
  25. return nil
  26. }
  27. if _, ok := in.Answer[0].(*dns.A); ok {
  28. //fmt.Println("Detected an 'A' record Answer. Returning RR!")
  29. return in.Answer
  30. } else if _, ok := in.Answer[0].(*dns.CNAME); ok {
  31. //fmt.Println("Detected a 'CNAME' record Answer. Returning RR!")
  32. return in.Answer
  33. } else {
  34. fmt.Println("Returning nil")
  35. return nil
  36. }
  37. }
  38. func main() {
  39. f, err := os.Open("list4.txt")
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43. defer f.Close()
  44. domain := "acme.com"
  45. domain_lookup := "." + domain + "."
  46. scanner := bufio.NewScanner(f)
  47. for scanner.Scan() {
  48. a_record := scanner.Text()
  49. lookup := a_record+domain_lookup
  50. fmt.Println("Looking up: ", lookup)
  51. dreq := dns_request_fwd(lookup)
  52. if len(dreq) > 0 {
  53. fmt.Println(" [+] Forward Lookup answer")
  54. if _, ok := dreq[0].(*dns.CNAME); ok {
  55. fmt.Println(" [+] Type is CNAME")
  56. //fmt.Println(dreq[0].(*dns.CNAME))
  57. //fmt.Println(dreq[1].(*dns.A))
  58. fmt.Println(" [+] Alias records: ", len(dreq) -1)
  59. // Iterate through returned alias A records
  60. for i, s := range dreq {
  61. if i == 0{
  62. //Do nothing because first record is repeat of request
  63. } else {
  64. // Need to parse the below RR to get the Name + IP address returned
  65. fmt.Println(" [+] Returned",i, s)
  66. fmt.Println(s[0])
  67. }
  68. }
  69. } else if _, ok := dreq[0].(*dns.A); ok {
  70. fmt.Println(" [+] Type is A")
  71. // Need to parse the below RR to get the IP address returned
  72. fmt.Println(" [+] Answer: ", dreq[0])
  73. }
  74. } else {
  75. fmt.Println(" [-] We Got Nothing")
  76. }
  77. }
  78. if err := scanner.Err(); err != nil {
  79. log.Fatal(err)
  80. }
  81. }

希望对你有帮助!

英文:

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':

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "github.com/miekg/dns"
  8. )
  9. func dns_request_fwd(s string) []dns.RR {
  10. //fmt.Println(s, " : started processing DNS request")
  11. m1 := new(dns.Msg)
  12. m1.Id = dns.Id()
  13. m1.RecursionDesired = true
  14. m1.Question = make([]dns.Question, 1)
  15. m1.Question[0] = dns.Question{s, dns.TypeA, dns.ClassINET}
  16. in, err := dns.Exchange(m1, "8.8.8.8:53")
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. if len(in.Answer) > 0 {
  21. //fmt.Println("Response greater than 0 - got something!")
  22. //fmt.Println(in.Answer)
  23. } else {
  24. //fmt.Println("Empty DNS Response")
  25. return nil
  26. }
  27. if _, ok := in.Answer[0].(*dns.A); ok {
  28. //fmt.Println("Detected an 'A' record Answer. Returning RR!")
  29. return in.Answer
  30. } else if _, ok := in.Answer[0].(*dns.CNAME); ok {
  31. //fmt.Println("Detected a 'CNAME' record Answer. Returning RR!")
  32. return in.Answer
  33. } else {
  34. fmt.Println("Returning nil")
  35. return nil
  36. }
  37. }
  38. func main() {
  39. f, err := os.Open("list4.txt")
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43. defer f.Close()
  44. domain := "acme.com"
  45. domain_lookup := "." + domain + "."
  46. scanner := bufio.NewScanner(f)
  47. for scanner.Scan() {
  48. a_record := scanner.Text()
  49. lookup := a_record+domain_lookup
  50. fmt.Println("Looking up: ", lookup)
  51. dreq := dns_request_fwd(lookup)
  52. if len(dreq) > 0 {
  53. fmt.Println(" [+] Forward Lookup answer")
  54. if _, ok := dreq[0].(*dns.CNAME); ok {
  55. fmt.Println(" [+] Type is CNAME")
  56. //fmt.Println(dreq[0].(*dns.CNAME))
  57. //fmt.Println(dreq[1].(*dns.A))
  58. fmt.Println(" [+] Alias records: ", len(dreq) -1)
  59. // Iterate through returned alias A records
  60. for i, s := range dreq {
  61. if i == 0{
  62. //Do nothing because first record is repeat of request
  63. } else {
  64. // Need to parse the below RR to get the Name + IP address returned
  65. fmt.Println(" [+] Returned",i, s)
  66. fmt.Println(s[0])
  67. }
  68. }
  69. } else if _, ok := dreq[0].(*dns.A); ok {
  70. fmt.Println(" [+] Type is A")
  71. // Need to parse the below RR to get the IP address returned
  72. fmt.Println(" [+] Answer: ", dreq[0])
  73. }
  74. } else {
  75. fmt.Println(" [-] We Got Nothing")
  76. }
  77. }
  78. if err := scanner.Err(); err != nil {
  79. log.Fatal(err)
  80. }
  81. }

答案1

得分: 1

你不需要“解析”一个结构体。库已经解析了响应,以便为你提供结构体。只需使用结构体中包含你想要的数据的字段,比如 dns.A.A 是一个 net.IP,或者 dns.CNAME.Target 是一个 string。更多详细信息请参阅包文档

  1. if arec, ok := dreq[0].(*dns.A); ok {
  2. fmt.Println(" [+] 类型是 A")
  3. fmt.Println(" [+] 答案:", arec.A)
  4. }
英文:

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.

  1. if arec, ok := dreq[0].(*dns.A); ok {
  2. fmt.Println(" [+] Type is A")
  3. fmt.Println(" [+] Answer: ", arec.A)
  4. }

huangapple
  • 本文由 发表于 2021年8月5日 22:11:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/68668231.html
匿名

发表评论

匿名网友

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

确定