rand-guard
Building a Small EDR Pipeline with Rust and eBPF
rand-guard is a small eBPF EDR project built with Rust and Aya. The goal is not to imitate a commercial EDR product, but to implement the full pipeline myself: collect process, file, and network telemetry from a Linux endpoint with eBPF, normalize and enrich it in userspace, evaluate detections, and write structured output.
This project prioritizes a small, explainable end-to-end flow over a broad feature list. The kernel side only collects a limited set of events through tracepoints, while policy decisions and output handling live in userspace. Events cross a fixed-layout ABI in crates/common, are delivered through the EVENTS ring buffer, and are emitted by the userspace runtime as NDJSON.
The current implementation covers process lifecycle events, file events, opt-in network syscall telemetry, built-in detections, an MVP rule engine, alert records, packaging, and demo workflows. DNS collection, payload collection, accept/accept4, socket lifecycle correlation, and multi-event time-window rule correlation are not implemented yet.
The project code is available at https://github.com/random6-xyz/rand-guard.
Posts
-
Building a Small Rust eBPF EDR 1: MVP Architecture
The first post explains the overall structure of
rand-guard. It follows an event from a Linux tracepoint through an eBPF program, theEVENTSring buffer, userspace normalization, detection/rule evaluation, and NDJSON output. -
Building a Small Rust eBPF EDR 2: Stable Event ABI
This post covers the ABI design used to pass events safely between eBPF and userspace. It focuses on
#[repr(C)]structs incrates/common,EventHeader, schema versioning, event kinds, fixed-size string fields, and truncation flags. -
Building a Small Rust eBPF EDR 3: Process Lifecycle Telemetry
This post explains how
execve,execveat,fork, andexitevents are collected and enriched through a userspace process table. It covers whysched_process_execand syscall tracepoints are used together, plusppid,comm,exe_pathenrichment and cache eviction limits. -
Building a Small Rust eBPF EDR 4: File Telemetry and Persistence Detection
This post describes file event collection for open, write, rename, and unlink syscall families, along with persistence-sensitive path detection. It explains
watch_paths,watch_patterns,exclude_paths, systemd service and cron path detections, source event annotations, and separate alert records. -
Building a Small Rust eBPF EDR 5: Optional Network Telemetry
This post explains why network telemetry is opt-in by default. It covers the currently supported
connect,bind, andlistentracepoints, IPv4/IPv6 sockaddr parsing, suspicious port detection, process name filtering, and why DNS, payload, and socket correlation are intentionally not implemented yet. -
Building a Small Rust eBPF EDR 6: MVP Rule Engine and Alert Records
This post explains the current userspace rule engine. It covers single-event matchers for process, file, and network events, built-in rules and config
[[rules]], stableevent_type = "alert"records, and why regex and multi-event correlation are not part of the MVP. -
Building a Small Rust eBPF EDR 7: Running, Packaging, Health, and Roadmap
This post summarizes how to build, run, and package the project. It covers
xtask, systemd packaging, quickstart demos, health records, local throughput benchmarks, the threat model, and the roadmap.
Current Scope
- Process lifecycle collection:
execve,execveat,fork,exit. - File telemetry: open, write, rename, unlink syscall families.
- Optional network telemetry:
connect,bind,listen. - Shared fixed-layout event ABI in
crates/common. - Ring-buffer delivery through the
EVENTSmap. - Userspace normalization and process context enrichment.
- Built-in persistence-sensitive file detections.
- Built-in suspicious network port detections.
- MVP single-event
[[rules]]evaluation. - Stable
event_type = "alert"records. - Stdout newline-delimited JSON output.
xtaskworkflows for build, test, package, smoke, and throughput.
Current Limits
- This project does not aim for production EDR parity.
- The rule engine is a single-event matcher MVP; it has no expression DSL, regex, time windows, or multi-event correlation.
- Network collection is limited to
connect,bind, andlistensyscall tracepoints. - DNS collection and payload collection are not implemented.
accept/accept4telemetry and full socket lifecycle correlation are not implemented.- Runtime output is currently centered on stdout NDJSON.
- Loading eBPF programs requires root or suitable Linux capabilities.
Code
crates/common: event ABI shared by eBPF and userspace.crates/ebpf:no_std,no_mainAya eBPF tracepoint programs.crates/user: loader, config, ring-buffer consumer, normalization, enrichment, detections, rule engine, and output.xtask: format, check, clippy, test, build, package, run, ci-smoke, and throughput workflows.docs: architecture, quickstart, threat model, roadmap, benchmark, and demo scenarios.