eBPF network connection tracker with live TUI display
netprobe uses Linux eBPF (via BCC) to hook into the kernel and capture every TCP and UDP connection the moment it happens — with zero packet capture overhead.
netprobe — eBPF network tracker [q]uit [c]lear [f]reeze [j]son
TIME PID COMM PROTO SOURCE DESTINATION
14:22:01.342 8541 curl TCP-CONNECT 10.0.0.5:54312 93.184.216.34:443
14:22:01.899 12003 chrome TCP-CONNECT 10.0.0.5:54313 142.250.80.46:443
14:22:02.001 1337 nginx TCP-ACCEPT 0.0.0.0:80 10.0.0.1:49210
14:22:02.100 9922 python3 UDP 10.0.0.5:52100 8.8.8.8:53
- eBPF hooks on
tcp_v4_connect,inet_csk_accept,udp_sendmsg - Per-event details: timestamp, PID, process name, src IP:port, dst IP:port, protocol
- Live curses TUI — scrollable, colour-coded by protocol
- JSON / NDJSON mode — pipe to
jq,grep, files, etc. - Flexible filters — PID, process name (regex), port, src/dst IP, protocol
- Kernel-side pre-filtering via BPF maps (fast-path — no unnecessary copies)
- Unit tests with mocked BCC (no root required for
pytest)
| Component | Version |
|---|---|
| Linux kernel | ≥ 4.9 (eBPF + kprobes) |
| Python | ≥ 3.8 |
| BCC | python3-bpfcc or pip bcc |
# Ubuntu / Debian
sudo apt install python3-bpfcc bpfcc-tools linux-headers-$(uname -r)
# Fedora / RHEL
sudo dnf install bcc-tools python3-bcc kernel-develRequires root (or
CAP_BPF+CAP_NET_ADMIN).
sudo python3 netprobe.pysudo python3 netprobe.py --json | jq 'select(.dport == 443)'# Only events from PID 1234
sudo python3 netprobe.py --pid 1234
# Only events from processes matching "curl" or "wget"
sudo python3 netprobe.py --comm "curl|wget"
# Only port 53 (DNS)
sudo python3 netprobe.py --port 53
# Only connections to 8.8.8.8
sudo python3 netprobe.py --dst-ip 8.8.8.8
# Only TCP
sudo python3 netprobe.py --protocol tcp
# Combine filters
sudo python3 netprobe.py --comm nginx --port 80 --json| Key | Action |
|---|---|
q |
Quit |
c |
Clear event log |
f |
Toggle freeze (pause display) |
j |
JSON dump of current log to stdout |
↑ / ↓ |
Scroll event history |
netprobe/
├── netprobe.bpf.c # eBPF C program (compiled by BCC at runtime)
├── netprobe.py # Main entry point, BPF loader, event decoder
├── display.py # curses TUI + plain/JSON stdout display
├── filters.py # Filter config + matching logic
├── tests/
│ ├── mock_bcc.py # BCC mock (no root needed)
│ ├── test_filters.py # Filter unit tests
│ ├── test_netprobe.py # Event decode + NetProbe integration tests
│ └── test_display.py # Display buffer & output tests
└── README.md
No root required — BCC is fully mocked.
pip install pytest
pytest tests/ -vKernel space User space
─────────────────────────────────────────────────────────
tcp_v4_connect() ─kprobe──────────▶ netprobe.py
inet_csk_accept() ─kretprobe───────▶ │ decode event
udp_sendmsg() ─kprobe──────────▶ │ apply filters
│ → curses TUI
perf ring buffer │ → JSON stdout
(zero-copy) │ → file / pipe
- BCC compiles
netprobe.bpf.cand loads it into the kernel at startup. - kprobes fire on every
tcp_v4_connect/inet_csk_accept/udp_sendmsgcall. - The eBPF program fills a
struct event_tand pushes it viaperf_submit. - Python reads from the perf ring buffer, decodes events, and applies any Python-side filters.
- Events are forwarded to the display (TUI or stdout).
MIT