High-throughput network stream inspection for live traffic and PCAPs.
WirePrism turns captured packets into bounded, queryable stream state while traffic is still arriving. It combines capture, flow tracking, transport reassembly, protocol parsing, content transforms, pattern matching, a local API, and a dense Web UI in one Rust process.
The engine is built for workloads where correctness and predictable resource usage matter: large PCAPs, long-running live capture, protocol research, network forensics, and CTF traffic analysis.
Important
WirePrism is under active development. The capture, reassembly, parser, API, and UI paths are working, but APIs and output schemas may change before 1.0.
- Live and offline input through libpcap, with BPF filters, source drop counters, configurable capture buffers, and batched PCAP replay.
- Stateful flow processing with canonical flow keys, TCP sequence tracking, bounded out-of-order reassembly, QUIC connection routing, and flow-sharded workers.
- Protocol-aware streams with structured message indexes for HTTP, DNS, TLS, QUIC, WebSocket, and a growing set of text and binary services.
- Content inspection with text, regex, and binary patterns; logical match offsets; highlighted slices; and text, hex, raw, or base64 copy formats.
- On-demand transforms for URL encoding, gzip, HTTP chunked bodies, gzip HTTP bodies, and compressed WebSocket messages.
- Bounded by design through explicit flow, parser, content, match, queue, and API retention limits instead of unbounded shared state.
- Observable under load with queue pressure, routed bytes, fallback reasons, hot-flow telemetry, packet/byte skew, parser misses, and per-shard diagnostics.
- Built-in local UI and API with live deltas, service filters, favorites, hidden streams, match navigation, and viewport-sized content reads.
WirePrism currently targets macOS and Linux. You need a current stable Rust toolchain, libpcap development files, Clang, and CMake.
On macOS:
xcode-select --install
brew install cmakeOn Ubuntu or Debian:
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libpcap-dev clang cmake libclang-devBuild the optimized binaries:
git clone https://github.com/eogod/wireprism.git
cd wireprism
cargo build --releaseThis produces:
target/release/wireprism- capture, analysis, API, and UI runtime.target/release/wireprism-load- repeatable load and regression harness.
./target/release/wireprism \
--pcap capture.pcap \
--output findings.jsonl \
--api-listen 127.0.0.1:33111Open http://127.0.0.1:33111 while the process is
running. After the PCAP finishes, the API remains available until Ctrl-C so
the retained streams can still be inspected.
List interfaces first:
./target/release/wireprism --list-interfacesCapture from an interface and open the live UI:
sudo ./target/release/wireprism \
--iface en0 \
--capture-filter 'tcp or udp' \
--api-listen 127.0.0.1:33111 \
--workers 0Live capture requires permission to open the selected interface. Build as your normal user and elevate only the finished binary when elevated capture access is required.
--workers 0 means the runtime uses available parallelism. The main runtime
accepts an integer worker count; the adaptive worker plan is provided by
wireprism-load for benchmarking and capacity selection.
Patterns are repeatable and can be combined in one run:
./target/release/wireprism \
--pcap capture.pcap \
--pattern 'token=' \
--regex 'flag\{[^}]+\}' \
--binary-pattern 'de ad be ef' \
--api-listen 127.0.0.1:33111--patternperforms byte-exact substring matching.--regexmatches byte-oriented regular expressions across chunk boundaries.--binary-patternaccepts hexadecimal bytes with optional spaces, colons, underscores, dashes, or a0xprefix.
Matches retain stream direction and logical offsets, allowing the API and UI to request only the content window needed for highlighting.
Use an NSS/SSLKEYLOGFILE-compatible key log for modern TLS and QUIC captures:
./target/release/wireprism \
--pcap capture.pcap \
--tls-keylog /path/to/sslkeys.log \
--api-listen 127.0.0.1:33111Static-RSA TLS 1.0-1.2 captures can use one or more PEM private keys:
./target/release/wireprism \
--pcap capture.pcap \
--tls-rsa-key /path/to/server-key.pemStatic RSA keys cannot decrypt ECDHE sessions. Key logs and private keys contain sensitive material and should never be committed to the repository.
Analysis mode emits bounded metadata and parser events without copying all retained payload content into the output stream:
./target/release/wireprism --pcap capture.pcap --output findings.jsonlPacket dump mode emits packet-level dump events:
./target/release/wireprism \
--pcap capture.pcap \
--mode dump \
--output packets.jsonl| Layer | Current coverage |
|---|---|
| Link and network | Ethernet, Linux SLL, BSD loopback, raw IP, IPv4, and IPv6 |
| Transport | TCP, UDP, ICMP decode, TCP reassembly, and QUIC state |
| Structured messages | HTTP/1-3, DNS over UDP/TCP, TLS, QUIC, and WebSocket |
| Text services | SSH, FTP, SMTP, POP3, IMAP, Redis, and Memcached |
| Binary services | MQTT, AMQP, Postgres, MySQL, MongoDB, LDAP, SMB2, and RDP |
| Datagram metadata | DHCP, NTP, SNMP, SSDP, NetBIOS name service, and ICMPv4 |
Coverage is protocol-specific. A protocol listed under text, binary, or datagram services may currently provide detection, framing, and selected message metadata rather than a complete semantic decoder for every operation.
flowchart LR
A["PCAP file or live interface"] --> B["Batched ingest"]
B --> C["Route-only dispatcher"]
C --> D["Stateful flow placement"]
subgraph S["Flow shard"]
E["Decode once"] --> F["Flow and transport state"]
F --> G["TCP / QUIC reassembly"]
G --> H["Detection and parsers"]
H --> I["Content, patterns, transforms"]
end
D --> S
S --> J["Coordinator"]
J --> K["JSONL sinks"]
J --> L["Live API"]
L --> M["Web UI"]
The hot path follows a few rules:
- Packets are decoded once inside their worker shard.
- Canonical flows retain an owner so reverse traffic reaches the same state.
- Heavy TCP stream work can use bounded offload lanes without moving flow ownership; eligible UDP elephant flows can be striped across workers.
- Worker input, output, and offload queues apply explicit backpressure.
- Stream content, parser state, match indexes, and UI deltas have independent memory caps and eviction policies.
- The coordinator owns query-facing view state, keeping slow UI clients away from worker-local mutable state.
The defaults are conservative enough for local analysis. Large or long-running captures should set memory and queue budgets deliberately.
| Option | Default | Purpose |
|---|---|---|
--workers |
0 |
Flow-shard workers; 0 uses available parallelism |
--batch-size |
4096 |
Packets read and dispatched per ingest batch |
--worker-queue-depth |
4096 |
Bounded input queue per worker |
--event-queue-depth |
4096 |
Bounded worker-to-coordinator event queue |
--max-flows |
1000000 |
Maximum retained flow states |
--max-stream-content-bytes |
268435456 |
Global retained content budget |
--max-stream-content-bytes-per-stream |
8388608 |
Per-stream content cap |
--health-interval-ms |
1000 |
Telemetry interval; 0 disables it |
Example with explicit capacity limits:
./target/release/wireprism \
--pcap capture.pcap \
--workers 8 \
--batch-size 8192 \
--worker-queue-depth 8192 \
--event-queue-depth 8192 \
--max-flows 2000000 \
--max-stream-content-bytes 536870912Queue depth is not a substitute for throughput. Use the health endpoint and load harness to distinguish sustained worker saturation from short bursts, fallback routing, or one legitimately dominant flow.
The API is intended for local use and has no authentication. Keep it bound to a loopback address unless it is placed behind an authenticated proxy.
| Endpoint | Purpose |
|---|---|
GET /api/health |
Pipeline, parser, queue, drop, and shard telemetry |
GET /api/service-profiles |
Built-in and custom service profiles |
GET /api/streams |
Cursor-based stream inventory and filters |
GET /api/streams/{id} |
Stream metadata and current view state |
GET /api/streams/{id}/messages |
Parsed protocol message index |
GET /api/streams/{id}/matches |
Retained pattern match ranges |
GET /api/streams/{id}/content |
Bounded text, hex, or raw content slice |
GET /api/live/deltas |
Long-polling stream and telemetry updates |
PATCH /api/streams/{id}/state |
Favorite or manually hide a stream |
POST /api/view/hide-rules |
Add an in-memory hide rule |
Examples:
curl http://127.0.0.1:33111/api/health
curl 'http://127.0.0.1:33111/api/streams?profile=http&limit=50'
curl 'http://127.0.0.1:33111/api/live/deltas?cursor=0&limit=1024&wait_ms=1000'
curl 'http://127.0.0.1:33111/api/streams/123/messages?protocol=http1&limit=128'
curl 'http://127.0.0.1:33111/api/streams/123/content?direction=a_to_b&start=0&len=65536&mode=text&transform=auto'Stream IDs are also returned as stream_id_hex so browser clients can preserve
the full 64-bit value without JavaScript number precision loss.
Profiles group streams by protocol, service, port, content kind, or pattern ID. They can also define default views, transform chains, and hide-rule templates.
{
"include_builtins": true,
"profiles": [
{
"id": "admin_web",
"name": "Admin web",
"priority": 150,
"protocol": "tcp",
"ports": [8080, 18080],
"services": ["http"],
"default_mode": "text",
"default_transform": "auto",
"default_transforms": ["http_chunked", "http_gzip", "url_decode"],
"hide_rules": [{ "kind": "port", "value": 18080 }]
}
]
}Load the file with:
./target/release/wireprism \
--pcap capture.pcap \
--service-profile-file profiles.json \
--api-listen 127.0.0.1:33111wireprism-load runs reproducible synthetic or PCAP-backed suites across worker
counts and reports packets/sec, bytes/sec, event throughput, shard skew,
fallback ratios, flow distribution, and planner decisions.
./target/release/wireprism-load \
--fixture http-requests \
--flows 100000 \
--workers 1,4,adaptive,0 \
--runs 3 \
--warmups 1 \
--output perf-http.jsonAvailable synthetic fixtures:
http-requestsout-of-order-httphttp-keep-alivemixed-servicesudp-elephanttcp-elephant
Replay a real capture:
./target/release/wireprism-load \
--pcap capture.pcap \
--workers 1,4,adaptive,0 \
--runs 3 \
--warmups 1 \
--output perf-pcap.jsonUse a saved JSON report as a regression baseline:
./target/release/wireprism-load \
--fixture http-requests \
--flows 100000 \
--workers adaptive \
--runs 5 \
--warmups 2 \
--baseline baselines/http.json \
--max-regression-pct 10 \
--fail-on-regression \
--output perf-current.jsonWarmups are excluded from summaries unless --include-warmups is set. A small
fixture can make additional workers slower; compare packet, byte, and flow
budgets per worker before treating worker-count results as a scaling regression.
Run the same core checks used by CI:
cargo fmt --check
cargo test --all-targets --all-features
cargo clippy --all-targets --all-features -- -D warnings
cargo bench --bench packet_decode --no-runRun a short end-to-end load smoke test:
cargo run --release --bin wireprism-load -- \
--fixture http-requests \
--flows 10000 \
--workers 1,adaptive \
--runs 1 \
--warmups 0Parser changes should be validated against the built-in protocol corpus and at least one real capture. Performance-sensitive changes should include before and after reports produced on the same machine with the same build profile.
- Broaden malformed-input, fragmentation, and fuzz coverage across every parser.
- Persist capture sessions, favorites, hide rules, and UI preferences.
- Expand message-first navigation and protocol-specific views in the Web UI.
- Add production-oriented storage and export sinks beyond JSONL.
- Export long-running metrics in a machine-readable format.
- Continue parser depth and encrypted-session coverage without weakening memory bounds or flow correctness.
Capture files, payloads, key logs, private keys, and JSONL output may contain credentials or other sensitive data. Keep them outside version control. Only capture or decrypt traffic you are authorized to inspect.
WirePrism is licensed under the MIT License.