diff --git a/parser/parse.go b/parser/parse.go index 1e7caae..70e1dbd 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -69,26 +69,17 @@ func ParseDevice(device string, snapshotLen int32, promiscuous bool, timeout tim func ParseDns(handle *pcap.Handle) { var ( schema DnsSchema - eth layers.Ethernet - dot1q layers.Dot1Q - ip4 layers.IPv4 - ip6 layers.IPv6 - tcp layers.TCP - udp layers.UDP - ldns layers.DNS + stats Statistics + ip4 *layers.IPv4 + ip6 *layers.IPv6 + tcp *layers.TCP + udp *layers.UDP ) - // Keep track of parsing statistics - stats := Statistics{} - // Set the source and sensor for packet source schema.Sensor = Sensor schema.Source = Source - // Let's reuse the same layers for performance improvement - parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &ip6, &tcp, &udp, &ldns) - var decoded []gopacket.LayerType - // Use the handle as a packet source to process all packets packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packetSource.NoCopy = true @@ -97,49 +88,72 @@ PACKETLOOP: for packet := range packetSource.Packets() { stats.PacketTotal += 1 - if err := parser.DecodeLayers(packet.Data(), &decoded); err != nil { - log.Debugf("Could not decode layers: %v\n", err) - } - - // Let's decode different layers - msg := new(dns.Msg) - for _, layerType := range decoded { - switch layerType { + // Let's analyze decoded layers + var msg *dns.Msg + for _, curLayer := range packet.Layers() { + switch curLayer.LayerType() { case layers.LayerTypeIPv4: - stats.PacketIPv4 += 1 + ip4 = curLayer.(*layers.IPv4) schema.SourceAddress = ip4.SrcIP.String() schema.DestinationAddress = ip4.DstIP.String() schema.Ipv4 = true + stats.PacketIPv4 += 1 case layers.LayerTypeIPv6: - stats.PacketIPv6 += 1 + ip6 = curLayer.(*layers.IPv6) schema.SourceAddress = ip6.SrcIP.String() schema.DestinationAddress = ip6.DstIP.String() schema.Ipv4 = false + stats.PacketIPv6 += 1 case layers.LayerTypeTCP: + tcp = curLayer.(*layers.TCP) stats.PacketTcp += 1 - schema.SourcePort = uint16(tcp.SrcPort) - schema.DestinationPort = uint16(tcp.DstPort) - schema.Udp = false - schema.Sha256 = fmt.Sprintf("%x", sha256.Sum256(tcp.Payload)) + + if !DoParseTcp { + continue PACKETLOOP + } + + msg = new(dns.Msg) if err := msg.Unpack(tcp.Payload); err != nil { log.Errorf("Could not decode DNS: %v\n", err) stats.PacketErrors += 1 continue PACKETLOOP } + stats.PacketDns += 1 + + schema.SourcePort = uint16(tcp.SrcPort) + schema.DestinationPort = uint16(tcp.DstPort) + schema.Udp = false + schema.Sha256 = fmt.Sprintf("%x", sha256.Sum256(tcp.Payload)) case layers.LayerTypeUDP: + udp = curLayer.(*layers.UDP) stats.PacketUdp += 1 - schema.SourcePort = uint16(udp.SrcPort) - schema.DestinationPort = uint16(udp.DstPort) - schema.Udp = true - schema.Sha256 = fmt.Sprintf("%x", sha256.Sum256(udp.Payload)) + + msg = new(dns.Msg) if err := msg.Unpack(udp.Payload); err != nil { log.Errorf("Could not decode DNS: %v\n", err) stats.PacketErrors += 1 continue PACKETLOOP } + stats.PacketDns += 1 + + schema.SourcePort = uint16(udp.SrcPort) + schema.DestinationPort = uint16(udp.DstPort) + schema.Udp = true + schema.Sha256 = fmt.Sprintf("%x", sha256.Sum256(udp.Payload)) } } + // This means we did not attempt to parse a DNS payload + if msg == nil { + // Let's check if we had any errors decoding any of the packet layers + if err := packet.ErrorLayer(); err != nil { + log.Debugf("Error decoding some part of the packet:", err) + stats.PacketErrors += 1 + } + + continue PACKETLOOP + } + // Ignore questions unless flag set if !msg.Response && !DoParseQuestions && !DoParseQuestionsEcs { continue PACKETLOOP @@ -184,9 +198,10 @@ PACKETLOOP: schema.Qtype = qr.Qtype } - // 1. Print all questions - // 2. Print only questions with ECS - // 3. Print NXDOMAINs without RRs (i.e., SOA) + // Let's get QUESTION information on if: + // 1. Questions flag is set + // 2. QuestionsEcs flag is set and ECS information in question + // 3. NXDOMAINs without RRs (i.e., SOA) if (DoParseQuestions && !schema.Response) || (DoParseQuestionsEcs && schema.EcsClient != nil && !schema.Response) || (schema.Rcode == 3 && len(msg.Ns) < 1) { @@ -207,11 +222,6 @@ PACKETLOOP: for _, rr := range msg.Extra { schema.ToJson(&rr, DnsAdditional) } - - // Let's check and see if we had any errors decoding any of the packets - if err := packet.ErrorLayer(); err != nil { - log.Debugf("Error decoding some part of the packet:", err) - } } log.Infof("Number of TOTAL packets: %v", stats.PacketTotal) @@ -219,5 +229,6 @@ PACKETLOOP: log.Infof("Number of IPv6 packets: %v", stats.PacketIPv6) log.Infof("Number of UDP packets: %v", stats.PacketUdp) log.Infof("Number of TCP packets: %v", stats.PacketTcp) + log.Infof("Number of DNS packets: %v", stats.PacketDns) log.Infof("Number of FAILED packets: %v", stats.PacketErrors) } diff --git a/parser/stats.go b/parser/stats.go index e34d277..01fe377 100644 --- a/parser/stats.go +++ b/parser/stats.go @@ -12,6 +12,7 @@ type Statistics struct { PacketIPv6 uint `json:"packetIPv6"` PacketTcp uint `json:"packetTcp"` PacketUdp uint `json:"packetUdp"` + PacketDns uint `json:"packetDns"` PacketErrors uint `json:"packetErrors"` }