Tracker Component
Real-time eBPF-based system call tracing for ransomware detection
Overview
The NERRF Tracker is a high-performance, kernel-space eBPF instrumentation layer that captures fine-grained file system operations in real-time. It forms the sensory foundation of the NERRF framework, streaming structured syscall events via gRPC to AI models for attack detection and recovery planning.
Key Capabilities
- Real-time syscall capture (≥1k events/sec sustained on 4-core VM)
- Sub-microsecond latency from kernel to userspace via ring buffers
- Zero-copy event passing using BPF ring buffers (vs. perf events)
- Efficient gRPC streaming with per-client buffering
- Protobuf-structured data for seamless ML pipeline integration
- Minimal kernel overhead (<5% CPU for production workloads)
Architecture Stack
┌─────────────────────────────────────────────────────────────┐
│ gRPC Clients (AI/ML) │
└────────────────────┬────────────────────────────────────────┘
│ gRPC Streaming
▼
┌─────────────────────────────────────────────────────────────┐
│ Go Userspace (tracker binary, port 50051) │
│ ┌─────────────────────────────────────────────────────────┤
│ │ Ring Buffer Reader │ Event Parser │ gRPC Server │
│ └──────────┬──────────────────────────────────────────────┘
│ │ ring-buffer-read (mmap'd)
└─────────────┼────────────────────────────────────────────────┘
│
┌─────────────▼────────────────────────────────────────────────┐
│ Linux Kernel eBPF Programs (tracepoints.o) │
│ ┌─────────────────────────────────────────────────────────┤
│ │ sys_enter_openat │ sys_enter_write │ sys_enter_rename │
│ │ (tracepoints.c) │ (tracepoints.c) │ (tracepoints.c) │
│ └─────────────────────────────────────────────────────────┘
└────────────────────────────────────────────────────────────┘
│
┌─────────────▼────────────────────────────────────────────────┐
│ Linux VFS & Syscall Layer (kernel 4.18+) │
└────────────────────────────────────────────────────────────┘Event Flow
- Syscall Tracepoint → Kernel triggers eBPF program
- Event Serialization → eBPF reserves space in ring buffer
- Atomic Submission → eBPF submits event without copying
- Userspace Read → Go program reads mmap'd ring buffer
- Event Parsing → Binary data → Go struct → Protobuf
- gRPC Broadcast → Event sent to all connected clients
Supported Syscalls
| Syscall | ID | Purpose | Captured Fields |
|---|---|---|---|
openat() | 1 | File open/create operations | path, flags, mode |
write() | 2 | File write operations (LockBit key) | fd, bytes, offset |
rename() | 3 | File rename/move (LockBit indicator) | old path, new path |
Future Extensions:
unlink()– File deletion patternschmod()– Permission changessetxattr()– Metadata modifications
Technology Choices
Why eBPF?
| Aspect | eBPF | Alternatives |
|---|---|---|
| Kernel-space | Programs run in kernel | strace, auditd (slower) |
| Zero-copy | Ring buffers (mmap'd) | perf events (copying) |
| Safety | Kernel verifier | Kernel modules (unsafe) |
| Performance | JIT-compiled, fast path | userspace hooks (slow) |
| Compatibility | Kernel 4.18+, no recompile | systemtap (setup-heavy) |
Ring Buffer vs. Perf Events
Ring Buffer (tracepoints.c): Perf Events (legacy):
├─ mmap'd shared memory ├─ per-CPU buffers
├─ atomic reservation (no locks) ├─ spinlock protection
├─ single-reader model ├─ complex consumer sync
├─ minimal CPU overhead ├─ higher CPU usage
└─ efficient GC (auto-wrap) └─ manual buffer managementWhy gRPC + Protobuf?
- Language-agnostic streaming to Python (AI), Rust (sandbox), etc.
- Structured schema prevents field mismatches between components
- Built-in compression for large trace uploads
- Reflection API for debugging with
grpcurl
Core Components
1. eBPF Programs (tracepoints.c)
Located at tracker/bpf/tracepoints.c (81 lines of kernel code):
Key Features:
- GPL License required for BPF helpers
- Ring buffer map (256 KB capacity, auto-wrap)
- Inline common fields via
fill_common()macro - String sanitization for paths (null-terminated, UTF-8)
- Zero-allocation event handling (pre-reserved slots)
Tracepoint Hook:
SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat(struct trace_event_raw_sys_enter *ctx)This hooks the sys_enter_openat tracepoint provided by the kernel, fired immediately when openat() syscall is invoked.
2. Go Userspace (cmd/tracker/main.go)
Located at tracker/cmd/tracker/main.go (331 lines):
Startup Sequence:
- Set
RLIMIT_MEMLOCK(unbounded) for eBPF memory - Load
tracepoints.ovialibbpfGo wrapper - Attach tracepoints to kernel hooks
- Create ring buffer reader (mmap'd interface)
- Launch gRPC server on
:50051 - Begin event broadcast loop
gRPC Server:
- Implements
TrackerServerinterface - Streams
EventBatchto clients - Per-client buffered channels (100-event buffer)
- Graceful client disconnect handling
Event Processing:
// Binary → Go struct
binary.Read(buffer, binary.LittleEndian, &event)
// Monotonic → Wall-clock timestamp
eventTime := bootTime.Add(time.Duration(e.Ts) * time.Nanosecond)
// Go struct → Protobuf
pbEvent := &pb.Event{Ts, Pid, Tid, Comm, Syscall, Path, ...}3. Protocol Buffers (proto/trace.proto)
Defines the gRPC contract:
message Event {
google.protobuf.Timestamp ts = 1; // Wall-clock time
uint32 pid = 2; // Process ID
uint32 tid = 3; // Thread ID
string comm = 4; // Executable name
string syscall = 5; // "openat" | "write" | "rename"
string path = 6; // File path
string new_path = 7; // Destination (rename only)
int64 ret_val = 8; // Return value (fd or error)
uint64 bytes = 9; // Bytes written
OpenFlags flags = 10; // File open flags
}
message EventBatch {
repeated Event events = 1; // Batch of 1+ events
}
service Tracker {
rpc StreamEvents(Empty) returns (stream EventBatch);
}Performance Characteristics
Benchmark Results (M1 Milestone)
Environment: 4-core cloud VM, 8 GB RAM, Ubuntu 22.04
| Metric | Result | Target | Status |
|---|---|---|---|
| Peak throughput | 1,250 evt/s | ≥1k evt/s | |
| P99 latency | 240 µs | <1 ms | |
| CPU overhead | 3.8% | <5% | |
| Memory footprint | 12 MB | <50 MB | |
| Sustained (10 min) | 1,100 evt/s | ≥1k evt/s |
Scalability Notes
- Ring buffer capacity (256 KB) handles ~50 ms of events at 1k evt/sec
- Userspace loop processes events in batches (adaptive)
- Per-client buffering (100 events) prevents gRPC backpressure
- Slow client handling via non-blocking channel send (drop overflow)
Deployment Options
1. Local Development (Host eBPF)
# Build tracker binary
cd tracker
make tracker
# Run with root
sudo ./bin/tracker
# Query events (in another terminal)
grpcurl -plaintext -d '{}' localhost:50051 nerrf.trace.Tracker/StreamEventsRequirements: Linux kernel 4.18+, root/CAP_SYS_ADMIN, libbpf
2. Container (Privileged)
# Build image
docker build -f tracker/Dockerfile.minimal -t nerrf/tracker:m1 .
# Run with host network & privileged (required for eBPF)
docker run --privileged --network host nerrf/tracker:m13. Kubernetes (DaemonSet)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: tracker
spec:
template:
spec:
hostNetwork: true
privileged: true
containers:
- name: tracker
image: nerrf/tracker:m1
env:
- name: TRACKER_LISTEN_ADDR
value: "0.0.0.0:50051" # Listen on all interfacesConsiderations:
- One pod per node (DaemonSet)
- Host network & privileged mode (eBPF requirement)
- Service discovery for AI components
Development Roadmap
M2 & Beyond
- kprobe-based FD resolution: Current
write()syscall lacks path info; kprobes can resolve fd → inode → path - Context aggregation: Thread-local storage for multi-syscall events (e.g.,
open → write → close) - Histograms & metrics: Prometheus integration for latency/throughput dashboards
- Filtering: User-space filter programs to reduce event volume pre-gRPC
- Compression: gRPC message compression for bandwidth optimization
Troubleshooting
"BPF object not found"
- Ensure
makecompleted:ls tracker/bpf/tracepoints.o - Check executable path detection logic
"Permission denied (eBPF attach)"
- Must run as root:
sudo ./bin/tracker - Or grant CAP_SYS_ADMIN:
setcap cap_sys_admin=ep ./bin/tracker
"ringbuf read error: resource temporarily unavailable"
- Normal when no events occur; logs retry automatically
gRPC connection refused
- Check listener:
ss -tlnp | grep 50051 - Verify address env var:
echo $TRACKER_LISTEN_ADDR
Next Steps
- Architecture Deep Dive – System design & threat model
- Getting Started – Quick setup guide
- Threat Model – LockBit scenario & detection logic
- Developer Guide – Contributing to Tracker