C2b-2: FlowSpec auto-mitigation wiring (persistence + config + CLI + daemon)#91
Merged
Conversation
…hods, journal 0005_flowspec migration (flowspec_rules active mirror + flowspec_requests intent log, partial unique index on (dst,proto,dst_port) WHERE withdrawn_at IS NULL); FlowSpecRuleRow/FlowSpecRequestRow; eight Store methods mirroring the rtbh_* methods (no-downgrade upsert, only_auto clear, status-driven drain, supersede); impl blackwall_rtbh::FlowSpecJournal for Store. f32 rate decoded via rate::real (no as-casts). DB tests gated on DATABASE_URL.
blackwall-core: FlowSpecPolicy (concentration, max-flows, rate, max-rules,
hold-down, ttl — no BGP peer, reuses the rtbh session + Policy.prefixes) as
Policy.flowspec: Option<_>. Policy drops Eq (f64/f32); PartialEq retained.
blackwall-config: flowspec directive mirroring rtbh (key=value, duplicate-guard,
ttl>=hold-down), plus a cross-check rejecting flowspec without an rtbh block.
Every Policy{..} literal across the workspace gains flowspec: None.
…ollector blackwalld flowspec add/remove/list mirrors the rtbh CLI (eligibility checked before the DB write). Command::Flow now, when policy.flowspec is set, builds a FlowSpecManager off the shared BgpHandle, rehydrates from list_active_flowspec, runs a single-owner flowspec_manager_task (tick + drain flowspec_requests), and feeds the collector a FanoutSink([Pg, SelectorSink]) so each detection routes to FlowSpec (concentrated) or RTBH (diffuse). Both managers share the one iBGP session.
…w-up) Guard the flowspec directive against silent-misconfig footguns the C2b-2 review flagged: concentration must be in 0.0..=1.0 (NaN would make select() never pick FlowSpec), max-flows >= 1 (0 disables selection), rate >= 0 (negative/NaN is a nonsensical traffic-rate). Added a test covering all four rejections.
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.
Closes #90. Completes sub-project C2b — makes the C2b-1 FlowSpec auto-mitigation core (#87) durable, configurable, and operable, mirroring the C1c RTBH control plane almost exactly.
What
blackwall-state):0005_flowspecmigration —flowspec_rulesactive mirror (partial-unique on(dst,proto,dst_port) WHERE withdrawn_at IS NULL, no-downgrademanual→autoupsert) +flowspec_requestsintent log. Eight Store methods +impl blackwall_rtbh::FlowSpecJournal for Store. Active rules re-announce on daemon restart.f32rate round-trips viarate::real(noas-casts).blackwall-core+blackwall-config):FlowSpecPolicy+ aflowspec concentration=… max-flows=… rate=… max-rules=… hold-down=… ttl=…directive. Reuses thertbhblock's BGP peer +Policy.prefixes; rejected at parse time if nortbhblock is present, and rejects out-of-range selection tunables.blackwalld):flowspec add/remove/listmirroringrtbh(eligibility checked before the DB write).blackwalld flowbuilds a single-ownerFlowSpecManagertask alongsideRtbhManageroff the sharedBgpHandle, rehydrates fromlist_active_flowspec, and feeds the collector aFanoutSink([Pg, SelectorSink])so each detection routes to FlowSpec (concentrated) or RTBH (diffuse).Verification
cargo fmt --all -- --check,cargo clippy --workspace --all-targets -- --deny warnings— clean.cargo test --workspace— 44 suites pass (incl. gated DB tests for the new Store methods + FlowSpecJournal, and config validation tests).scripts/coverage.sh— 95.02% (≥90%).only_autoclear, supersede scoping, shared-session BgpHandle, channel wiring not swapped, rehydrate-before-start, Pg sink retained, eligibility-before-DB). Two Low config-hardening findings fixed in the last commit.Branch is off
main(after #87 + #89 landed). Pure-core/thin-IO preserved: all decisions are in the coveredblackwall-state/blackwall-rtbh/blackwall-flowcores; onlyblackwalldglue is coverage-excluded (proven by theflowspec-auto-birdlab gate from C2b-1).🤖 Generated with Claude Code