Skip to main content

Fleet Bans

One agent blocking an address is an observation. Forty agents blocking the same address is a different kind of fact — and the second one is invisible to any agent looking only at its own traffic.

Fleet bans close that gap. Each agent reports what it decided to block, the platform corroborates across the deployment, and every agent pulls back the aggregated result.

Advisory by default — nothing is enforced

A fleet ban does not install a block. The set is consulted, the outcome counted and logged, and traffic is unaffected.

That is deliberate. Acting on what other machines concluded is a large step, and it should be justified by the false-positive rate that advisory mode exists to measure. Run it, read the numbers, then decide.

Two halves of one loop

DirectionConfigScope
Ban ledgerUpload — what this agent decided to blockplatform.ban_ledgerfleet_bans:write
Fleet bansDownload — what the fleet corroboratedplatform.fleet_bansfleet_bans:read

They are separate stores with opposite provenance, and kept separate on purpose. The ledger holds first-party evidence — decisions this agent made from its own events. The fleet set holds bans this agent has no local evidence for. Merging them is how a fleet ban gets re-reported upward as fresh evidence and corroboration becomes an echo of itself.

What a fleet ban carries

Field
agentsDistinct agents that reported banning this address
agent_count_totalLive agents in the workspace — the denominator
confidencePlatform confidence, 0–100
scorePlatform score, 0–99, directly comparable to a threat-MMDB score
first_banned_unixWhen the fleet first banned this address
expires_unixWhen the ban lapses; absent means no expiry
layersBitmask of the enforcing layers that reported it

agent_count_total is the field that makes the rest readable. agents: 3 is unanimity in a three-agent fleet and noise in a three-thousand-agent one. Any threshold you write should be a ratio, not a count.

The layer bitmask records what kind of agreement it is — access_rules, smart_firewall, ids, waf, threat_intel, captcha, rate_limit. Three agents agreeing via three different layers is stronger corroboration than three agreeing via the same one, which is usually the same rule firing three times.

The platform is not trusted

Both local safety predicates are re-applied to everything the platform serves, and anything failing either is dropped regardless of what arrived:

PredicateDrops
Ban-safeAnything not unambiguously global-unicast. Fails closed.
Never-banYour own infrastructure — HOME_NET, load-balancer VIPs, node IPs

The never-ban check is the one that matters most in practice. A public load balancer VIP is global-unicast, so the first predicate would permit it; banning it blackholes every client behind it.

The asymmetry is intentional: the agent is permissive about what it uploads — an unsafe ban is worth reporting so the fleet can see it — and strict about what it accepts.

Rejections are counted separately as rejected_unsafe, rejected_protected and rejected_malformed, so a set that is arriving but being discarded is visible rather than looking like an empty fleet. A malformed record is skipped and counted rather than failing the whole payload.

Configuration

platform:
ban_ledger:
enabled: true
interval_secs: 60

fleet_bans:
enabled: true
refresh_secs: 60
advisory: true
advisory_dedup_secs: 300

Both inherit platform.base_url, so neither normally states a URL.

interval_secs governs how fast a ban propagates, not how much traffic this generates: a tick whose snapshot has not changed sends nothing at all, and a forced resend happens only every twelfth suppressed tick. refresh_secs is a cheap version check — the artifact is downloaded only when the version changes.

Both default to 60 seconds so the loop is symmetric rather than having a slow leg. Raise refresh_secs if a large fleet makes the version endpoint hot.

Limits worth knowing

  • Advisory means advisory. Consulted, counted, logged. No traffic is affected until someone decides otherwise on the evidence.
  • An unloaded set is not an empty one. A miss before the first set has been published means we do not know yet, not not banned. Advisory mode can ignore the difference; anything enforcing must not.
  • Corroboration is not proof. Agents in one deployment often run one policy, so agreement can mean the same rule fired everywhere rather than independent confirmation. Read the layer mask before treating a count as consensus.
  • It needs both scopes. fleet_bans:write to contribute, fleet_bans:read to receive. An agent with only read is a passenger.

Use cases

  • Measure before enforcing — run advisory for a period and read the false-positive rate against your own traffic.
  • Spread a detection across a fleet — one agent seeing a scanner means every agent knows about it within about a minute.
  • Corroborate a marginal signal — a source your local threshold nearly caught is easier to judge when forty other agents already did.
  • Spot a bad rule — a sudden spike in reported bans across one layer is usually a rule, not an attack.

See also