Add eBPF SYN-flood candidate detection#8
Merged
Conversation
Adds a `tcp_v4_rcv` kprobe that inspects each inbound IPv4 TCP segment,
filters for SYN-only (SYN=1, ACK=0), reads the source IPv4 from the
embedded IP header, and increments a per-source-IP BPF HashMap (bounded
at 8192 entries — when full, new keys are dropped silently). The map is
read-and-cleared every harvest interval so the exposed value is the SYN
volume seen in the most recent window.
Hook choice: `tcp_v4_rcv(struct sk_buff *skb)`. This is the entry into
the IPv4 TCP receive path and fires once per inbound segment. The probe
uses fixed `sk_buff` offsets (head=200, network_header=182) and an IPv4
ihl-aware computation to locate the TCP flags byte, mirroring the
existing approach used for `skc_dport` and `srtt_us` in this codebase.
If the layout shifts on a different kernel, the `bpf_probe_read_kernel`
calls fail safely and the probe returns Ok(()) without recording.
Userspace pieces:
- `SynCountValue` shared type in `sigma-agent-ebpf-common`
- New `SynStats` / `SharedSynStats` plumbing in `ebpf_traffic.rs`
- `harvest_syn` reads + clears the SYN_MAP and converts saddr u32 (in
network byte order, as observed by `bpf_probe_read_kernel`) back to
dotted-quad strings
- `render_syn_metrics` emits `sigma_tcp_syn_count{hostname,source_ip}`
on the existing `/metrics` endpoint, only for non-zero entries
- MCP tool `query_syn_flood_candidates` (optional `min_syn` arg,
default 100). Returns `{"enabled": false, "candidates": []}` when
built without `--features ebpf-traffic`
- README subsection under "eBPF Traffic Monitoring"
The kprobe attach is best-effort: if the kernel hook is unavailable
(too old, BTF missing, layout drift), the agent logs a warning and
continues — mirroring the existing DNS/exec/OOM probe pattern.
Constraints relaxed: chose `tcp_v4_rcv` over `tcp_conn_request` /
`inet_csk_complete_hashdance` despite the spec preferring the
simplest LISTEN-state hook. `tcp_v4_rcv` fires per-segment so the
filter cost is a few `bpf_probe_read_kernel` calls + early return for
non-SYN traffic; this is the most reliable way to count *attempted*
SYNs (not just those reaching SYN-RECV) and the spec explicitly
named this hook first.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2971bba to
ef72466
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new eBPF kprobe on
tcp_v4_rcvthat counts inbound TCP SYN packets per source IPv4 address, useful for spotting SYN-flood candidates. Extends the existing eBPF observability subsystem (currently 8 probes) with a 9th.What
Kernel side (
sigma-agent-ebpf/src/main.rs):tcp_v4_rcv_synattached totcp_v4_rcv(struct sk_buff *skb)iph->saddrand TCP flags fromskb->head + skb->network_headerusing fixed offsets (mirrors the existingSKC_DPORT_OFFSET/SRTT_US_OFFSETpattern)SYN && !ACK); increments aBPF_MAP_TYPE_HASH<u32, SynCountValue>map keyed by source IPShared types (
sigma-agent-ebpf-common):SynCountValue#[repr(C)]struct shared between kernel and userspaceUserspace (
sigma-agent/src/ebpf_traffic.rs,metrics.rs,mcp.rs):SynStatstype +Arc<RwLock<Vec<SynStats>>>snapshotharvest_syn()reads + resets the map each interval (so counts are per-window, not cumulative)sigma_tcp_syn_count{source_ip}— only non-zero entries emittedquery_syn_flood_candidateswith optionalmin_synfilter (default 100)Design choices
tcp_v4_rcvrather thantcp_conn_request.tcp_v4_rcvcounts attempted SYNs including flood traffic dropped before request_sock creation — exactly what you want for flood detection. Cost is a fewbpf_probe_read_kernelcalls + early return on non-SYN packets.sigma_tcp_syn_countrepresents SYNs in the last window, not all-time. Easier for alerting (rate-of-change isn't needed).Test plan
cargo check --no-default-features— clean (userspace compiles without aya)cargo test --no-default-features— 25/25 pass (IP-format helper + Prometheus render tests)cargo check --features ebpf-traffic— sigma-agent code type-checks before the pre-existing aya/macOS failure (Linux-only crate)## eBPF Traffic MonitoringPart of the agent roadmap.