Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pktbite

A fast terminal packet console for live debugging.

Pktbite is a Rust TUI quick triage over SSH or a local terminal.

#     time        iface    proto   len   source                → destination             info
   42 14:02:11.203 eth0     TCP     74   10.0.0.5:54321        → 1.1.1.1:443             SYN TLS ClientHello SNI=example.com
   43 14:02:11.204 eth0     UDP     78   10.0.0.5:53122        → 8.8.8.8:53              DNS query www.example.com

Why this exists

Tool Strength Gap
tcpdump Everywhere, scriptable Hard to browse live
Wireshark Deepest analysis Heavy RAM/GUI; awkward on servers
termshark Wireshark-in-terminal Depends on tshark; heavier stack
pktbite Live TUI, fixed memory, simple filters Shallow decode by design

Use pktbite to answer “what is talking right now?”, then export a pcap when you need full dissection.


Features

Capture & reliability

  • Live capture on one or more interfaces (each on its own thread)
  • UI never blocks on capture; packets flow over a bounded channel
  • Ring buffer with fixed capacity (--buffer-size, default 10000) for the live view
  • When the ring is full, oldest packets are spilled to temporary pcap segments (not lost)
  • Spill budget: 10% of total disk capacity (filesystem of the current directory)
  • If the filesystem is ≥ 90% full, oldest spill segments are deleted first while new data keeps rolling
  • Windowed list rendering (only visible rows) so a full buffer stays responsive
  • On exit: choose backup (merged pcap + segment copy) or delete temp spill files
  • Channel-backpressure counter (drop_chan) when the UI cannot keep up
  • Clean quit restores the terminal and stops capture threads

Visibility (htop-style TUI)

  • Color-coded protocol rows (TCP / UDP / ICMP / ARP)
  • Header meters for buffer fill, drops, and flow count
  • Adaptive layout by terminal size:
    • Wide (≥140 cols): packet list | live detail preview
    • Tall: list above detail preview
    • Small: compact columns, list only
  • Column header bar and single-line function footer (htop-like)
  • L2–L4 summaries: Ethernet, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6, ARP
  • App-layer hints: DNS, TLS ClientHello SNI, HTTP lines
  • TCP hints: SYN / FIN / RST
  • Full detail, stream follow, and conversation views

Filters & I/O

  • Capture filter (BPF) at start — presets, custom, or --filter
  • Display filter while viewing (/) — simple host/port/proto/text terms
  • Offline pcap read (--read) — no root required
  • Continuous pcap write (--write) during live capture
  • Export currently filtered packets to a pcap file (e)

Requirements

Dependency Notes
Rust Edition 2021 toolchain (cargo, rustc)
libpcap Packet capture library + headers for build
Root / CAP_NET_RAW Required for live capture only

Install libpcap (examples)

# Debian / Ubuntu
sudo apt install libpcap-dev

# Fedora
sudo dnf install libpcap-devel

# Arch
sudo pacman -S libpcap

Build

git clone <repo-url> pktbite
cd pktbite
cargo build --release

Binary: ./target/release/pktbite

cargo test
cargo run -- --help

Usage

Quick start (interactive)

sudo ./target/release/pktbite

You will be prompted for:

  1. Network interface(s)
  2. A capture-filter preset (or custom BPF)

Common commands

# Single interface + BPF (skips preset menu)
sudo pktbite --iface eth0 --filter "port 53"

# Multiple interfaces
sudo pktbite --iface eth0 --iface lo
sudo pktbite --multi

# Larger ring buffer + continuous pcap write
sudo pktbite --iface eth0 --buffer-size 50000 --write /tmp/live.pcap

# All traffic, no filter prompt
sudo pktbite --iface eth0 --no-filter-prompt

# Offline analysis (no root)
pktbite --read ./capture.pcap

# List interfaces
sudo pktbite --list-devices

pktbite --help

CLI reference

Option Description
--iface <name> / -i Capture on interface (repeatable)
--multi Interactive multi-select of interfaces
--filter <BPF> Capture filter; skips the preset menu
--no-filter-prompt Start with no capture filter
--buffer-size <N> Ring buffer capacity in packets (default: 10000)
--read <file.pcap> / -r Open a pcap offline
--write <file.pcap> / -w Append every live packet to a pcap file
--list-devices Print interfaces and exit
-h / --help Show help

Keyboard shortcuts

Key Action
j / k or / Move one row
Page Down / Page Up Page through list, flows, or scroll detail/stream/help
Home Jump to first packet
End or f Follow live (auto-scroll to newest)
Enter Open packet detail
Esc Back / clear flow focus
p Pause UI (capture still runs)
/ Edit display filter
x Clear display filter
t Conversation / flow view
s Follow stream for selected packet
g Go to packet number
e Export filtered packets to pcap
c Clear ring buffer + flow table
? In-app help
q or Ctrl+C Quit

Page size follows the visible panel height (adapts when you resize the terminal).
In flows view: Enter focuses the list on that conversation.


Filters

There are two different filters. Confusing them is a common source of pain in other tools; the status bar labels them separately.

1. Capture filter (BPF)

Applied in the kernel / libpcap before packets enter the buffer. Fewer packets captured = less noise and memory pressure.

Set via:

  • Interactive presets at startup (DNS, HTTP, HTTPS, ARP, ICMP, SSH, custom, …)
  • --filter "tcp port 443"

Examples:

port 53
tcp port 80 or tcp port 443
host 10.0.0.5
arp
icmp or icmp6

Invalid BPF is reported when the capture opens (friendly error from libpcap).

2. Display filter (UI)

Applied after packets are already in the ring buffer. Use it to search or narrow the view without restarting capture.

Open with /. Whitespace-separated terms are AND-ed.

Term Meaning
tcp udp icmp arp icmpv6 Protocol
host <ip> Source or destination IP
src <ip> / dst <ip> Directional IP
port <n> Source or destination port
sport <n> / dport <n> Directional port
free text Substring match on info / DNS / SNI / iface

Examples:

tcp
host 10.0.0.5
port 443
tcp dport 443
src 192.168.1.1 dport 53
example.com

Status bar

Typical fields:

Field Meaning
Device name(s) Active interface(s) or file:… offline
LIVE / PAUSED / STOPPED / OFFLINE Capture state
Mode LIST, DETAIL, FLOWS, STREAM, …
pkts Total packets accepted into the buffer
view Count matching the current display filter / flow focus
buf used/cap (%) Ring buffer occupancy
drop_old Packets evicted because the buffer was full
drop_chan Packets dropped because the UI channel was full
follow Auto-scroll on/off
flows Number of tracked conversations
write Packets written by --write
cap:[…] Active BPF capture filter
disp:[…] Active display filter

Non-zero drop_* means you are under load or the buffer is too small — raise --buffer-size, tighten the capture filter, or pause less of the UI work.


Architecture (short)

  NIC(s) ──► capture thread(s) ──► bounded channel ──► TUI loop
                    │                    │                  │
                    │              drop if full        ring buffer
                    │                                  + flow table
                    └── optional --write pcap               │
                                                            ▼
                                              list / detail / flows / export
  • Capture uses a short pcap read timeout so threads can shut down cleanly.
  • Parsing is shallow and local (no tshark dependency).
  • Deep analysis path: export pcap → open in Wireshark.

Project layout

src/
  main.rs       CLI, live vs offline entry
  function.rs   Device selection, capture workers, auto-writer
  buffer.rs     Ring buffer + packet model
  parse.rs      L2–L4 + DNS / TLS SNI / HTTP
  filter.rs     Display filter + BPF presets
  flow.rs       Conversation aggregation
  pcap_io.rs    pcap read/write
  spill.rs      temp spill segments, disk budget, exit prompt
  tui_set.rs    htop-style TUI, adaptive layout, keys

Spill / temporary storage

While capturing, the in-memory ring holds the newest packets for the TUI. When it fills, older packets are written under:

./.pktbite-spill-<timestamp>-<pid>/spill-XXXXXX.pcap
Policy Behavior
Spill budget 10% of total capacity of the disk that contains .
Segment size Rotate ~every 8 MiB (granular deletes)
Disk pressure If used space ≥ 90%, delete oldest segments first
Auto-export Segments are valid pcaps; exit Backup also writes merged.pcap
Exit prompt Backup (copy + merge) or Delete temps

Header status shows spill: packet counts and on-disk size.


Design principles

  1. Filters should be forgiving — presets + simple display language; BPF for power users.
  2. Interop over completeness — pcap in/out instead of reimplementing Wireshark.
  3. Server-native — works over SSH, no GUI, predictable keys, clean terminal restore.

Limitations

  • Not a full protocol dissector (by design).
  • App-layer support is limited to high-signal summaries (DNS, TLS SNI, cleartext HTTP).
  • TLS payloads remain encrypted; there is no key-log decryption.
  • Capture filter changes require restarting the tool (no mid-session BPF reapply yet).
  • pcap format support targets common Ethernet/usec captures; exotic link types may not parse cleanly.
  • Windows support is not a current goal.

Troubleshooting

Problem What to try
“Root permissions are required…” Use sudo, or open a file with --read
No devices listed Check interface names; try ip link / --list-devices
BPF error on start Simplify the filter; test with tcpdump -i eth0 <filter>
Empty list but traffic exists Clear display filter (x); check capture filter is not too tight
High drop_chan / drop_old Increase --buffer-size; add a tighter BPF; avoid very busy unfiltered links
Terminal messed up after crash Run reset

License


Contributions and issue reports welcome once the project is published. This project is build by AI. but It’s quite useful, so I’m releasing it for others to use.

About

A fast terminal packet console for live debugging

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages