golang网络数据包捕获库gopacket详解

Written by

in

文章目录
  • github.com/google/gopacket/pcap 是 Go 语言中一个强大的网络数据包捕获库,它是 gopacket 项目的一部分,提供了对 libpcap(Linux/Unix)和 WinPcap(Windows)的 Go 语言绑定,用于实时网络数据包捕获和分析。
  • github.com/google/gopacket/pcap 可以捕获和解析 DNS 请求和响应,但需要结合 gopacket/layers 包中的 DNS 层解析功能。
  • 要从 layers.DNS 数据包中提取域名和对应的 IP 地址,你需要检查 DNS 响应中的回答部分 (Answers)。以下是详细方法和示例代码:
  • 以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。 您可能感兴趣的文章: 使用Golang实现对网络数据包的捕获与分析 Golang实现读取ZIP压缩包并显示Gin静态html网站 golang版本升级如何实现 golang格式化输出函数printf、sprintf、fprintf解读 golang如何获取域名ip dns信息
  • 目录
    • 详解github.com/google/gopacket/pcap包
      • 核心功能
      • 基本使用
        • 1. 安装
        • 2. 获取网络接口列表
        • 3. 打开网络接口进行捕获
        • 4. 设置BPF过滤器
        • 5. 读取数据包
      • 高级功能
        • 1. 解析数据包
        • 2. 写入pcap文件
        • 3. 读取pcap文件
      • 性能优化
        • 常见问题
          • 实际应用示例
            • 简单的HTTP请求捕获
        • 使用github.com/google/gopacket/pcap解析 DNS 请求和响应
          • 1. 基本 DNS 解析设置
            • 2. 捕获 DNS 流量的配置
              • 方法一:捕获所有DNS流量(端口53)
              • 方法二:区分请求和响应
            • 3. 解析DNS数据包
              • 4. 详细DNS解析函数
                • 5. 处理TCP DNS流量
                  • 6. 完整示例:DNS监控工具
                    • 注意事项
                    • 从layers.DNS中获取域名和对应 IP 的方法
                      • 基本方法
                        • 示例代码
                          • 更完整的处理函数
                            • 处理特殊情况
                              • 性能优化建议
                                • 完整示例(带CNAME处理)
                                • 总结

                                  github.com/google/gopacket/pcap 是 Go 语言中一个强大的网络数据包捕获库,它是 gopacket 项目的一部分,提供了对 libpcap(Linux/Unix)和 WinPcap(Windows)的 Go 语言绑定,用于实时网络数据包捕获和分析。

                                  • 实时网络数据包捕获
                                  • 过滤网络流量(BPF过滤器)
                                  • 读取和解析pcap文件
                                  • 统计网络接口信息

                                  go get github.com/google/gopacket
                                  go get github.com/google/gopacket/pcap
                                  

                                  devices, err := pcap.FindAllDevs()
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  
                                  for _, device := range devices {
                                      fmt.Printf("Device: %sn", device.Name)
                                      fmt.Printf("Description: %sn", device.Description)
                                      fmt.Printf("Flags: %dn", device.Flags)
                                      for _, address := range device.Addresses {
                                          fmt.Printf("tIP: %sn", address.IP)
                                          fmt.Printf("tNetmask: %sn", address.Netmask)
                                      }
                                  }
                                  

                                  handle, err := pcap.OpenLive(
                                      "eth0",    // 接口名
                                      65536,     // 最大包长度
                                      true,      // 是否启用混杂模式
                                      pcap.BlockForever, // 超时时间
                                  )
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  defer handle.Close()
                                  

                                  err = handle.SetBPFFilter("tcp and port 80")
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  

                                  packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                  for packet := range packetSource.Packets() {
                                      // 处理每个数据包
                                      fmt.Println(packet)
                                  }
                                  

                                  // 解析以太网层
                                  ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
                                  if ethernetLayer != nil {
                                      ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
                                      fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
                                      fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
                                  }
                                  
                                  // 解析IP层
                                  ipLayer := packet.Layer(layers.LayerTypeIPv4)
                                  if ipLayer != nil {
                                      ip, _ := ipLayer.(*layers.IPv4)
                                      fmt.Println("Source IP: ", ip.SrcIP)
                                      fmt.Println("Destination IP: ", ip.DstIP)
                                  }
                                  
                                  // 解析TCP层
                                  tcpLayer := packet.Layer(layers.LayerTypeTCP)
                                  if tcpLayer != nil {
                                      tcp, _ := tcpLayer.(*layers.TCP)
                                      fmt.Println("Source Port: ", tcp.SrcPort)
                                      fmt.Println("Destination Port: ", tcp.DstPort)
                                  }
                                  

                                  handle, err := pcap.OpenDead(layers.LinkTypeEthernet, 65536)
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  defer handle.Close()
                                  
                                  writer, err := pcap.NewWriter(handle, "output.pcap")
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  defer writer.Close()
                                  
                                  // 创建并写入数据包
                                  // ... (创建数据包代码)
                                  err = writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  

                                  handle, err := pcap.OpenOffline("input.pcap")
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  defer handle.Close()
                                  
                                  packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                  for packet := range packetSource.Packets() {
                                      fmt.Println(packet)
                                  }
                                  

                                  重用缓冲区:减少内存分配

                                  var buf [4096]byte
                                  for {
                                      data, ci, err := handle.ReadPacketData()
                                      if err != nil {
                                          continue
                                      }
                                      copy(buf[:], data)
                                      // 处理数据
                                  }
                                  

                                  零拷贝处理:直接操作原始数据

                                  packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
                                  

                                  并发处理:使用多个goroutine处理数据包

                                  packets := make(chan gopacket.Packet, 1000)
                                  go func() {
                                      for packet := range packetSource.Packets() {
                                          packets <- packet
                                      }
                                      close(packets)
                                  }()
                                  
                                  for i := 0; i < runtime.NumCPU(); i++ {
                                      go func() {
                                          for packet := range packets {
                                              // 处理数据包
                                          }
                                      }()
                                  }
                                  

                                  • 权限问题:需要root或管理员权限才能捕获网络数据包
                                  • 接口不可用:确保接口名称正确且处于活动状态
                                  • 过滤器语法错误:BPF过滤器需要正确语法
                                  • 内存泄漏:确保及时关闭handle和释放资源

                                  handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever)
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  defer handle.Close()
                                  
                                  err = handle.SetBPFFilter("tcp and port 80")
                                  if err != nil {
                                      log.Fatal(err)
                                  }
                                  
                                  packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                  for packet := range packetSource.Packets() {
                                      appLayer := packet.ApplicationLayer()
                                      if appLayer != nil {
                                          payload := appLayer.Payload()
                                          if bytes.Contains(payload, []byte("HTTP")) {
                                              fmt.Printf("%sn", payload)
                                          }
                                      }
                                  }
                                  

                                  pcap 包是 Go 中网络监控和安全工具开发的基础,结合 gopacket 的其他组件可以构建强大的网络分析工具。

                                  github.com/google/gopacket/pcap 可以捕获和解析 DNS 请求和响应,但需要结合 gopacket/layers 包中的 DNS 层解析功能。

                                  首先需要导入必要的包:

                                  import (
                                      "github.com/google/gopacket"
                                      "github.com/google/gopacket/layers" // 包含DNS层定义
                                      "github.com/google/gopacket/pcap"
                                  )
                                  

                                  handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever)
                                  if err != nil {
                                      panic(err)
                                  }
                                  defer handle.Close()
                                  
                                  // 设置BPF过滤器捕获DNS流量(UDP和TCP端口53)
                                  err = handle.SetBPFFilter("udp port 53 or tcp port 53")
                                  if err != nil {
                                      panic(err)
                                  }
                                  

                                  // 捕获发往DNS服务器的请求
                                  err = handle.SetBPFFilter("dst port 53")
                                  
                                  // 或者捕获来自DNS服务器的响应
                                  err = handle.SetBPFFilter("src port 53")
                                  

                                  packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                  for packet := range packetSource.Packets() {
                                      // 检查是否包含DNS层
                                      dnsLayer := packet.Layer(layers.LayerTypeDNS)
                                      if dnsLayer != nil {
                                          dns, _ := dnsLayer.(*layers.DNS)
                                          analyzeDNS(dns) // 自定义解析函数
                                      }
                                  }
                                  

                                  func analyzeDNS(dns *layers.DNS) {
                                      // 判断是请求还是响应
                                      if dns.QR {
                                          fmt.Println("[DNS Response]")
                                      } else {
                                          fmt.Println("[DNS Query]")
                                      }
                                    
                                      // 打印基本信息
                                      fmt.Printf("ID: %d, OpCode: %s, RecursionDesired: %tn",
                                          dns.ID, dns.OpCode, dns.RD)
                                    
                                      // 解析问题部分(查询的问题)
                                      for _, question := range dns.Questions {
                                          fmt.Printf("Query: %s (Type: %s, Class: %s)n",
                                              string(question.Name), 
                                              question.Type, 
                                              question.Class)
                                      }
                                    
                                      // 解析回答部分(响应的资源记录)
                                      for _, answer := range dns.Answers {
                                          fmt.Printf("Answer: %s -> %s (Type: %s, TTL: %d)n",
                                              string(answer.Name),
                                              getAnswerValue(answer), // 自定义函数获取值
                                              answer.Type,
                                              answer.TTL)
                                      }
                                    
                                      // 解析权威名称服务器部分
                                      for _, ns := range dns.Authorities {
                                          fmt.Printf("Authority: %s -> %sn",
                                              string(ns.Name),
                                              getAnswerValue(ns))
                                      }
                                    
                                      // 解析附加记录部分
                                      for _, extra := range dns.Additionals {
                                          fmt.Printf("Additional: %s -> %sn",
                                              string(extra.Name),
                                              getAnswerValue(extra))
                                      }
                                  }
                                  
                                  // 辅助函数:根据类型获取DNS记录的值
                                  func getAnswerValue(answer layers.DNSResourceRecord) string {
                                      switch answer.Type {
                                      case layers.DNSTypeA:
                                          return answer.IP.String()
                                      case layers.DNSTypeAAAA:
                                          return answer.IP.String()
                                      case layers.DNSTypeCNAME:
                                          return string(answer.CNAME)
                                      case layers.DNSTypeMX:
                                          return fmt.Sprintf("%s (pref %d)", string(answer.MX), answer.Preference)
                                      case layers.DNSTypeNS:
                                          return string(answer.NS)
                                      case layers.DNSTypeTXT:
                                          return string(answer.TXT)
                                      case layers.DNSTypeSOA:
                                          return fmt.Sprintf("MName: %s, RName: %s", string(answer.SOA.MName), string(answer.SOA.RName))
                                      default:
                                          return fmt.Sprintf("[Unhandled Type %d]", answer.Type)
                                      }
                                  }
                                  

                                  DNS通常使用UDP,但大响应可能使用TCP:

                                  // 在分析函数中添加TCP处理
                                  tcpLayer := packet.Layer(layers.LayerTypeTCP)
                                  if tcpLayer != nil {
                                      tcp, _ := tcpLayer.(*layers.TCP)
                                      if tcp.SYN {
                                          // TCP握手开始
                                      } else if len(tcp.Payload) > 0 {
                                          // 尝试解析TCP负载中的DNS
                                          dns := &layers.DNS{}
                                          err := dns.DecodeFromBytes(tcp.Payload, gopacket.NilDecodeFeedback)
                                          if err == nil {
                                              analyzeDNS(dns)
                                          }
                                      }
                                  }
                                  

                                  package main
                                  
                                  import (
                                      "fmt"
                                      "log"
                                      "time"
                                    
                                      "github.com/google/gopacket"
                                      "github.com/google/gopacket/layers"
                                      "github.com/google/gopacket/pcap"
                                  )
                                  
                                  func main() {
                                      // 1. 获取网络设备
                                      devices, err := pcap.FindAllDevs()
                                      if err != nil {
                                          log.Fatal(err)
                                      }
                                    
                                      // 打印可用设备
                                      fmt.Println("Available devices:")
                                      for _, dev := range devices {
                                          fmt.Printf("- %s", dev.Name)
                                          if dev.Description != "" {
                                              fmt.Printf(" (%s)", dev.Description)
                                          }
                                          fmt.Println()
                                      }
                                    
                                      // 2. 打开设备
                                      var deviceName = "eth0" // 根据实际情况修改
                                      var snapshotLen int32 = 1024
                                      var promiscuous = true
                                      var timeout = 30 * time.Second
                                    
                                      handle, err := pcap.OpenLive(deviceName, snapshotLen, promiscuous, timeout)
                                      if err != nil {
                                          log.Fatal(err)
                                      }
                                      defer handle.Close()
                                    
                                      // 3. 设置过滤器
                                      var filter = "udp port 53 or tcp port 53"
                                      err = handle.SetBPFFilter(filter)
                                      if err != nil {
                                          log.Fatal(err)
                                      }
                                    
                                      // 4. 处理数据包
                                      packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                      for packet := range packetSource.Packets() {
                                          processPacket(packet)
                                      }
                                  }
                                  
                                  func processPacket(packet gopacket.Packet) {
                                      // 检查DNS层
                                      dnsLayer := packet.Layer(layers.LayerTypeDNS)
                                      if dnsLayer != nil {
                                          dns, _ := dnsLayer.(*layers.DNS)
                                          printDNSInfo(dns)
                                      }
                                    
                                      // 检查TCP DNS
                                      tcpLayer := packet.Layer(layers.LayerTypeTCP)
                                      if tcpLayer != nil {
                                          tcp, _ := tcpLayer.(*layers.TCP)
                                          if len(tcp.Payload) > 0 && (tcp.SrcPort == 53 || tcp.DstPort == 53) {
                                              dns := &layers.DNS{}
                                              err := dns.DecodeFromBytes(tcp.Payload, gopacket.NilDecodeFeedback)
                                              if err == nil {
                                                  printDNSInfo(dns)
                                              }
                                          }
                                      }
                                  }
                                  
                                  func printDNSInfo(dns *layers.DNS) {
                                      // 打印基本信息
                                      direction := "Query"
                                      if dns.QR {
                                          direction = "Response"
                                      }
                                    
                                      fmt.Printf("n=== %s ===n", direction)
                                      fmt.Printf("Transaction ID: 0x%xn", dns.ID)
                                      fmt.Printf("Flags: %s (QR: %t, OpCode: %s, AA: %t, TC: %t, RD: %t, RA: %t, Z: %d, RCode: %s)n",
                                          dns.Flags, dns.QR, dns.OpCode, dns.AA, dns.TC, dns.RD, dns.RA, dns.Z, dns.ResponseCode)
                                    
                                      // 打印问题部分
                                      if len(dns.Questions) > 0 {
                                          fmt.Println("nQuestions:")
                                          for _, q := range dns.Questions {
                                              fmt.Printf("- %s (Type: %s, Class: %s)n", 
                                                  string(q.Name), q.Type, q.Class)
                                          }
                                      }
                                    
                                      // 打印回答部分
                                      if len(dns.Answers) > 0 {
                                          fmt.Println("nAnswers:")
                                          for _, a := range dns.Answers {
                                              fmt.Printf("- %s: %s (Type: %s, TTL: %d)n",
                                                  string(a.Name), getDNSRecordValue(a), a.Type, a.TTL)
                                          }
                                      }
                                    
                                      // 打印权威部分
                                      if len(dns.Authorities) > 0 {
                                          fmt.Println("nAuthorities:")
                                          for _, a := range dns.Authorities {
                                              fmt.Printf("- %s: %s (Type: %s, TTL: %d)n",
                                                  string(a.Name), getDNSRecordValue(a), a.Type, a.TTL)
                                          }
                                      }
                                    
                                      // 打印附加部分
                                      if len(dns.Additionals) > 0 {
                                          fmt.Println("nAdditionals:")
                                          for _, a := range dns.Additionals {
                                              fmt.Printf("- %s: %s (Type: %s, TTL: %d)n",
                                                  string(a.Name), getDNSRecordValue(a), a.Type, a.TTL)
                                          }
                                      }
                                  }
                                  
                                  func getDNSRecordValue(r layers.DNSResourceRecord) string {
                                      switch r.Type {
                                      case layers.DNSTypeA:
                                          return r.IP.String()
                                      case layers.DNSTypeAAAA:
                                          return r.IP.String()
                                      case layers.DNSTypeCNAME:
                                          return string(r.CNAME)
                                      case layers.DNSTypeMX:
                                          return fmt.Sprintf("%s (pref %d)", string(r.MX), r.Preference)
                                      case layers.DNSTypeNS:
                                          return string(r.NS)
                                      case layers.DNSTypePTR:
                                          return string(r.PTR)
                                      case layers.DNSTypeSOA:
                                          return fmt.Sprintf("MName: %s, RName: %s", string(r.SOA.MName), string(r.SOA.RName))
                                      case layers.DNSTypeTXT:
                                          return string(r.TXT)
                                      case layers.DNSTypeSRV:
                                          return fmt.Sprintf("Target: %s, Port: %d, Priority: %d, Weight: %d", 
                                              string(r.SRV.Name), r.SRV.Port, r.SRV.Priority, r.SRV.Weight)
                                      default:
                                          return fmt.Sprintf("[Type %d Data]", r.Type)
                                      }
                                  }
                                  

                                  • 权限要求:需要root或管理员权限才能捕获网络数据包
                                  • 性能考虑:高流量环境下可能需要优化处理逻辑
                                  • DNS over HTTPS/TLS:这种方法无法解析DoH/DoT加密的DNS流量
                                  • EDNS扩展:如果需要解析EDNS扩展信息,需要额外处理OPT记录

                                  通过这种组合使用 pcaplayers 包,你可以构建功能强大的DNS监控和分析工具,能够详细解析DNS协议的各种细节。

                                  要从 layers.DNS 数据包中提取域名和对应的 IP 地址,你需要检查 DNS 响应中的回答部分 (Answers)。以下是详细方法和示例代码:

                                  • 检查 DNS 响应:确保是 DNS 响应 (QR == true)
                                  • 遍历回答记录:检查 Answers 切片
                                  • 过滤 A 和 AAAA 记录:获取 IPv4 和 IPv6 地址
                                  • 解析记录数据:将二进制数据转换为可读格式

                                  package main
                                  
                                  import (
                                      "fmt"
                                      "github.com/google/gopacket"
                                      "github.com/google/gopacket/layers"
                                      "github.com/google/gopacket/pcap"
                                      "net"
                                  )
                                  
                                  func main() {
                                      // 打开网络接口
                                      handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever)
                                      if err != nil {
                                          panic(err)
                                      }
                                      defer handle.Close()
                                    
                                      // 设置过滤器只捕获 DNS 响应
                                      err = handle.SetBPFFilter("udp and port 53")
                                      if err != nil {
                                          panic(err)
                                      }
                                    
                                      // 开始捕获数据包
                                      packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
                                      for packet := range packetSource.Packets() {
                                          // 检查是否包含 DNS 层
                                          dnsLayer := packet.Layer(layers.LayerTypeDNS)
                                          if dnsLayer == nil {
                                              continue
                                          }
                                        
                                          dns, _ := dnsLayer.(*layers.DNS)
                                        
                                          // 只处理响应包
                                          if !dns.QR {
                                              continue
                                          }
                                        
                                          // 遍历所有回答记录
                                          for _, answer := range dns.Answers {
                                              var ip string
                                            
                                              // 根据记录类型处理
                                              switch answer.Type {
                                              case layers.DNSTypeA:
                                                  // IPv4 地址
                                                  if len(answer.Data) == net.IPv4len {
                                                      ip = net.IP(answer.Data).String()
                                                  }
                                              case layers.DNSTypeAAAA:
                                                  // IPv6 地址
                                                  if len(answer.Data) == net.IPv6len {
                                                      ip = net.IP(answer.Data).String()
                                                  }
                                              default:
                                                  continue // 跳过非IP记录
                                              }
                                            
                                              if ip != "" {
                                                  fmt.Printf("域名: %s, IP: %s, TTL: %dn", 
                                                      string(answer.Name), ip, answer.TTL)
                                              }
                                          }
                                      }
                                  }
                                  

                                  下面是一个更完整的函数,可以处理各种情况:

                                  func extractDomainsAndIPs(dns *layers.DNS) map[string][]string {
                                      result := make(map[string][]string)
                                    
                                      // 首先收集所有查询的域名
                                      var domains []string
                                      for _, q := range dns.Questions {
                                          domains = append(domains, string(q.Name))
                                      }
                                    
                                      // 处理回答记录
                                      for _, answer := range dns.Answers {
                                          domain := string(answer.Name)
                                          var ip string
                                        
                                          switch answer.Type {
                                          case layers.DNSTypeA:
                                              if len(answer.Data) >= net.IPv4len {
                                                  ip = net.IP(answer.Data).String()
                                              }
                                          case layers.DNSTypeAAAA:
                                              if len(answer.Data) >= net.IPv6len {
                                                  ip = net.IP(answer.Data).String()
                                              }
                                          case layers.DNSTypeCNAME:
                                              // 处理CNAME记录
                                              cname := string(answer.Data)
                                              result[domain] = append(result[domain], "CNAME: "+cname)
                                              continue
                                          default:
                                              continue
                                          }
                                        
                                          if ip != "" {
                                              result[domain] = append(result[domain], ip)
                                          }
                                      }
                                    
                                      return result
                                  }
                                  

                                  • CNAME 记录:如果遇到 CNAME 记录,你可能需要继续查找对应的 A/AAAA 记录
                                  • 多IP情况:一个域名可能对应多个IP地址
                                  • 压缩域名layers.DNS 已经自动处理了DNS名称压缩

                                  • 预分配切片:如果你知道大致数量,可以预分配切片大小
                                  • 重用缓冲区:在处理大量数据包时重用缓冲区
                                  • 并行处理:使用 goroutine 池处理数据包

                                  func processDNSResponse(dns *layers.DNS) {
                                      if !dns.QR {
                                          return // 不是响应包
                                      }
                                    
                                      // 创建域名到IP的映射
                                      domainToIPs := make(map[string][]string)
                                      cnameMap := make(map[string]string)
                                    
                                      // 首先处理CNAME记录
                                      for _, answer := range dns.Answers {
                                          if answer.Type == layers.DNSTypeCNAME {
                                              domain := string(answer.Name)
                                              cname := string(answer.Data)
                                              cnameMap[domain] = cname
                                          }
                                      }
                                    
                                      // 然后处理A和AAAA记录
                                      for _, answer := range dns.Answers {
                                          var ip string
                                          domain := string(answer.Name)
                                        
                                          switch answer.Type {
                                          case layers.DNSTypeA:
                                              if len(answer.Data) >= net.IPv4len {
                                                  ip = net.IP(answer.Data).String()
                                              }
                                          case layers.DNSTypeAAAA:
                                              if len(answer.Data) >= net.IPv6len {
                                                  ip = net.IP(answer.Data).String()
                                              }
                                          default:
                                              continue
                                          }
                                        
                                          if ip != "" {
                                              // 检查是否有CNAME链
                                              finalDomain := domain
                                              for {
                                                  if cname, exists := cnameMap[finalDomain]; exists {
                                                      finalDomain = cname
                                                  } else {
                                                      break
                                                  }
                                              }
                                              domainToIPs[finalDomain] = append(domainToIPs[finalDomain], ip)
                                          }
                                      }
                                    
                                      // 打印结果
                                      for domain, ips := range domainToIPs {
                                          fmt.Printf("域名: %sn", domain)
                                          for _, ip := range ips {
                                              fmt.Printf("  IP: %sn", ip)
                                          }
                                      }
                                  }
                                  

                                  通过这些方法,你可以有效地从 layers.DNS 数据包中提取域名和对应的IP地址,并处理各种DNS记录类型和特殊情况。

                                  以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。

                                  您可能感兴趣的文章:

                                  • 使用Golang实现对网络数据包的捕获与分析
                                  • Golang实现读取ZIP压缩包并显示Gin静态html网站
                                  • golang版本升级如何实现
                                  • golang格式化输出函数printf、sprintf、fprintf解读
                                  • golang如何获取域名ip dns信息

                                  站内搜索