capture

package
v0.70.5 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: BSD-3-Clause Imports: 15 Imported by: 0

Documentation

Overview

Package capture provides userspace packet capture in pcap format.

It taps decrypted WireGuard packets flowing through the FilteredDevice and writes them as pcap (readable by tcpdump, tshark, Wireshark) or as human-readable one-line-per-packet text.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AFPacketCapture

type AFPacketCapture struct {
	// contains filtered or unexported fields
}

AFPacketCapture reads raw packets from a network interface using an AF_PACKET socket. This is the kernel-mode fallback when FilteredDevice is not available (kernel WireGuard). Linux only.

It implements device.PacketCapture so it can be set on a Session, but it drives its own read loop rather than being called from FilteredDevice. Call Start to begin and Stop to end.

func NewAFPacketCapture

func NewAFPacketCapture(ifaceName string, sess *Session) *AFPacketCapture

NewAFPacketCapture creates a capture bound to the given interface. The session receives packets via Offer.

func (*AFPacketCapture) Offer

func (c *AFPacketCapture) Offer([]byte, bool)

Offer satisfies device.PacketCapture but is unused: the AFPacketCapture drives its own read loop. This exists only so the type signature is compatible if someone tries to set it as a PacketCapture.

func (*AFPacketCapture) Start

func (c *AFPacketCapture) Start() error

Start opens the AF_PACKET socket and begins reading packets. Packets are fed to the session via Offer. Returns immediately; the read loop runs in a goroutine.

func (*AFPacketCapture) Stop

func (c *AFPacketCapture) Stop()

Stop closes the socket and waits for the read loop to exit. Idempotent.

type Direction

type Direction uint8

Direction indicates whether a packet is entering or leaving the host.

const (
	// Inbound is a packet arriving from the network (FilteredDevice.Write path).
	Inbound Direction = iota
	// Outbound is a packet leaving the host (FilteredDevice.Read path).
	Outbound
)

func (Direction) String

func (d Direction) String() string

String returns "IN" or "OUT".

type Filter

type Filter struct {
	SrcIP   netip.Addr
	DstIP   netip.Addr
	Host    netip.Addr
	SrcPort uint16
	DstPort uint16
	Port    uint16
	Proto   uint8
}

Filter selects packets by flat AND'd criteria. Useful for structured APIs (query params, proto fields). Implements Matcher.

func (*Filter) IsEmpty

func (f *Filter) IsEmpty() bool

IsEmpty returns true if the filter has no criteria set.

func (*Filter) Match

func (f *Filter) Match(data []byte) bool

Match implements Matcher. All non-zero fields must match (AND).

type Matcher

type Matcher interface {
	Match(data []byte) bool
}

Matcher tests whether a raw packet should be captured.

func ParseFilter

func ParseFilter(expr string) (Matcher, error)

ParseFilter parses a BPF-like filter expression and returns a Matcher. Returns nil Matcher for an empty expression (match all).

Grammar (mirrors common tcpdump BPF syntax):

orExpr   = andExpr ("or" andExpr)*
andExpr  = unary ("and" unary)*
unary    = "not" unary | "(" orExpr ")" | term

term     = "host" IP | "src" target | "dst" target
         | "port" NUM | "net" PREFIX
         | "tcp" | "udp" | "icmp" | "icmp6"
         | "ip" | "ip6" | "proto" NUM
target   = "host" IP | "port" NUM | "net" PREFIX | IP

Examples:

host 10.0.0.1 and tcp port 443
not port 22
(host 10.0.0.1 or host 10.0.0.2) and tcp
ip6 and icmp6
net 10.0.0.0/24
src host 10.0.0.1 or dst port 80

type Options

type Options struct {
	// Output receives pcap-formatted data. Nil disables pcap output.
	Output io.Writer
	// TextOutput receives human-readable packet summaries. Nil disables text output.
	TextOutput io.Writer
	// Matcher selects which packets to capture. Nil captures all.
	// Use ParseFilter("host 10.0.0.1 and tcp") or &Filter{...}.
	Matcher Matcher
	// Verbose adds seq/ack, TTL, window, total length to text output.
	Verbose bool
	// ASCII dumps transport payload as printable ASCII after each packet line.
	ASCII bool
	// SnapLen is the maximum bytes captured per packet. 0 means 65535.
	SnapLen uint32
	// BufSize is the internal channel buffer size. 0 means 256.
	BufSize int
}

Options configures a capture session.

type PcapWriter

type PcapWriter struct {
	// contains filtered or unexported fields
}

PcapWriter writes packets in pcap format to an underlying writer. The global header is written lazily on the first WritePacket call so that the writer can be used with unbuffered io.Pipes without deadlocking. It is not safe for concurrent use; callers must serialize access.

func NewPcapWriter

func NewPcapWriter(w io.Writer, snapLen uint32) *PcapWriter

NewPcapWriter creates a pcap writer. The global header is deferred until the first WritePacket call.

func (*PcapWriter) WriteHeader

func (pw *PcapWriter) WriteHeader() error

WriteHeader writes the pcap global header. Safe to call multiple times.

func (*PcapWriter) WritePacket

func (pw *PcapWriter) WritePacket(ts time.Time, data []byte) error

WritePacket writes a single packet record, preceded by the global header on the first call.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session manages an active packet capture. Packets are offered via Offer, buffered in a channel, and written to configured sinks by a background goroutine. This keeps the hot path (FilteredDevice.Read/Write) non-blocking.

The caller must call Stop when done to flush remaining packets and release resources.

func NewSession

func NewSession(opts Options) (*Session, error)

NewSession creates and starts a capture session. At least one of Options.Output or Options.TextOutput must be non-nil.

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done returns a channel that is closed when the session's writer goroutine has fully exited and all buffered packets have been flushed.

func (*Session) Offer

func (s *Session) Offer(data []byte, outbound bool)

Offer submits a packet for capture. It returns immediately and never blocks the caller. If the internal buffer is full the packet is dropped silently.

outbound should be true for packets leaving the host (FilteredDevice.Read path) and false for packets arriving (FilteredDevice.Write path).

Offer satisfies the device.PacketCapture interface.

func (*Session) Stats

func (s *Session) Stats() Stats

Stats returns current capture counters.

func (*Session) Stop

func (s *Session) Stop()

Stop signals the session to stop accepting packets, drains any buffered packets to the sinks, and waits for the writer goroutine to exit. It is safe to call multiple times.

type Stats

type Stats struct {
	Packets int64
	Bytes   int64
	Dropped int64
}

Stats reports capture session counters.

type TextWriter

type TextWriter struct {
	// contains filtered or unexported fields
}

TextWriter writes human-readable one-line-per-packet summaries. It is not safe for concurrent use; callers must serialize access.

func NewTextWriter

func NewTextWriter(w io.Writer, verbose, ascii bool) *TextWriter

NewTextWriter creates a text formatter that writes to w.

func (*TextWriter) WritePacket

func (tw *TextWriter) WritePacket(ts time.Time, data []byte, dir Direction) error

WritePacket formats and writes a single packet line.

Jump to

Keyboard shortcuts

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