tpt-fathom

Rust

Memory-safe, declarative network protocol analyzer and packet inspection engine written in Rust — a spiritual successor to Wireshark. Protocols are defined as YAML schemas and compiled into safe parsers at runtime, eliminating the C-dissector buffer overflows that plague traditional packet analyzers.

0 stars0 forks0 watchers11 open issuesApache License 2.0
memory-safetynetwork-protocol-analyzernetwork-securitypacket-analyzerpacket-snifferpcapprotocol-parserrustsecurity-toolswireshark-alternative

Languages

Rust89.9%Python9.6%PowerShell0.5%
README

TPT Fathom

A memory-safe, highly extensible, and declarative network protocol analyzer and packet inspection engine — a spiritual successor to Wireshark.

Why

Wireshark's C dissectors parse untrusted, malformed network packets. A single buffer overflow in a C dissector can let a maliciously crafted packet execute arbitrary code on a security analyst's machine, and writing a new dissector in C takes days of boilerplate.

TPT Fathom's dissectors are described by a Declarative Schema (YAML), compiled into a safe parser at runtime by a Rust engine built on zerocopy. Adding a new protocol is a matter of writing (or AI-generating) a schema file, not writing unsafe C.

Status

Core v1 feature set is implemented — see todo.md for the full checklist. Shipped: schema format + validator, decode engine, fifteen protocol schemas (Ethernet, IPv4, IPv6, TCP, UDP, DNS, DHCP, DHCPv6, HTTP/2, SMB2, ARP, ICMP, HTTP/1.x, TLS, VLAN), CLI (file + live, display filter, BPF capture filter, packet limit, pcap export), egui GUI (search filter, export JSON, recent files, sortable columns, keyboard nav, error log), fuzz corpus with zero panics across 2158 malformed packets, and an AI schema-extraction tool.

Reachability from Ethernet captures: IPv4 → ICMP/TCP/UDP → DNS (UDP/53), DHCP (UDP/67-68), SMB2 (TCP/445), HTTP (TCP/80), TLS (TCP/443); IPv6 → TCP/UDP/DHCPv6 (UDP/546-547); ARP; VLAN (802.1Q + QinQ) → inner IPv4/IPv6/ARP are all wired end-to-end via protocol_ref port/protocol dispatch. HTTP/2 remains schema-select/test-only until a TLS payload dissector lands (TLS record layer is now present but HTTP/2-over-TLS needs handshake parsing). Release/publishing is deferred (Phase 15). Schema format reference: docs/SCHEMA.md.

Architecture

schemas/*.yaml ──► fathom-schema ──► fathom-engine ◄── raw frame bytes
  (YAML schemas)    (parse +          (zerocopy decode     (from fathom-capture
                     validate at       to a field tree;     or a pcap file)
                     load time)        panic-free)
                                          │
                    ┌─────────────────────┼─────────────────────┐
                    ▼                     ▼                     ▼
               fathom-cli            fathom-gui           serde export
            (tree / JSON out)   (list + hex + tree)      (JSON / YAML)
  • fathom-schema — parses YAML schemas and statically validates them (dangling length_refs, zero-length fields, overlapping bitfields, …) at load time. No decoding.
  • fathom-engine — interprets a validated schema against raw bytes into a DecodedField tree. Panic-free: every malformed input yields an EngineError.
  • fathom-capture — reads .pcap/.pcapng files (pure Rust, no external deps) and does live capture via Npcap (Windows) / libpcap, exposed as a tokio-friendly stream.
  • fathom-cli / fathom-gui — two frontends over the same decode path. Schemas are embedded at compile time with include_str!.

Protocol layering is data-driven: a schema's protocol_ref field dispatches to another schema by name (Ethernet → IPv4 → TCP/UDP → DNS), resolved by a SchemaRegistry at decode time. No Rust code changes are needed to add a protocol.

Building

pwsh tools/fetch-npcap-sdk.ps1   # Windows only, once: fetch Npcap SDK headers + import libs
cargo build --workspace

The Npcap SDK fetch is build-time only (fathom-capture links against it on Windows); the output lands in gitignored vendor/npcap-sdk/. Plain file-mode decoding works with nothing else installed. On Linux, install libpcap-dev instead (CI does this automatically).

Running the CLI

cargo run -p fathom-cli -- tests/fixtures/sample.pcap          # decoded field tree
cargo run -p fathom-cli -- tests/fixtures/sample.pcap --json   # one JSON array
cargo run -p fathom-cli -- tests/fixtures/sample.pcap --yaml   # one YAML document
cargo run -p fathom-cli -- --list-schemas                     # bundled schema names
cargo run -p fathom-cli -- --list-interfaces                   # live-capture interfaces
cargo run -p fathom-cli -- --interface eth0                    # live capture (Ctrl+C to stop)
cargo run -p fathom-cli -- --interface eth0 --json             # live: JSON Lines (one object/line)
cargo run -p fathom-cli -- tests/fixtures/sample.pcap \
    --filter 'protocol==TCP and dst_port==80'                 # display filter
cargo run -p fathom-cli -- --interface eth0 -f 'port 53'      # BPF capture filter
cargo run -p fathom-cli -- tests/fixtures/sample.pcap -c 10 -w out.pcap  # limit + export

File mode wraps all packets in a single JSON array; live mode streams JSON Lines, since a live capture has no fixed end. Decode errors on individual packets are reported per-packet (decode error: … / an "error" field in JSON) and do not fail the process. Display filters affect printed/JSON output only; -w still exports every packet read (respecting -c). Invalid checksums and decode errors are colored red only when the target stream is a terminal.

Live capture setup

Live capture needs the Npcap runtime installed separately from the SDK: https://npcap.com/#download (admin rights required). The SDK fetch above only provides headers/import libraries so the binary links. wpcap.dll/Packet.dll are delay-loaded, so file-mode decoding keeps working even with no Npcap install; requesting --interface/--list-interfaces without the runtime fails with a clean error message rather than a crash.

Running the GUI

cargo run -p fathom-gui

An egui desktop app with a packet list (protocol-chain summary), a hex dump pane, and a field-tree detail pane synced to selection (clicking a leaf highlights its bytes in the hex dump). Use Open (native file dialog) for .pcap/.pcapng, or the live-capture action to pick an interface and stream decoded frames into the list.

Development

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace

CI (.github/workflows/ci.yml) runs the same four steps (fmt, clippy, build, test) plus fixture-drift, fuzz-corpus, and cargo doc smoke checks on both Ubuntu and Windows. Integration tests load schemas from schemas/ via relative paths — run them from the workspace root.

Fixtures are raw frame bytes regenerated by Python (stdlib struct only, no scapy):

py -3 tests/fixtures/gen_fixtures.py       # regenerate .bin frames after schema changes
py -3 tests/fixtures/gen_pcap_fixture.py   # rebuild sample.pcap from those frames

Fuzz corpus + manual procedure: tools/fuzz/README.md.

Adding a protocol

Start from schemas/_template.yaml. See CONTRIBUTING.md for the full walkthrough — by hand, or drafted from an RFC via tools/ai-extractor (with a mandatory human-review step).

Tech stack

Rust, zerocopy, tokio, serde, egui, pcap (Npcap on Windows); Python (stdlib only) for fixture/fuzz generation and the AI schema-extraction tool.

License

Apache-2.0 — see LICENSE.