funcmain() { // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil {log.Fatal(err) } defer handle.Close()
// Use the handle as a packet source to process all packets packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // Process packet here fmt.Println(packet) } }
funcmain() { // Open output pcap file and write header f, _ := os.Create("test.pcap") w := pcapgo.NewWriter(f) w.WriteFileHeader(snapshotLen, layers.LinkTypeEthernet) defer f.Close()
// Open the device for capturing handle, err = pcap.OpenLive(deviceName, snapshotLen, promiscuous, timeout) if err != nil { fmt.Printf("Error opening device %s: %v", deviceName, err) os.Exit(1) } defer handle.Close()
// Start processing packets packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // Process packet here fmt.Println(packet) w.WritePacket(packet.Metadata().CaptureInfo, packet.Data()) packetCount++ // Only capture 100 and then stop if packetCount > 100 { break } } }
funcmain() { // Open file instead of device handle, err = pcap.OpenOffline(pcapFile) if err != nil { log.Fatal(err) } defer handle.Close()
// Loop through packets in file packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { fmt.Println(packet) } }
// Set filter var filter string = "tcp and port 80" err = handle.SetBPFFilter(filter) if err != nil { log.Fatal(err) } fmt.Println("Only capturing TCP port 80 packets.")
packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // Do something with a packet here. fmt.Println(packet) }
funcmain() { // Open device handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout) if err != nil {log.Fatal(err) } defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { printPacketInfo(packet) } }
funcprintPacketInfo(packet gopacket.Packet) { // Let's see if the packet is an ethernet packet ethernetLayer := packet.Layer(layers.LayerTypeEthernet) if ethernetLayer != nil { fmt.Println("Ethernet layer detected.") ethernetPacket, _ := ethernetLayer.(*layers.Ethernet) fmt.Println("Source MAC: ", ethernetPacket.SrcMAC) fmt.Println("Destination MAC: ", ethernetPacket.DstMAC) // Ethernet type is typically IPv4 but could be ARP or other fmt.Println("Ethernet type: ", ethernetPacket.EthernetType) fmt.Println() }
// Let's see if the packet is IP (even though the ether type told us) ipLayer := packet.Layer(layers.LayerTypeIPv4) if ipLayer != nil { fmt.Println("IPv4 layer detected.") ip, _ := ipLayer.(*layers.IPv4)
// IP layer variables: // Version (Either 4 or 6) // IHL (IP Header Length in 32-bit words) // TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?), // Checksum, SrcIP, DstIP fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP) fmt.Println("Protocol: ", ip.Protocol) fmt.Println() }
// Let's see if the packet is TCP tcpLayer := packet.Layer(layers.LayerTypeTCP) if tcpLayer != nil { fmt.Println("TCP layer detected.") tcp, _ := tcpLayer.(*layers.TCP)
// Iterate over all layers, printing out each layer type fmt.Println("All packet layers:") for _, layer := range packet.Layers() { fmt.Println("- ", layer.LayerType()) }
// When iterating through packet.Layers() above, // if it lists Payload layer then that is the same as // this applicationLayer. applicationLayer contains the payload applicationLayer := packet.ApplicationLayer() if applicationLayer != nil { fmt.Println("Application layer/Payload found.") fmt.Printf("%s\n", applicationLayer.Payload())
// Search for a string inside the payload if strings.Contains(string(applicationLayer.Payload()), "HTTP") { fmt.Println("HTTP found!") } }
// Check for errors if err := packet.ErrorLayer(); err != nil { fmt.Println("Error decoding some part of the packet:", err) } }
funcmain() { // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil {log.Fatal(err) } defer handle.Close()
// Send raw bytes over wire rawBytes := []byte{10, 20, 30} err = handle.WritePacketData(rawBytes) if err != nil { log.Fatal(err) }
// Create a properly formed packet, just with // empty details. Should fill out MAC addresses, // IP addresses, etc. buffer = gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, &layers.Ethernet{}, &layers.IPv4{}, &layers.TCP{}, gopacket.Payload(rawBytes), ) outgoingPacket := buffer.Bytes() // Send our packet err = handle.WritePacketData(outgoingPacket) if err != nil { log.Fatal(err) }
// This time lets fill out some information ipLayer := &layers.IPv4{ SrcIP: net.IP{127, 0, 0, 1}, DstIP: net.IP{8, 8, 8, 8}, } ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA}, DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD}, } tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(4321), DstPort: layers.TCPPort(80), } // And create the packet with the layers buffer = gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, tcpLayer, gopacket.Payload(rawBytes), ) outgoingPacket = buffer.Bytes() }
funcmain() { // If we don't have a handle to a device or a file, but we have a bunch // of raw bytes, we can try to decode them in to packet information
// NewPacket() takes the raw bytes that make up the packet as the first parameter // The second parameter is the lowest level layer you want to decode. It will // decode that layer and all layers on top of it. The third layer // is the type of decoding: default(all at once), lazy(on demand), and NoCopy // which will not create a copy of the buffer
// Create an packet with ethernet, IP, TCP, and payload layers // We are creating one we know will be decoded properly but // your byte source could be anything. If any of the packets // come back as nil, that means it could not decode it in to // the proper layer (malformed or incorrect packet type) payload := []byte{2, 4, 6} options := gopacket.SerializeOptions{} buffer := gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, &layers.Ethernet{}, &layers.IPv4{}, &layers.TCP{}, gopacket.Payload(payload), ) rawBytes := buffer.Bytes()
// with Lazy decoding it will only decode what it needs when it needs it // This is not concurrency safe. If using concurrency, use default ipPacket := gopacket.NewPacket( rawBytes, layers.LayerTypeIPv4, gopacket.Lazy, )
// With the NoCopy option, the underlying slices are referenced // directly and not copied. If the underlying bytes change so will // the packet tcpPacket := gopacket.NewPacket( rawBytes, layers.LayerTypeTCP, gopacket.NoCopy, )
// Create custom layer structure type CustomLayer struct { // This layer just has two bytes at the front SomeByte byte AnotherByte byte restOfData []byte }
// Register the layer type so we can use it // The first argument is an ID. Use negative // or 2000+ for custom layers. It must be unique var CustomLayerType = gopacket.RegisterLayerType( 2001, gopacket.LayerTypeMetadata{ "CustomLayerType", gopacket.DecodeFunc(decodeCustomLayer), }, )
// When we inquire about the type, what type of layer should // we say it is? We want it to return our custom layer type func(l CustomLayer) LayerType() gopacket.LayerType { return CustomLayerType }
// LayerContents returns the information that our layer // provides. In this case it is a header layer so // we return the header information func(l CustomLayer) LayerContents() []byte { return []byte{l.SomeByte, l.AnotherByte} }
// LayerPayload returns the subsequent layer built // on top of our layer or raw payload func(l CustomLayer) LayerPayload() []byte { return l.restOfData }
// Custom decode function. We can name it whatever we want // but it should have the same arguments and return value // When the layer is registered we tell it to use this decode function funcdecodeCustomLayer(data []byte, p gopacket.PacketBuilder)error { // AddLayer appends to the list of layers that the packet has p.AddLayer(&CustomLayer{data[0], data[1], data[2:]})
// The return value tells the packet what layer to expect // with the rest of the data. It could be another header layer, // nothing, or a payload layer.
// nil means this is the last layer. No more decoding // return nil
// Returning another layer type tells it to decode // the next layer with that layer's decoder function // return p.NextDecoder(layers.LayerTypeEthernet)
// Returning payload type means the rest of the data // is raw payload. It will set the application layer // contents with the payload return p.NextDecoder(gopacket.LayerTypePayload) }
funcmain() { // If you create your own encoding and decoding you can essentially // create your own protocol or implement a protocol that is not // already defined in the layers package. In our example we are just // wrapping a normal ethernet packet with our own layer. // Creating your own protocol is good if you want to create // some obfuscated binary data type that was difficult for others // to decode
// Finally, decode your packets: rawBytes := []byte{0xF0, 0x0F, 65, 65, 66, 67, 68} packet := gopacket.NewPacket( rawBytes, CustomLayerType, gopacket.Default, ) fmt.Println("Created packet out of raw bytes.") fmt.Println(packet)
// Decode the packet as our custom layer customLayer := packet.Layer(CustomLayerType) if customLayer != nil { fmt.Println("Packet was successfully decoded with custom layer decoder.") customLayerContent, _ := customLayer.(*CustomLayer) // Now we can access the elements of the custom struct fmt.Println("Payload: ", customLayerContent.LayerPayload()) fmt.Println("SomeByte element:", customLayerContent.SomeByte) fmt.Println("AnotherByte element:", customLayerContent.AnotherByte) } }