-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration 0x
For the 0.x line, which ended at 0.5.5. The detection tuning flags added in 1.x are not available here. Running 1.x or later? See Configuration.
There are three places settings live: the Stage 1 service unit, the dashboard,
and a few JSON files in stage2/.
The sensor is configured by its command line, written into the systemd unit at
/etc/systemd/system/ddos-stage1.service. Edit the ExecStart line, then:
sudo systemctl daemon-reload
sudo systemctl restart ddos-stage1| Flag | Default | What it does |
|---|---|---|
--interface <IFACE> |
required | Ingress interface to capture on |
--egress-interface <IFACE> |
none | Second interface, enables drop rate measurement |
--victim-ips <IPs> |
none | Comma separated protected hosts |
--victim-subnet <CIDR> |
none | Protect a range instead of a list |
--k <FLOAT> |
2.0 | Anomaly sensitivity multiplier |
--alpha <FLOAT> |
0.125 | Rate smoothing factor |
--socket <PATH> |
/run/ddos_stage1/stage1.sock |
IPC socket |
--baseline-path <PATH> |
/var/lib/ddos_stage1/baselines.json |
Where the learned baseline is saved |
--baseline-ttl-secs <N> |
3600 | Reject a saved baseline older than this |
--no-filter |
off | Capture everything, for testing only |
--log-file <PATH> |
none | Also write logs to a file |
Set RUST_LOG=debug in the unit's environment for per window detail.
This is the main sensitivity control. The sensor flags a window when the rate
exceeds mean + k * sigma, or entropy falls below mean - k * sigma.
A smaller k puts the boundary closer to the average, so more windows are
flagged. A larger k demands a bigger deviation before anything fires.
Raise it if you are seeing anomalies on traffic you know is normal. Lower it if attacks are getting through. Change it in steps of half a point and watch the journal before changing it again.
To capture labelled data for retraining the classifier:
--train-csv /path/to/output.csv --label 0
Labels are 0 for normal, 1 for flash crowd, 2 for DDoS. In this mode every post
warm up window is written to the CSV, not just the anomalous ones. Run one
session per traffic class, then train with stage2/train.py.
These live in stage2/enforcement_config.json and are editable from the
dashboard's firewall page. Anything not present in the file falls back to its
default, so an older file keeps working after an update.
| Setting | Default | Meaning |
|---|---|---|
dominant_ip_ratio_block_threshold |
0.40 | How concentrated traffic must be on one source before that source alone justifies a block |
dominant_ip_ratio_extreme_threshold |
0.75 | Above this, the window is classified as an attack regardless of entropy |
block_rate_floor_pps |
300.0 | A source must exceed this to be blocked, whatever the learned baseline says |
ratelimit_rate_floor_pps |
50.0 | The same floor for the softer rate limit tier |
block_sigma_multiplier |
10.0 | How far above baseline a single source must sit to be blocked |
block_hysteresis_windows |
2 | Consecutive attack windows required before a hard block |
block_duration_seconds |
3600 | How long a block lasts |
ratelimit_duration_seconds |
3600 | How long a rate limit lasts |
ratelimit_hashlimit_pps |
50 | The packets per second cap enforced on rate limited sources |
The two floors exist to stop a near idle host producing an absurdly low bar. If a protected host normally receives two packets per second, its learned baseline would otherwise let ten packets per second look like a flood.
block_hysteresis_windows applies only to hard blocks. Rate limiting is not
gated by it, on the reasoning that throttling a legitimate source is
recoverable and blocking one is not.
Changing ratelimit_hashlimit_pps rewrites the live iptables rule, since the
cap is part of the rule itself and cannot be edited in place.
Understanding what fires when makes the settings above easier to reason about.
Tier 1, dominant source. One source is carrying most of the traffic and is sending far above baseline. Blocked outright.
Tier 2, per source escalation. Individual sources above their own threshold are blocked, after the hysteresis window count.
Tier 3, soft rate limit. Sources over the rate limit floor are throttled rather than blocked.
Tier 4, aggregate fallback. The window is clearly an attack but no individual source stands out. Everything contributing is rate limited, nothing is blocked.
The progression is deliberate. Blocking is only used where attribution is confident.
Managed from the dashboard's targets page, stored in stage2/victims.json.
Adding a host here tells Stage 2 which addresses to track and report on. It does not change the sensor's capture filter, which comes from the service unit. If you add a target that the sensor is not filtering for, no traffic to it will ever be seen. Keep the two in step.
Addresses on the whitelist are never blocked and never rate limited, at any
tier. Stored in stage2/whitelist.json, managed from the firewall page.
Put your own management address here before you do anything else. Blocking yourself out of the gateway is the most common self inflicted problem, and recovering means console access to flush the ipset by hand.
Stored in stage2/shared_ips.json.
An address marked as shared fronts many hosts, so dropping it entirely would cut off every legitimate user behind it. When enforcement decides to block an address on this list, it rate limits instead. The attacker's share is capped and everyone else keeps working.
Mark your NAT and CGNAT egress points here. FLOD cannot detect them on its own, because from the outside a NAT gateway and a single busy host look identical.
Configured on the dashboard's alerts page, stored in
stage2/alerts_config.json with owner only permissions.
Discord needs a webhook URL from your server's channel settings.
Email uses SMTP with STARTTLS. For Gmail you need an app password, not your account password, which requires two factor authentication to be enabled on the account first.
Alerts fire on classification changes into and out of an attack state, and on hard blocks, with repeats for the same address suppressed for as long as the block lasts. Soft rate limits do not alert, since under load they would be constant.
There is a test button for each channel so you can confirm delivery without waiting for a real attack.
Alert failures are logged and swallowed. A broken webhook will never interfere with enforcement.
| Path | Contents |
|---|---|
stage2/stage2.db |
Accounts, incident log, metrics history |
stage2/victims.json |
Protected hosts |
stage2/whitelist.json |
Never enforced against |
stage2/shared_ips.json |
NAT egress points |
stage2/enforcement_config.json |
Tuning above |
stage2/alerts_config.json |
Webhook and SMTP settings |
/var/lib/ddos_stage1/baselines.json |
Learned baseline, survives restart |
/run/ddos_stage1/stage1.sock |
IPC socket |
/etc/ddos_stage2/tls/ |
Certificate and key |
The files holding credentials or secrets are owner only. They protect against other local accounts, not against root, and both services run as root.