Building a Small Rust eBPF EDR 7: Running, Packaging, Health, and Roadmap
목차
마지막 글에서는 rand-guard를 어떻게 빌드하고 실행하고 패키징하고 검증하는지 정리한다. eBPF EDR은 코드만 작성해서 끝나는 프로젝트가 아니다. 실제로 build artifact가 만들어져야 하고, root 권한으로 load되어야 하며, output이 검증 가능해야 한다.
rand-guard는 이 반복 작업을 xtask로 묶어 둔다.
xtask workflow
저장소 root에서 다음 명령을 사용할 수 있다.
cargo run -p xtask -- ci-format
cargo run -p xtask -- check
cargo run -p xtask -- clippy
cargo run -p xtask -- test
cargo run -p xtask -- build
Cargo alias도 있다.
cargo xf
cargo xc
cargo xl
cargo xt
cargo xb
eBPF program build에는 nightly Rust와 rust-src, bpf-linker가 필요하다. userspace crate는 stable Rust로 빌드된다. 이 분리는 eBPF target의 특수성을 반영한다.
실행은 다음과 같이 할 수 있다.
cargo run -p xtask -- run
이 명령은 eBPF object를 load하므로 root 또는 적절한 capability가 필요하다. 일반적인 Linux 환경에서는 sudo가 필요할 수 있다.
package workflow
release artifact는 package command로 만들 수 있다.
cargo run -p xtask -- package
package에는 다음 항목이 포함된다.
- userspace binary
- eBPF object
- default config
- sample rules
- systemd unit
- installer script
quickstart 문서 기준으로 설치 경로는 다음과 같다.
/usr/local/bin/rand-guard
/usr/local/lib/rand-guard/edr-ebpf
/etc/rand-guard/config.toml
/etc/rand-guard/rules.d/sample-rules.toml
/etc/systemd/system/rand-guard.service
systemd unit은 EDR_CONFIG와 EDR_EBPF_OBJECT environment variable을 설정한다. 이 구조 덕분에 runtime binary와 eBPF object 위치를 명확히 분리할 수 있다.
quick verification
agent를 실행한 뒤 process event는 간단히 만들 수 있다.
/bin/true
file event는 demo service file을 만들고 지우는 방식으로 확인할 수 있다.
sudo sh -c 'printf "# rand-guard quickstart\n" > /etc/rand-guard-quickstart.service'
sudo rm -f /etc/rand-guard-quickstart.service
network telemetry는 기본 비활성화이므로 config에서 켠 뒤 확인해야 한다.
[events]
network = true
[network]
enabled = true
hooks = ["connect", "bind", "listen"]
collect_dns = false
collect_payload = false
이후 loopback listener demo를 실행할 수 있다.
nc -l 127.0.0.1 4444
printf 'demo\n' | nc 127.0.0.1 4444health records
runtime은 주기적으로 health record를 출력한다. health record는 detection이 아니라 runtime 상태를 이해하기 위한 telemetry다.
대표 field는 다음과 같다.
- raw events read
- normalized events output
- alerts output
- userspace filtered count
- userspace rate limited count
- invalid schema count
- unsupported kind count
- output failure count
- process table size
- pending exec source size
- eviction count
- uptime
- RSS
이 정보는 성능 문제나 event loss를 볼 때 중요하다. 예를 들어 raw event는 많이 들어오는데 normalized output이 적다면 filtering이나 rate limiting이 영향을 주고 있을 수 있다. process table eviction이 많다면 cache limit을 조정하거나 workload를 다시 봐야 한다.
throughput workflow
rand-guard에는 local throughput workflow도 있다.
cargo run -p xtask -- throughput
이 benchmark는 controlled file-write workload를 만들고, health record를 파싱해서 .local/throughput/ 아래에 summary를 남긴다.
중요한 점은 benchmark 숫자를 일반적인 성능 보장처럼 쓰면 안 된다는 것이다. kernel version, CPU, filesystem, background load, enabled hook, build mode에 따라 결과가 달라진다. 이 workflow는 같은 host에서 코드 변경 전후를 비교하기 위한 local comparison data다.
threat model
rand-guard는 root attacker를 막는 agent가 아니다. root 권한을 가진 공격자는 service를 중지하거나 config를 바꾸거나 binary를 교체하거나 output을 조작할 수 있다.
현재 threat model은 다음 범위에 더 가깝다.
- local user-space command가 telemetry를 발생시킨다.
- eBPF program은 verifier-friendly하게 작게 유지한다.
- output record는 민감한 host telemetry로 취급한다.
- detection은 selected behavior를 모델링하는 investigation signal이다.
이런 제한을 문서에 명시하는 것은 중요하다. 보안 프로젝트에서 하지 않는 것을 분명히 쓰는 것은 하는 것을 쓰는 것만큼 중요하다.
roadmap
현재 MVP는 다음을 구현했다.
- process lifecycle collection
- file collection and filtering
- optional network syscall telemetry
- shared event ABI
- ring buffer delivery
- userspace normalization and enrichment
- built-in persistence and suspicious port detection
- MVP
[[rules]] - stable alert records
- packaging and smoke workflows
near-term work는 rule evaluation test, alert output stability, demo scenario 개선, benchmark 문서화, config validation 개선, false positive 문서화에 가깝다.
longer-term research로는 reverse shell, web shell execution, credential access, systemd persistence, drop-and-execute 같은 scenario-based detection이 있다. 하지만 이것들은 현재 구현된 기능으로 과장해서 쓰면 안 된다. 연구 방향이지 완성된 coverage가 아니다.
시리즈 정리
이 시리즈는 작은 Rust eBPF EDR을 end-to-end로 구성하는 과정을 다뤘다.
- 1편에서는 전체 architecture를 잡았다.
- 2편에서는 eBPF와 userspace 사이의 ABI를 다뤘다.
- 3편에서는 process lifecycle과 process table enrichment를 봤다.
- 4편에서는 file telemetry와 persistence-sensitive detection을 봤다.
- 5편에서는 opt-in network telemetry를 봤다.
- 6편에서는 MVP rule engine과 alert record를 다뤘다.
- 7편에서는 실행, 패키징, health, benchmark, roadmap을 정리했다.
rand-guard의 핵심은 기능을 많이 붙이는 것이 아니라, 작고 설명 가능한 EDR pipeline을 실제 코드로 완성하는 것이다. eBPF program은 커널에서 안전하게 수집하고, userspace는 그 event를 이해 가능한 telemetry와 alert로 바꾼다. 이 경계를 선명하게 유지하는 것이 프로젝트의 가장 중요한 설계 원칙이다.