slimcap

module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 8, 2024 License: Apache-2.0

README

A high-performance network packet capture library

Github Release GoDoc Go Report Card Build/Test Status CodeQL

This package provides a simple yet powerful interface to perform network packet capture / sniffing. It is focused on high performance / traffic throughput.

Features

  • Support for raw payload / IP layer packet capture via AF_PACKET (Linux) directly from network socket or using a ring buffer
  • Minimal CPU usage and memory (allocation) footprint, support for zero-copy operations
  • Virtual / mock capture sources including traffic replay from PCAP files (or even "chaining" multiple sources)
  • Inherent support for packet type / direction detection
  • Written in native Go (no CGO dependency)

[!WARNING] This package does not perform any payload / network layer decoding
slimcap is aimed at doing the heavy lifting of extracting up to the IP layer of network packets with the utmost performance possible (and hence limits itself to packets which actually have an IP layer). All further parsing / processing must be done by the caller.

Installation

go get -u github.com/fako1024/slimcap

Usage

Perform simple capture of a few packets on a network interface using the various options of the capture.Source interface, using a fixed capture length (i.e. snaplen) of 64 bytes:
listener, err := afpacket.NewSource("enp1s0",
	afpacket.CaptureLength(link.CaptureLengthFixed(64)),
)
if err != nil {
	// Error handling
}

// Capture a packet from the wire (allocate & copy)
p, err := listener.NextPacket(nil)
if err != nil {
	// Error handling
}
fmt.Printf("Received packet on enp1s0 (total len %d): %v (inbound: %v)\n",
	p.TotalLen(), p.Payload(), p.IsInbound())

// Capture a packet from the wire (copy to existing / reusable buffer packet)
pBuf := listener.NewPacket()
p, err := listener.NextPacket(pBuf)
if err != nil {
	// Error handling
}
fmt.Printf("Received packet on enp1s0 (total len %d): %v (inbound: %v)\n",
	p.TotalLen(), p.Payload(), p.IsInbound())

// Capture a packet from the wire (function execution)
if err := listener.NextPacketFn(func(payload []byte, totalLen uint32, pktType, ipLayerOffset byte) (err error) {
	fmt.Printf("Received packet on enp1s0 (total len %d): %v (inbound: %v)\n",
		totalLen, payload, pktType != capture.PacketOutgoing)
	return
}); err != nil {
	// Error handling
}

// Close the listener / the capture
if err := listener.Close(); err != nil {
	// Error handling
}
Perform zero-copy capture of a few packets on a network interface using the various options of the capture.SourceZeroCopy interface, using an optimal capture length (i.e. snaplen) to ensure any transport layer can be accessed for IPv4 & IPv6 packets and setting custom ring buffer size / number of blocks:
listener, err := afring.NewSource("enp1s0",
	afring.CaptureLength(link.CaptureLengthMinimalIPv6Transport),
	afring.BufferSize((1<<20), 4),
	afring.Promiscuous(false),
)
if err != nil {
	// Error handling
}

// Capture a raw packet (full payload) from the wire (zero-copy, no heap allocation)
payload, pktType, totalLen, err := listener.NextPayloadZeroCopy()
if err != nil {
	// Error handling
}
fmt.Printf("Received payload on enp1s0 (total len %d): %v (inbound: %v)\n",
	totalLen, payload, pktType != capture.PacketOutgoing)

// Capture a packet (IP layer only) from the wire (zero-copy, no heap allocation)
ipLayer, pktType, totalLen, err := listener.NextIPPacketZeroCopy()
if err != nil {
	// Error handling
}
fmt.Printf("Received IP layer on enp1s0 (total len %d): %v (inbound: %v)\n",
	totalLen, ipLayer, pktType != capture.PacketOutgoing)

// Close the listener / the capture
if err := listener.Close(); err != nil {
	// Error handling
}

[!WARNING] In zero-copy mode, any and all interaction with the payload / IP Layer must be concluded prior to the next invocation of Next...ZeroCopy() since the calls provide direct access to the memory areas allocated by AF_PACKET (which may be overwritten by the next call)!

For further examples, please refer to the implementations in examples. A production-level project that uses slimcap and showcases all its capabilities (including end-to-end testing using mock sources) is goProbe.

Performance

The following benchmarks (c.f. afring_mock_test.go) show the relative difference in general performance and memory allocation footprint of a single packet retrieval (obtained on a commodity Laptop using mock capture sources). For obvious reasons, zero-copy mode performs best and hence should be chosen in high-throughput scenarios:

goarch: amd64
pkg: github.com/fako1024/slimcap/capture/afpacket/afring
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkCaptureMethods
BenchmarkCaptureMethods/NextPacket         	226401712	  74.60 ns/op	64 B/op	  1 allocs/op
BenchmarkCaptureMethods/NextPacketInPlace  	353661006	  32.17 ns/op	 0 B/op	  0 allocs/op
BenchmarkCaptureMethods/NextPayload        	176332635	  63.81 ns/op	48 B/op	  1 allocs/op
BenchmarkCaptureMethods/NextPayloadInPlace 	516911223	  21.65 ns/op	 0 B/op	  0 allocs/op
BenchmarkCaptureMethods/NextPayloadZeroCopy     535092314	  19.67 ns/op	 0 B/op	  0 allocs/op
BenchmarkCaptureMethods/NextIPPacket            179753388	  64.18 ns/op	48 B/op	  1 allocs/op
BenchmarkCaptureMethods/NextIPPacketInPlace     381187490	  28.33 ns/op	 0 B/op	  0 allocs/op
BenchmarkCaptureMethods/NextIPPacketZeroCopy    567278034	  19.67 ns/op	 0 B/op	  0 allocs/op
BenchmarkCaptureMethods/NextPacketFn            559334258	  20.44 ns/op	 0 B/op	  0 allocs/op

Capture Mocks / Testing

In order to support extensive testing up to end-to-end level without having to rely on actual network interface capture, both plain AF_PACKET and ring buffer captures are provided with mock-level sources implementing / wrapping their actual implementations. Hence, it is possible to simply exchange any invocation of an afpacket or afring source with their respective mock counterpart, e.g. by changing:

listener, err := afring.NewSource("enp1s0",
	// Options
)

to

listener, err := afring.NewMockSource("enp1s0",
	// Options
)

By either generating synthetic packet data or piping previously captured packets from a PCAP file these mock sources can then be used just like actual capture sources, e.g. for testing purposes. Some good examples on how to perform test using mocks can be found in afpacket_mock_test.go and afring_mock_test.go, respectively. Since the mock implementations incur a minor, yet significant performance overhead (even if not used), slimcap supports a build tag that allows disabling mocks completely (which in turn will also remove the aforementioned overhead):

go build -tags slimcap_nomock

Using this build tag for high performance production environments is recommended.

Bug Reports & Feature Requests

Please use the issue tracker for bugs and feature requests (or any other matter).

License

See the LICENSE file for usage conditions.

Directories

Path Synopsis
Package capture provides the high level / central interface definitions for all slimcap capture sources and core structures.
Package capture provides the high level / central interface definitions for all slimcap capture sources and core structures.
afpacket/afpacket
Package afpacket implements a capture.Source that allows reading network packets from Linux network interfaces via the AF_PACKET mechanism.
Package afpacket implements a capture.Source that allows reading network packets from Linux network interfaces via the AF_PACKET mechanism.
afpacket/afring
Package afring implements a capture.Source and a capture.SourceZeroCopy that allows reading network packets from Linux network interfaces via the AF_PACKET / TPacket ring buffer mechanism.
Package afring implements a capture.Source and a capture.SourceZeroCopy that allows reading network packets from Linux network interfaces via the AF_PACKET / TPacket ring buffer mechanism.
afpacket/socket
Package socket implements AF_PACKET sockets / file descriptors (both for `afring` and plain `afpacket` modes).
Package socket implements AF_PACKET sockets / file descriptors (both for `afring` and plain `afpacket` modes).
pcap
Package pcap allows reading / parsing pcap files (compressed and uncompressed) and implement the capture.Source interface.
Package pcap allows reading / parsing pcap files (compressed and uncompressed) and implement the capture.Source interface.
Package event provides access to system-level event file descriptors that act as semaphores and notification mechanism to facilitate AF_PACKET network traffic capture.
Package event provides access to system-level event file descriptors that act as semaphores and notification mechanism to facilitate AF_PACKET network traffic capture.
examples
dump
Package dump provides a simple packet dump tool that will simply consume up to a certain number of network packets from the provided interface and then exit.
Package dump provides a simple packet dump tool that will simply consume up to a certain number of network packets from the provided interface and then exit.
pcap
Package pcap provides a simple packet dump tool that will simply consume up to a certain number of previously captured network packets from the provided pcap file, optionally log them and then exit.
Package pcap provides a simple packet dump tool that will simply consume up to a certain number of previously captured network packets from the provided pcap file, optionally log them and then exit.
trace
Package trace provides a comprehensive tool that supports various common use cases when interacting with the `slimcap` module, including plain and ring-buffer AF_PACKET capture on multiple interfaces, zero-copy mode (if requested) and optional logging and profiling.
Package trace provides a comprehensive tool that supports various common use cases when interacting with the `slimcap` module, including plain and ring-buffer AF_PACKET capture on multiple interfaces, zero-copy mode (if requested) and optional logging and profiling.
Package link provides access to network interfaces and their parameters, such as link type and flags.
Package link provides access to network interfaces and their parameters, such as link type and flags.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL