Andrea Campanella | 7167ebb | 2020-02-24 09:56:38 +0100 | [diff] [blame] | 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 | |
| 61 | Reading Packets From A Source |
| 62 | |
| 63 | Most of the time, you won't just have a []byte of packet data lying around. |
| 64 | Instead, you'll want to read packets in from somewhere (file, interface, etc) |
| 65 | and process them. To do that, you'll want to build a PacketSource. |
| 66 | |
| 67 | First, you'll need to construct an object that implements the PacketDataSource |
| 68 | interface. There are implementations of this interface bundled with gopacket |
| 69 | in the gopacket/pcap and gopacket/pfring subpackages... see their documentation |
| 70 | for more information on their usage. Once you have a PacketDataSource, you can |
| 71 | pass it into NewPacketSource, along with a Decoder of your choice, to create |
| 72 | a PacketSource. |
| 73 | |
| 74 | Once you have a PacketSource, you can read packets from it in multiple ways. |
| 75 | See the docs for PacketSource for more details. The easiest method is the |
| 76 | Packets function, which returns a channel, then asynchronously writes new |
| 77 | packets into that channel, closing the channel if the packetSource hits an |
| 78 | end-of-file. |
| 79 | |
| 80 | packetSource := ... // construct using pcap or pfring |
| 81 | for packet := range packetSource.Packets() { |
| 82 | handlePacket(packet) // do something with each packet |
| 83 | } |
| 84 | |
| 85 | You can change the decoding options of the packetSource by setting fields in |
| 86 | packetSource.DecodeOptions... see the following sections for more details. |
| 87 | |
| 88 | |
| 89 | Lazy Decoding |
| 90 | |
| 91 | gopacket optionally decodes packet data lazily, meaning it |
| 92 | only decodes a packet layer when it needs to handle a function call. |
| 93 | |
| 94 | // Create a packet, but don't actually decode anything yet |
| 95 | packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy) |
| 96 | // Now, decode the packet up to the first IPv4 layer found but no further. |
| 97 | // If no IPv4 layer was found, the whole packet will be decoded looking for |
| 98 | // it. |
| 99 | ip4 := packet.Layer(layers.LayerTypeIPv4) |
| 100 | // Decode all layers and return them. The layers up to the first IPv4 layer |
| 101 | // are already decoded, and will not require decoding a second time. |
| 102 | layers := packet.Layers() |
| 103 | |
| 104 | Lazily-decoded packets are not concurrency-safe. Since layers have not all been |
| 105 | decoded, each call to Layer() or Layers() has the potential to mutate the packet |
| 106 | in order to decode the next layer. If a packet is used |
| 107 | in multiple goroutines concurrently, don't use gopacket.Lazy. Then gopacket |
| 108 | will decode the packet fully, and all future function calls won't mutate the |
| 109 | object. |
| 110 | |
| 111 | |
| 112 | NoCopy Decoding |
| 113 | |
| 114 | By default, gopacket will copy the slice passed to NewPacket and store the |
| 115 | copy within the packet, so future mutations to the bytes underlying the slice |
| 116 | don't affect the packet and its layers. If you can guarantee that the |
| 117 | underlying slice bytes won't be changed, you can use NoCopy to tell |
| 118 | gopacket.NewPacket, and it'll use the passed-in slice itself. |
| 119 | |
| 120 | // This channel returns new byte slices, each of which points to a new |
| 121 | // memory location that's guaranteed immutable for the duration of the |
| 122 | // packet. |
| 123 | for data := range myByteSliceChannel { |
| 124 | p := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) |
| 125 | doSomethingWithPacket(p) |
| 126 | } |
| 127 | |
| 128 | The fastest method of decoding is to use both Lazy and NoCopy, but note from |
| 129 | the many caveats above that for some implementations either or both may be |
| 130 | dangerous. |
| 131 | |
| 132 | |
| 133 | Pointers To Known Layers |
| 134 | |
| 135 | During decoding, certain layers are stored in the packet as well-known |
| 136 | layer types. For example, IPv4 and IPv6 are both considered NetworkLayer |
| 137 | layers, while TCP and UDP are both TransportLayer layers. We support 4 |
| 138 | layers, corresponding to the 4 layers of the TCP/IP layering scheme (roughly |
| 139 | anagalous to layers 2, 3, 4, and 7 of the OSI model). To access these, |
| 140 | you can use the packet.LinkLayer, packet.NetworkLayer, |
| 141 | packet.TransportLayer, and packet.ApplicationLayer functions. Each of |
| 142 | these functions returns a corresponding interface |
| 143 | (gopacket.{Link,Network,Transport,Application}Layer). The first three |
| 144 | provide methods for getting src/dst addresses for that particular layer, |
| 145 | while the final layer provides a Payload function to get payload data. |
| 146 | This is helpful, for example, to get payloads for all packets regardless |
| 147 | of their underlying data type: |
| 148 | |
| 149 | // Get packets from some source |
| 150 | for packet := range someSource { |
| 151 | if app := packet.ApplicationLayer(); app != nil { |
| 152 | if strings.Contains(string(app.Payload()), "magic string") { |
| 153 | fmt.Println("Found magic string in a packet!") |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | A particularly useful layer is ErrorLayer, which is set whenever there's |
| 159 | an error parsing part of the packet. |
| 160 | |
| 161 | packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Default) |
| 162 | if err := packet.ErrorLayer(); err != nil { |
| 163 | fmt.Println("Error decoding some part of the packet:", err) |
| 164 | } |
| 165 | |
| 166 | Note that we don't return an error from NewPacket because we may have decoded |
| 167 | a number of layers successfully before running into our erroneous layer. You |
| 168 | may still be able to get your Ethernet and IPv4 layers correctly, even if |
| 169 | your TCP layer is malformed. |
| 170 | |
| 171 | |
| 172 | Flow And Endpoint |
| 173 | |
| 174 | gopacket has two useful objects, Flow and Endpoint, for communicating in a protocol |
| 175 | independent manner the fact that a packet is coming from A and going to B. |
| 176 | The general layer types LinkLayer, NetworkLayer, and TransportLayer all provide |
| 177 | methods for extracting their flow information, without worrying about the type |
| 178 | of the underlying Layer. |
| 179 | |
| 180 | A Flow is a simple object made up of a set of two Endpoints, one source and one |
| 181 | destination. It details the sender and receiver of the Layer of the Packet. |
| 182 | |
| 183 | An Endpoint is a hashable representation of a source or destination. For |
| 184 | example, for LayerTypeIPv4, an Endpoint contains the IP address bytes for a v4 |
| 185 | IP packet. A Flow can be broken into Endpoints, and Endpoints can be combined |
| 186 | into Flows: |
| 187 | |
| 188 | packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy) |
| 189 | netFlow := packet.NetworkLayer().NetworkFlow() |
| 190 | src, dst := netFlow.Endpoints() |
| 191 | reverseFlow := gopacket.NewFlow(dst, src) |
| 192 | |
| 193 | Both Endpoint and Flow objects can be used as map keys, and the equality |
| 194 | operator can compare them, so you can easily group together all packets |
| 195 | based on endpoint criteria: |
| 196 | |
| 197 | flows := map[gopacket.Endpoint]chan gopacket.Packet |
| 198 | packet := gopacket.NewPacket(myPacketData, layers.LayerTypeEthernet, gopacket.Lazy) |
| 199 | // Send all TCP packets to channels based on their destination port. |
| 200 | if tcp := packet.Layer(layers.LayerTypeTCP); tcp != nil { |
| 201 | flows[tcp.TransportFlow().Dst()] <- packet |
| 202 | } |
| 203 | // Look for all packets with the same source and destination network address |
| 204 | if net := packet.NetworkLayer(); net != nil { |
| 205 | src, dst := net.NetworkFlow().Endpoints() |
| 206 | if src == dst { |
| 207 | fmt.Println("Fishy packet has same network source and dst: %s", src) |
| 208 | } |
| 209 | } |
| 210 | // Find all packets coming from UDP port 1000 to UDP port 500 |
| 211 | interestingFlow := gopacket.NewFlow(layers.NewUDPPortEndpoint(1000), layers.NewUDPPortEndpoint(500)) |
| 212 | if t := packet.NetworkLayer(); t != nil && t.TransportFlow() == interestingFlow { |
| 213 | fmt.Println("Found that UDP flow I was looking for!") |
| 214 | } |
| 215 | |
| 216 | For load-balancing purposes, both Flow and Endpoint have FastHash() functions, |
| 217 | which provide quick, non-cryptographic hashes of their contents. Of particular |
| 218 | importance is the fact that Flow FastHash() is symmetric: A->B will have the same |
| 219 | hash as B->A. An example usage could be: |
| 220 | |
| 221 | channels := [8]chan gopacket.Packet |
| 222 | for i := 0; i < 8; i++ { |
| 223 | channels[i] = make(chan gopacket.Packet) |
| 224 | go packetHandler(channels[i]) |
| 225 | } |
| 226 | for packet := range getPackets() { |
| 227 | if net := packet.NetworkLayer(); net != nil { |
| 228 | channels[int(net.NetworkFlow().FastHash()) & 0x7] <- packet |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | This allows us to split up a packet stream while still making sure that each |
| 233 | stream sees all packets for a flow (and its bidirectional opposite). |
| 234 | |
| 235 | |
| 236 | Implementing Your Own Decoder |
| 237 | |
| 238 | If your network has some strange encapsulation, you can implement your own |
| 239 | decoder. In this example, we handle Ethernet packets which are encapsulated |
| 240 | in a 4-byte header. |
| 241 | |
| 242 | // Create a layer type, should be unique and high, so it doesn't conflict, |
| 243 | // giving it a name and a decoder to use. |
| 244 | var MyLayerType = gopacket.RegisterLayerType(12345, gopacket.LayerTypeMetadata{Name: "MyLayerType", Decoder: gopacket.DecodeFunc(decodeMyLayer)}) |
| 245 | |
| 246 | // Implement my layer |
| 247 | type MyLayer struct { |
| 248 | StrangeHeader []byte |
| 249 | payload []byte |
| 250 | } |
| 251 | func (m MyLayer) LayerType() gopacket.LayerType { return MyLayerType } |
| 252 | func (m MyLayer) LayerContents() []byte { return m.StrangeHeader } |
| 253 | func (m MyLayer) LayerPayload() []byte { return m.payload } |
| 254 | |
| 255 | // Now implement a decoder... this one strips off the first 4 bytes of the |
| 256 | // packet. |
| 257 | func decodeMyLayer(data []byte, p gopacket.PacketBuilder) error { |
| 258 | // Create my layer |
| 259 | p.AddLayer(&MyLayer{data[:4], data[4:]}) |
| 260 | // Determine how to handle the rest of the packet |
| 261 | return p.NextDecoder(layers.LayerTypeEthernet) |
| 262 | } |
| 263 | |
| 264 | // Finally, decode your packets: |
| 265 | p := gopacket.NewPacket(data, MyLayerType, gopacket.Lazy) |
| 266 | |
| 267 | See the docs for Decoder and PacketBuilder for more details on how coding |
| 268 | decoders works, or look at RegisterLayerType and RegisterEndpointType to see how |
| 269 | to add layer/endpoint types to gopacket. |
| 270 | |
| 271 | |
| 272 | Fast Decoding With DecodingLayerParser |
| 273 | |
| 274 | TLDR: DecodingLayerParser takes about 10% of the time as NewPacket to decode |
| 275 | packet data, but only for known packet stacks. |
| 276 | |
| 277 | Basic decoding using gopacket.NewPacket or PacketSource.Packets is somewhat slow |
| 278 | due to its need to allocate a new packet and every respective layer. It's very |
| 279 | versatile and can handle all known layer types, but sometimes you really only |
| 280 | care about a specific set of layers regardless, so that versatility is wasted. |
| 281 | |
| 282 | DecodingLayerParser avoids memory allocation altogether by decoding packet |
| 283 | layers directly into preallocated objects, which you can then reference to get |
| 284 | the packet's information. A quick example: |
| 285 | |
| 286 | func main() { |
| 287 | var eth layers.Ethernet |
| 288 | var ip4 layers.IPv4 |
| 289 | var ip6 layers.IPv6 |
| 290 | var tcp layers.TCP |
| 291 | parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp) |
| 292 | decoded := []gopacket.LayerType{} |
| 293 | for packetData := range somehowGetPacketData() { |
| 294 | if err := parser.DecodeLayers(packetData, &decoded); err != nil { |
| 295 | fmt.Fprintf(os.Stderr, "Could not decode layers: %v\n", err) |
| 296 | continue |
| 297 | } |
| 298 | for _, layerType := range decoded { |
| 299 | switch layerType { |
| 300 | case layers.LayerTypeIPv6: |
| 301 | fmt.Println(" IP6 ", ip6.SrcIP, ip6.DstIP) |
| 302 | case layers.LayerTypeIPv4: |
| 303 | fmt.Println(" IP4 ", ip4.SrcIP, ip4.DstIP) |
| 304 | } |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | The important thing to note here is that the parser is modifying the passed in |
| 310 | layers (eth, ip4, ip6, tcp) instead of allocating new ones, thus greatly |
| 311 | speeding up the decoding process. It's even branching based on layer type... |
| 312 | it'll handle an (eth, ip4, tcp) or (eth, ip6, tcp) stack. However, it won't |
| 313 | handle any other type... since no other decoders were passed in, an (eth, ip4, |
| 314 | udp) stack will stop decoding after ip4, and only pass back [LayerTypeEthernet, |
| 315 | LayerTypeIPv4] through the 'decoded' slice (along with an error saying it can't |
| 316 | decode a UDP packet). |
| 317 | |
| 318 | Unfortunately, not all layers can be used by DecodingLayerParser... only those |
| 319 | implementing the DecodingLayer interface are usable. Also, it's possible to |
| 320 | create DecodingLayers that are not themselves Layers... see |
| 321 | layers.IPv6ExtensionSkipper for an example of this. |
| 322 | |
| 323 | |
| 324 | Creating Packet Data |
| 325 | |
| 326 | As well as offering the ability to decode packet data, gopacket will allow you |
| 327 | to create packets from scratch, as well. A number of gopacket layers implement |
| 328 | the SerializableLayer interface; these layers can be serialized to a []byte in |
| 329 | the following manner: |
| 330 | |
| 331 | ip := &layers.IPv4{ |
| 332 | SrcIP: net.IP{1, 2, 3, 4}, |
| 333 | DstIP: net.IP{5, 6, 7, 8}, |
| 334 | // etc... |
| 335 | } |
| 336 | buf := gopacket.NewSerializeBuffer() |
| 337 | opts := gopacket.SerializeOptions{} // See SerializeOptions for more details. |
| 338 | err := ip.SerializeTo(buf, opts) |
| 339 | if err != nil { panic(err) } |
| 340 | fmt.Println(buf.Bytes()) // prints out a byte slice containing the serialized IPv4 layer. |
| 341 | |
| 342 | SerializeTo PREPENDS the given layer onto the SerializeBuffer, and they treat |
| 343 | the current buffer's Bytes() slice as the payload of the serializing layer. |
| 344 | Therefore, you can serialize an entire packet by serializing a set of layers in |
| 345 | reverse order (Payload, then TCP, then IP, then Ethernet, for example). The |
| 346 | SerializeBuffer's SerializeLayers function is a helper that does exactly that. |
| 347 | |
| 348 | To generate a (empty and useless, because no fields are set) |
| 349 | Ethernet(IPv4(TCP(Payload))) packet, for example, you can run: |
| 350 | |
| 351 | buf := gopacket.NewSerializeBuffer() |
| 352 | opts := gopacket.SerializeOptions{} |
| 353 | gopacket.SerializeLayers(buf, opts, |
| 354 | &layers.Ethernet{}, |
| 355 | &layers.IPv4{}, |
| 356 | &layers.TCP{}, |
| 357 | gopacket.Payload([]byte{1, 2, 3, 4})) |
| 358 | packetData := buf.Bytes() |
| 359 | |
| 360 | A Final Note |
| 361 | |
| 362 | If you use gopacket, you'll almost definitely want to make sure gopacket/layers |
| 363 | is imported, since when imported it sets all the LayerType variables and fills |
| 364 | in a lot of interesting variables/maps (DecodersByLayerName, etc). Therefore, |
| 365 | it's recommended that even if you don't use any layers functions directly, you still import with: |
| 366 | |
| 367 | import ( |
| 368 | _ "github.com/google/gopacket/layers" |
| 369 | ) |
| 370 | */ |
| 371 | package gopacket |