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, ð, &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(ð) 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(ð) 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