github.com/gopacket/gopacket@v1.1.0/doc.go (about)

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  /*
     8  Package gopacket provides packet decoding for the Go language.
     9  
    10  gopacket contains many sub-packages with additional functionality you may find
    11  useful, including:
    12  
    13    - layers: You'll probably use this every time.  This contains of the logic
    14      built into gopacket for decoding packet protocols.  Note that all example
    15      code below assumes that you have imported both gopacket and
    16      gopacket/layers.
    17    - pcap: C bindings to use libpcap to read packets off the wire.
    18    - pfring: C bindings to use PF_RING to read packets off the wire.
    19    - afpacket: C bindings for Linux's AF_PACKET to read packets off the wire.
    20    - tcpassembly: TCP stream reassembly
    21  
    22  Also, if you're looking to dive right into code, see the examples subdirectory
    23  for numerous simple binaries built using gopacket libraries.
    24  
    25  Minimum go version required is 1.5 except for pcapgo/EthernetHandle, afpacket,
    26  and bsdbpf which need at least 1.7 due to x/sys/unix dependencies.
    27  
    28  # Basic Usage
    29  
    30  gopacket takes in packet data as a []byte and decodes it into a packet with
    31  a non-zero number of "layers".  Each layer corresponds to a protocol
    32  within the bytes.  Once a packet has been decoded, the layers of the packet
    33  can be requested from the packet.
    34  
    35  	// Decode a packet
    36  	packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Default)
    37  	// Get the TCP layer from this packet
    38  	if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
    39  	  fmt.Println("This is a TCP packet!")
    40  	  // Get actual TCP data from this layer
    41  	  tcp, _ := tcpLayer.(*layers.TCP)
    42  	  fmt.Printf("From src port %d to dst port %d\n", tcp.SrcPort, tcp.DstPort)
    43  	}
    44  	// Iterate over all layers, printing out each layer type
    45  	for _, layer := range packet.Layers() {
    46  	  fmt.Println("PACKET LAYER:", layer.LayerType())
    47  	}
    48  
    49  Packets can be decoded from a number of starting points.  Many of our base
    50  types implement Decoder, which allow us to decode packets for which
    51  we don't have full data.
    52  
    53  	// Decode an ethernet packet
    54  	ethP := gopacket.NewPacket(p1, layers.LayerTypeEthernet, gopacket.Default)
    55  	// Decode an IPv6 header and everything it contains
    56  	ipP := gopacket.NewPacket(p2, layers.LayerTypeIPv6, gopacket.Default)
    57  	// Decode a TCP header and its payload
    58  	tcpP := gopacket.NewPacket(p3, layers.LayerTypeTCP, gopacket.Default)
    59  
    60  # Reading Packets From A Source
    61  
    62  Most of the time, you won't just have a []byte of packet data lying around.
    63  Instead, you'll want to read packets in from somewhere (file, interface, etc)
    64  and process them.  To do that, you'll want to build a PacketSource.
    65  
    66  First, you'll need to construct an object that implements the PacketDataSource
    67  interface.  There are implementations of this interface bundled with gopacket
    68  in the gopacket/pcap and gopacket/pfring subpackages... see their documentation
    69  for more information on their usage.  Once you have a PacketDataSource, you can
    70  pass it into NewPacketSource, along with a Decoder of your choice, to create
    71  a PacketSource.
    72  
    73  Once you have a PacketSource, you can read packets from it in multiple ways.
    74  See the docs for PacketSource for more details.  The easiest method is the
    75  Packets function, which returns a channel, then asynchronously writes new
    76  packets into that channel, closing the channel if the packetSource hits an
    77  end-of-file.
    78  
    79  	packetSource := ...  // construct using pcap or pfring
    80  	for packet := range packetSource.Packets() {
    81  	  handlePacket(packet)  // do something with each packet
    82  	}
    83  
    84  You can change the decoding options of the packetSource by setting fields in
    85  packetSource.DecodeOptions... see the following sections for more details.
    86  
    87  # Lazy Decoding
    88  
    89  gopacket optionally decodes packet data lazily, meaning it
    90  only decodes a packet layer when it needs to handle a function call.
    91  
    92  	// Create a packet, but don't actually decode anything yet
    93  	packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy)
    94  	// Now, decode the packet up to the first IPv4 layer found but no further.
    95  	// If no IPv4 layer was found, the whole packet will be decoded looking for
    96  	// it.
    97  	ip4 := packet.Layer(layers.LayerTypeIPv4)
    98  	// Decode all layers and return them.  The layers up to the first IPv4 layer
    99  	// are already decoded, and will not require decoding a second time.
   100  	layers := packet.Layers()
   101  
   102  Lazily-decoded packets are not concurrency-safe.  Since layers have not all been
   103  decoded, each call to Layer() or Layers() has the potential to mutate the packet
   104  in order to decode the next layer.  If a packet is used
   105  in multiple goroutines concurrently, don't use gopacket.Lazy.  Then gopacket
   106  will decode the packet fully, and all future function calls won't mutate the
   107  object.
   108  
   109  # NoCopy Decoding
   110  
   111  By default, gopacket will copy the slice passed to NewPacket and store the
   112  copy within the packet, so future mutations to the bytes underlying the slice
   113  don't affect the packet and its layers.  If you can guarantee that the
   114  underlying slice bytes won't be changed, you can use NoCopy to tell
   115  gopacket.NewPacket, and it'll use the passed-in slice itself.
   116  
   117  	// This channel returns new byte slices, each of which points to a new
   118  	// memory location that's guaranteed immutable for the duration of the
   119  	// packet.
   120  	for data := range myByteSliceChannel {
   121  	  p := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
   122  	  doSomethingWithPacket(p)
   123  	}
   124  
   125  The fastest method of decoding is to use both Lazy and NoCopy, but note from
   126  the many caveats above that for some implementations either or both may be
   127  dangerous.
   128  
   129  # Pointers To Known Layers
   130  
   131  During decoding, certain layers are stored in the packet as well-known
   132  layer types.  For example, IPv4 and IPv6 are both considered NetworkLayer
   133  layers, while TCP and UDP are both TransportLayer layers.  We support 4
   134  layers, corresponding to the 4 layers of the TCP/IP layering scheme (roughly
   135  anagalous to layers 2, 3, 4, and 7 of the OSI model).  To access these,
   136  you can use the packet.LinkLayer, packet.NetworkLayer,
   137  packet.TransportLayer, and packet.ApplicationLayer functions.  Each of
   138  these functions returns a corresponding interface
   139  (gopacket.{Link,Network,Transport,Application}Layer).  The first three
   140  provide methods for getting src/dst addresses for that particular layer,
   141  while the final layer provides a Payload function to get payload data.
   142  This is helpful, for example, to get payloads for all packets regardless
   143  of their underlying data type:
   144  
   145  	// Get packets from some source
   146  	for packet := range someSource {
   147  	  if app := packet.ApplicationLayer(); app != nil {
   148  	    if strings.Contains(string(app.Payload()), "magic string") {
   149  	      fmt.Println("Found magic string in a packet!")
   150  	    }
   151  	  }
   152  	}
   153  
   154  A particularly useful layer is ErrorLayer, which is set whenever there's
   155  an error parsing part of the packet.
   156  
   157  	packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Default)
   158  	if err := packet.ErrorLayer(); err != nil {
   159  	  fmt.Println("Error decoding some part of the packet:", err)
   160  	}
   161  
   162  Note that we don't return an error from NewPacket because we may have decoded
   163  a number of layers successfully before running into our erroneous layer.  You
   164  may still be able to get your Ethernet and IPv4 layers correctly, even if
   165  your TCP layer is malformed.
   166  
   167  # Flow And Endpoint
   168  
   169  gopacket has two useful objects, Flow and Endpoint, for communicating in a protocol
   170  independent manner the fact that a packet is coming from A and going to B.
   171  The general layer types LinkLayer, NetworkLayer, and TransportLayer all provide
   172  methods for extracting their flow information, without worrying about the type
   173  of the underlying Layer.
   174  
   175  A Flow is a simple object made up of a set of two Endpoints, one source and one
   176  destination.  It details the sender and receiver of the Layer of the Packet.
   177  
   178  An Endpoint is a hashable representation of a source or destination.  For
   179  example, for LayerTypeIPv4, an Endpoint contains the IP address bytes for a v4
   180  IP packet.  A Flow can be broken into Endpoints, and Endpoints can be combined
   181  into Flows:
   182  
   183  	packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy)
   184  	netFlow := packet.NetworkLayer().NetworkFlow()
   185  	src, dst := netFlow.Endpoints()
   186  	reverseFlow := gopacket.NewFlow(dst, src)
   187  
   188  Both Endpoint and Flow objects can be used as map keys, and the equality
   189  operator can compare them, so you can easily group together all packets
   190  based on endpoint criteria:
   191  
   192  	flows := map[gopacket.Endpoint]chan gopacket.Packet
   193  	packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy)
   194  	// Send all TCP packets to channels based on their destination port.
   195  	if tcp := packet.Layer(layers.LayerTypeTCP); tcp != nil {
   196  	  flows[tcp.TransportFlow().Dst()] <- packet
   197  	}
   198  	// Look for all packets with the same source and destination network address
   199  	if net := packet.NetworkLayer(); net != nil {
   200  	  src, dst := net.NetworkFlow().Endpoints()
   201  	  if src == dst {
   202  	    fmt.Println("Fishy packet has same network source and dst: %s", src)
   203  	  }
   204  	}
   205  	// Find all packets coming from UDP port 1000 to UDP port 500
   206  	interestingFlow := gopacket.FlowFromEndpoints(layers.NewUDPPortEndpoint(1000), layers.NewUDPPortEndpoint(500))
   207  	if t := packet.NetworkLayer(); t != nil && t.TransportFlow() == interestingFlow {
   208  	  fmt.Println("Found that UDP flow I was looking for!")
   209  	}
   210  
   211  For load-balancing purposes, both Flow and Endpoint have FastHash() functions,
   212  which provide quick, non-cryptographic hashes of their contents.  Of particular
   213  importance is the fact that Flow FastHash() is symmetric: A->B will have the same
   214  hash as B->A.  An example usage could be:
   215  
   216  	channels := [8]chan gopacket.Packet
   217  	for i := 0; i < 8; i++ {
   218  	  channels[i] = make(chan gopacket.Packet)
   219  	  go packetHandler(channels[i])
   220  	}
   221  	for packet := range getPackets() {
   222  	  if net := packet.NetworkLayer(); net != nil {
   223  	    channels[int(net.NetworkFlow().FastHash()) & 0x7] <- packet
   224  	  }
   225  	}
   226  
   227  This allows us to split up a packet stream while still making sure that each
   228  stream sees all packets for a flow (and its bidirectional opposite).
   229  
   230  # Implementing Your Own Decoder
   231  
   232  If your network has some strange encapsulation, you can implement your own
   233  decoder.  In this example, we handle Ethernet packets which are encapsulated
   234  in a 4-byte header.
   235  
   236  	// Create a layer type, should be unique and high, so it doesn't conflict,
   237  	// giving it a name and a decoder to use.
   238  	var MyLayerType = gopacket.RegisterLayerType(12345, gopacket.LayerTypeMetadata{Name: "MyLayerType", Decoder: gopacket.DecodeFunc(decodeMyLayer)})
   239  
   240  	// Implement my layer
   241  	type MyLayer struct {
   242  	  StrangeHeader []byte
   243  	  payload []byte
   244  	}
   245  	func (m MyLayer) LayerType() gopacket.LayerType { return MyLayerType }
   246  	func (m MyLayer) LayerContents() []byte { return m.StrangeHeader }
   247  	func (m MyLayer) LayerPayload() []byte { return m.payload }
   248  
   249  	// Now implement a decoder... this one strips off the first 4 bytes of the
   250  	// packet.
   251  	func decodeMyLayer(data []byte, p gopacket.PacketBuilder) error {
   252  	  // Create my layer
   253  	  p.AddLayer(&MyLayer{data[:4], data[4:]})
   254  	  // Determine how to handle the rest of the packet
   255  	  return p.NextDecoder(layers.LayerTypeEthernet)
   256  	}
   257  
   258  	// Finally, decode your packets:
   259  	p := gopacket.NewPacket(data, MyLayerType, gopacket.Lazy)
   260  
   261  See the docs for Decoder and PacketBuilder for more details on how coding
   262  decoders works, or look at RegisterLayerType and RegisterEndpointType to see how
   263  to add layer/endpoint types to gopacket.
   264  
   265  # Fast Decoding With DecodingLayerParser
   266  
   267  TLDR:  DecodingLayerParser takes about 10% of the time as NewPacket to decode
   268  packet data, but only for known packet stacks.
   269  
   270  Basic decoding using gopacket.NewPacket or PacketSource.Packets is somewhat slow
   271  due to its need to allocate a new packet and every respective layer.  It's very
   272  versatile and can handle all known layer types, but sometimes you really only
   273  care about a specific set of layers regardless, so that versatility is wasted.
   274  
   275  DecodingLayerParser avoids memory allocation altogether by decoding packet
   276  layers directly into preallocated objects, which you can then reference to get
   277  the packet's information.  A quick example:
   278  
   279  	func main() {
   280  	  var eth layers.Ethernet
   281  	  var ip4 layers.IPv4
   282  	  var ip6 layers.IPv6
   283  	  var tcp layers.TCP
   284  	  parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &ip6, &tcp)
   285  	  decoded := []gopacket.LayerType{}
   286  	  for packetData := range somehowGetPacketData() {
   287  	    if err := parser.DecodeLayers(packetData, &decoded); err != nil {
   288  	      fmt.Fprintf(os.Stderr, "Could not decode layers: %v\n", err)
   289  	      continue
   290  	    }
   291  	    for _, layerType := range decoded {
   292  	      switch layerType {
   293  	        case layers.LayerTypeIPv6:
   294  	          fmt.Println("    IP6 ", ip6.SrcIP, ip6.DstIP)
   295  	        case layers.LayerTypeIPv4:
   296  	          fmt.Println("    IP4 ", ip4.SrcIP, ip4.DstIP)
   297  	      }
   298  	    }
   299  	  }
   300  	}
   301  
   302  The important thing to note here is that the parser is modifying the passed in
   303  layers (eth, ip4, ip6, tcp) instead of allocating new ones, thus greatly
   304  speeding up the decoding process.  It's even branching based on layer type...
   305  it'll handle an (eth, ip4, tcp) or (eth, ip6, tcp) stack.  However, it won't
   306  handle any other type... since no other decoders were passed in, an (eth, ip4,
   307  udp) stack will stop decoding after ip4, and only pass back [LayerTypeEthernet,
   308  LayerTypeIPv4] through the 'decoded' slice (along with an error saying it can't
   309  decode a UDP packet).
   310  
   311  Unfortunately, not all layers can be used by DecodingLayerParser... only those
   312  implementing the DecodingLayer interface are usable.  Also, it's possible to
   313  create DecodingLayers that are not themselves Layers... see
   314  layers.IPv6ExtensionSkipper for an example of this.
   315  
   316  # Faster And Customized Decoding with DecodingLayerContainer
   317  
   318  By default, DecodingLayerParser uses native map to store and search for a layer
   319  to decode. Though being versatile, in some cases this solution may be not so
   320  optimal. For example, if you have only few layers faster operations may be
   321  provided by sparse array indexing or linear array scan.
   322  
   323  To accomodate these scenarios, DecodingLayerContainer interface is introduced
   324  along with its implementations: DecodingLayerSparse, DecodingLayerArray and
   325  DecodingLayerMap. You can specify a container implementation to
   326  DecodingLayerParser with SetDecodingLayerContainer method. Example:
   327  
   328  	dlp := gopacket.NewDecodingLayerParser(LayerTypeEthernet)
   329  	dlp.SetDecodingLayerContainer(gopacket.DecodingLayerSparse(nil))
   330  	var eth layers.Ethernet
   331  	dlp.AddDecodingLayer(&eth)
   332  	// ... add layers and use DecodingLayerParser as usual...
   333  
   334  To skip one level of indirection (though sacrificing some capabilities) you may
   335  also use DecodingLayerContainer as a decoding tool as it is. In this case you have to
   336  handle unknown layer types and layer panics by yourself. Example:
   337  
   338  	func main() {
   339  	  var eth layers.Ethernet
   340  	  var ip4 layers.IPv4
   341  	  var ip6 layers.IPv6
   342  	  var tcp layers.TCP
   343  	  dlc := gopacket.DecodingLayerContainer(gopacket.DecodingLayerArray(nil))
   344  	  dlc = dlc.Put(&eth)
   345  	  dlc = dlc.Put(&ip4)
   346  	  dlc = dlc.Put(&ip6)
   347  	  dlc = dlc.Put(&tcp)
   348  	  // you may specify some meaningful DecodeFeedback
   349  	  decoder := dlc.LayersDecoder(LayerTypeEthernet, gopacket.NilDecodeFeedback)
   350  	  decoded := make([]gopacket.LayerType, 0, 20)
   351  	  for packetData := range somehowGetPacketData() {
   352  	    lt, err := decoder(packetData, &decoded)
   353  	    if err != nil {
   354  	      fmt.Fprintf(os.Stderr, "Could not decode layers: %v\n", err)
   355  	      continue
   356  	    }
   357  	    if lt != gopacket.LayerTypeZero {
   358  	      fmt.Fprintf(os.Stderr, "unknown layer type: %v\n", lt)
   359  	      continue
   360  	    }
   361  	    for _, layerType := range decoded {
   362  	      // examine decoded layertypes just as already shown above
   363  	    }
   364  	  }
   365  	}
   366  
   367  DecodingLayerSparse is the fastest but most effective when LayerType values
   368  that layers in use can decode are not large because otherwise that would lead
   369  to bigger memory footprint. DecodingLayerArray is very compact and primarily
   370  usable if the number of decoding layers is not big (up to ~10-15, but please do
   371  your own benchmarks). DecodingLayerMap is the most versatile one and used by
   372  DecodingLayerParser by default. Please refer to tests and benchmarks in layers
   373  subpackage to further examine usage examples and performance measurements.
   374  
   375  You may also choose to implement your own DecodingLayerContainer if you want to
   376  make use of your own internal packet decoding logic.
   377  
   378  # Creating Packet Data
   379  
   380  As well as offering the ability to decode packet data, gopacket will allow you
   381  to create packets from scratch, as well.  A number of gopacket layers implement
   382  the SerializableLayer interface; these layers can be serialized to a []byte in
   383  the following manner:
   384  
   385  	ip := &layers.IPv4{
   386  	  SrcIP: net.IP{1, 2, 3, 4},
   387  	  DstIP: net.IP{5, 6, 7, 8},
   388  	  // etc...
   389  	}
   390  	buf := gopacket.NewSerializeBuffer()
   391  	opts := gopacket.SerializeOptions{}  // See SerializeOptions for more details.
   392  	err := ip.SerializeTo(buf, opts)
   393  	if err != nil { panic(err) }
   394  	fmt.Println(buf.Bytes())  // prints out a byte slice containing the serialized IPv4 layer.
   395  
   396  SerializeTo PREPENDS the given layer onto the SerializeBuffer, and they treat
   397  the current buffer's Bytes() slice as the payload of the serializing layer.
   398  Therefore, you can serialize an entire packet by serializing a set of layers in
   399  reverse order (Payload, then TCP, then IP, then Ethernet, for example).  The
   400  SerializeBuffer's SerializeLayers function is a helper that does exactly that.
   401  
   402  To generate a (empty and useless, because no fields are set)
   403  Ethernet(IPv4(TCP(Payload))) packet, for example, you can run:
   404  
   405  	buf := gopacket.NewSerializeBuffer()
   406  	opts := gopacket.SerializeOptions{}
   407  	gopacket.SerializeLayers(buf, opts,
   408  	  &layers.Ethernet{},
   409  	  &layers.IPv4{},
   410  	  &layers.TCP{},
   411  	  gopacket.Payload([]byte{1, 2, 3, 4}))
   412  	packetData := buf.Bytes()
   413  
   414  # A Final Note
   415  
   416  If you use gopacket, you'll almost definitely want to make sure gopacket/layers
   417  is imported, since when imported it sets all the LayerType variables and fills
   418  in a lot of interesting variables/maps (DecodersByLayerName, etc).  Therefore,
   419  it's recommended that even if you don't use any layers functions directly, you still import with:
   420  
   421  	import (
   422  	  _ "github.com/gopacket/gopacket/layers"
   423  	)
   424  */
   425  package gopacket