func gatherPacketLayersInfo(event common.MapStr, packet gopacket.Packet) { // see https://godoc.org/github.com/google/gopacket#hdr-Pointers_To_Known_Layers // Pointers To Known Layers: // During decoding, certain layers are stored in the packet as well-known layer types. // For example, IPv4 and IPv6 are both considered NetworkLayer layers, // while TCP and UDP are both TransportLayer layers. // We support 4 layers, corresponding to the 4 layers of the TCP/IP layering scheme // (roughly anagalous to layers 2, 3, 4, and 7 of the OSI model). // To access these, you can use the: // packet.LinkLayer, // packet.NetworkLayer, // packet.TransportLayer, and // packet.ApplicationLayer functions. // Each of these functions returns a corresponding interface (gopacket.{Link,Network,Transport,Application}Layer). // The first three provide methods for getting src/dst addresses for that particular layer, // while the final layer provides a Payload function to get payload data. // use "packet.Dump()" as a fail-safe to capture all available layers for a packet, // just in case we encounter something unexpected in the unified2 file or we // have neglected to handle a particular layer explicitly event["packet_dump"] = packet.Dump() // "packet.Dump()" is very verbose, i.e. a large amount of text, but that's ok // capture the name of the layers found var packet_layers []string for _, layer := range packet.Layers() { packet_layers = append(packet_layers, fmt.Sprintf("%v", layer.LayerType())) } event["packet_layers"] = packet_layers // Ethernet layer? ethernetLayer := packet.Layer(layers.LayerTypeEthernet) if ethernetLayer != nil { ethernetPacket, _ := ethernetLayer.(*layers.Ethernet) event["ethernet_src_mac"] = fmt.Sprintf("%v", ethernetPacket.SrcMAC) event["ethernet_dst_mac"] = fmt.Sprintf("%v", ethernetPacket.DstMAC) // ethernet type is typically IPv4 but could be ARP or other event["ethernet_type"] = fmt.Sprintf("%v", ethernetPacket.EthernetType) // Length is only set if a length field exists within this header. Ethernet // headers follow two different standards, one that uses an EthernetType, the // other which defines a length the follows with a LLC header (802.3). If the // former is the case, we set EthernetType and Length stays 0. In the latter // case, we set Length and EthernetType = EthernetTypeLLC. event["ethernet_length"] = fmt.Sprintf("%v", ethernetPacket.Length) } // IPv4 layer? ipLayer := packet.Layer(layers.LayerTypeIPv4) if ipLayer != nil { ip, _ := ipLayer.(*layers.IPv4) event["ip_version"] = ip.Version event["ip_ihl"] = ip.IHL event["ip_tos"] = ip.TOS event["ip_length"] = ip.Length event["ip_id"] = ip.Id event["ip_flags"] = ip.Flags event["ip_fragoffset"] = ip.FragOffset event["ip_ttl"] = ip.TTL event["ip_protocol"] = ip.Protocol event["ip_checksum"] = ip.Checksum event["ip_src_ip"] = ip.SrcIP event["ip_dst_ip"] = ip.DstIP event["ip_options"] = ip.Options // maybe? fmt.Sprintf("%v", ip.Options) event["ip_padding"] = ip.Padding } // IPv6 layer? ip6Layer := packet.Layer(layers.LayerTypeIPv6) if ip6Layer != nil { ip6, _ := ip6Layer.(*layers.IPv6) event["ip6_version"] = ip6.Version event["ip6_trafficclass"] = ip6.TrafficClass event["ip6_flowlabel"] = ip6.FlowLabel event["ip6_length"] = ip6.Length event["ip6_nextheader"] = ip6.NextHeader event["ip6_hoplimit"] = ip6.HopLimit event["ip6_src_ip"] = ip6.SrcIP event["ip6_dst_ip"] = ip6.DstIP event["ip6_hopbyhop"] = ip6.HopByHop } // see: gopacket/layers folder ... what layers are needed for Snort/Suricata alerts? // ICMPv4 layer? // ICMPv6 layer? // ARP layer? // UDP layer? udpLayer := packet.Layer(layers.LayerTypeUDP) if udpLayer != nil { udp, _ := udpLayer.(*layers.UDP) event["udp_src_port"] = udp.SrcPort event["udp_dst_port"] = udp.DstPort event["udp_length"] = udp.Length event["udp_checksum"] = udp.Checksum } // TCP layer? tcpLayer := packet.Layer(layers.LayerTypeTCP) if tcpLayer != nil { tcp, _ := tcpLayer.(*layers.TCP) event["tcp_src_port"] = tcp.SrcPort event["tcp_dst_port"] = tcp.DstPort event["tcp_seq"] = tcp.Seq event["tcp_ack"] = tcp.Ack event["tcp_data_offset"] = tcp.DataOffset event["tcp_fin"] = tcp.FIN event["tcp_syn"] = tcp.SYN event["tcp_rst"] = tcp.RST event["tcp_psh"] = tcp.PSH event["tcp_ack"] = tcp.ACK event["tcp_urg"] = tcp.URG event["tcp_ece"] = tcp.ECE event["tcp_cwr"] = tcp.CWR event["tcp_ns"] = tcp.NS event["tcp_window"] = tcp.Window event["tcp_checksum"] = tcp.Checksum event["tcp_urgent"] = tcp.Urgent event["tcp_options"] = tcp.Options // maybe? fmt.Sprintf("%v", tcp.Options) event["tcp_padding"] = tcp.Padding } // note: the Payload layer is the same as this applicationLayer // also, we can get payloads for all packets regardless of their underlying data type: // application layer? (aka packet payload) applicationLayer := packet.ApplicationLayer() if applicationLayer != nil { event["packet_payload"] = fmt.Sprintf("%s", applicationLayer.Payload()) } // errors? if err := packet.ErrorLayer(); err != nil { event["packet_error"] = fmt.Sprintf("Packet decoding error: %v", err) } }