Skip to content

Rate-Based Detection ​

Per-IP, per-second rate thresholds with additive suspicion scoring. When an IP exceeds a threshold, points are added to its suspicion_score. When the cumulative score reaches the effective ban threshold, the IP is banned.

How scoring works ​

Window (1 second):
  IP sends N packets, M bytes, T TCP, U UDP, I ICMP, S SYN
  For each threshold exceeded → add score to suspicion_score
  suspicion_score decays by suspicion_threshold/10 each window
  When suspicion_score ≥ effective_threshold → ban

Thresholds and scores ​

MetricDefault thresholdDefault scoreConfig field
Packets/s85020pps_threshold / pps_score
Bytes/s8,912,896 (~8.5 MB/s)20bps_threshold / bps_score
TCP/s68015tcp_pps_threshold / tcp_pps_score
UDP/s42515udp_pps_threshold / udp_pps_score
ICMP/s8525icmp_pps_threshold / icmp_pps_score
SYN/s17030syn_pps_threshold / syn_pps_score

SYN floods are scored higher by default (30 points vs 20 for PPS) because they are almost always malicious at high rates.

Check frequency ​

Threshold scoring evaluates on two triggers:

  1. Window reset — every 1 second, the per-IP window counters become the rate
  2. Per-packet sampling — every 256th packet (pkt_count & 0xFF == 0) triggers a mid-window evaluation

This catches rate violations within ~256 packets instead of waiting the full second.

Suspicion decay ​

Suspicion score uses subtractive decay — a fixed amount is subtracted each window reset:

c
decay_amount = suspicion_threshold / 10;  // default: 100/10 = 10
if (decay_amount < 5) decay_amount = 5;   // floor of 5
stats->suspicion_score -= decay_amount;   // never goes below 0
Config valueDecay amountTime to clear a 100-point burst
1001010 windows (10s)
200205 windows (5s)
505 (floor)20 windows (20s)

The suspicion_decay_percent config field controls the decay amount indirectly: decay_percent >= 100 disables decay entirely. Otherwise the subtractive formula above applies.

Subtractive, not multiplicative

The old documentation described multiplicative decay (score * 0.5). The actual implementation is subtractive. This is deliberate — subtractive decay prevents a single massive burst from keeping the score permanently elevated.

Repeat offenders ​

The effective ban threshold tightens for repeat offenders:

effective_threshold = suspicion_threshold * 2 / (2 + ban_count)
minimum floor = 10
Ban countEffective threshold (default 100)
0 (first offense)100
166
250
340
528
10+10 (floor)

The ban_count is stored per-IP in ip_stats and is never reset by the kernel. It is cleared only by userspace restart (all ip_stats maps are cleared on loader startup).

Attack mode threshold tightening ​

When the dynamic mitigation subsystem declares ATTACK_UNDER_ATTACK, all rate thresholds are multiplied by attack_threshold_multiplier_percent (default 50%):

During attack: pps_threshold = 850 * 0.5  = 425
               bps_threshold = 8912896 * 0.5 = 4456448
               ...etc.

This makes detection more aggressive during confirmed attack conditions and returns to normal thresholds when the attack subsides.

Token bucket alternative ​

Set rate_limit_mode: token_bucket to use token bucket rate limiting instead of threshold scoring:

yaml
static:
  rate_limit_mode: token_bucket
  token_rate: 1000          # Tokens refilled per second per IP
  token_burst: 2000         # Max tokens before draining

Tokens refill proportionally to elapsed nanoseconds. First packet seeds the bucket. Each packet drains 1 token. Drop when empty. The token bucket is independent of suspicion scoring — no ban is triggered on token bucket exhaustion; packets are simply dropped.

Which mode to choose

  • Threshold scoring: Best for servers with mixed traffic profiles. Allows brief bursts (decay clears them), bans persistent offenders.
  • Token bucket: Best for strict rate limiting of known-good traffic patterns. Predictable, no stateful ban tracking.

Configuration ​

yaml
static:
  enabled: true
  pps_threshold: 850
  bps_threshold: 8912896
  tcp_pps_threshold: 680
  udp_pps_threshold: 425
  icmp_pps_threshold: 85
  syn_pps_threshold: 170
  suspicion_threshold: 100
  ban_duration: 3600
  suspicion_decay: "0.5"                # Actually subtractive (see above)
  rate_limit_mode: threshold
  token_rate: 0                         # Set >0 for token bucket mode
  token_burst: 0                        # Set >0 for token bucket mode

Ban System · Rate Limiting · Mitigation Overview