-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting 0x
For the 0.x line, which ended at 0.5.5. Running 1.x or later? See Troubleshooting, which also covers the kernel capture backend.
Start here:
systemctl status ddos-stage1 ddos-stage2
journalctl -fu ddos-stage1
journalctl -fu ddos-stage2The capture status line shows raw_captured=0 and it never climbs.
Traffic is not routed through the gateway. This is the usual cause. If the source and the protected host are on the same bridge and the same subnet, they talk directly at Layer 2 and the gateway never sees the packets, even when it is configured as their default gateway. Confirm independently:
sudo tcpdump -i ens19 -c 20If tcpdump sees nothing either, the problem is the network layout, not FLOD. See the network placement section in Installation.
The wrong interface. Check the ExecStart line in
/etc/systemd/system/ddos-stage1.service against ip link.
The filter excludes your traffic. The sensor only captures traffic destined
for the addresses given by --victim-ips or --victim-subnet. Traffic to
anything else is dropped in the kernel before it reaches the sensor. To confirm
this is the cause, restart briefly with --no-filter and see whether counts
start climbing. Do not leave it that way.
Missing capture rights. The journal will say so at startup. Either run as root or grant the capability:
sudo setcap cap_net_raw+ep /usr/local/bin/ddos_stage1Compare raw_captured against forwarded in the status line.
parse_failed counts frames that were not parseable at all. A small number on a
noisy link is normal; a large proportion is not.
non_ip counts non IP frames, which should be near zero given the filter.
truncated counts frames whose payload was cut short by the snapshot length.
This is expected and harmless. The sensor reads only headers, and a truncated
frame is still fully analysed. A large truncated count alongside
parse_failed=0 is the normal, healthy state.
Still warming up. The sensor learns your baseline before it will flag anything. Until warm up finishes there is deliberately no enforcement. The journal shows progress.
Sensitivity too low. Lower --k in steps of half a point. Every step
widens what counts as an anomaly.
Traffic genuinely is not anomalous. If an attack is distributed enough to resemble normal traffic in both rate and source diversity, this detector will not separate it. That is a real limitation of a header only feature set, not a misconfiguration.
Check the flagged windows in the journal:
ANOMALY window 34 | flags=0x02 | r=24.5 (boundary=68.2) |
h=0.9533 (boundary=0.9565) | dom_ratio=0.200
Read the margins. If the measured value is barely past the boundary, and
dom_ratio is low, traffic is well distributed and this is a false positive.
flags=0x01 is a rate anomaly, flags=0x02 is an entropy anomaly.
This happens when your normal traffic is very consistent. A small variance puts the boundary almost on top of the average, so ordinary fluctuation crosses it.
Remedies, in order of preference:
- Raise
--kso the boundary sits further from the average. - Raise
block_rate_floor_ppsandratelimit_rate_floor_ppsso a low absolute rate cannot trigger enforcement whatever the baseline says. - Whitelist the sources if they are known and fixed.
Rate limited addresses recover on their own when their entry expires. To clear one immediately, use the firewall page or:
sudo ipset del ddos_ratelimit <address>Blocking your own management address is the most common self inflicted problem. From console access:
sudo ipset del ddos_blocklist <your-address>
sudo ipset del ddos_ratelimit <your-address>Then add yourself to the whitelist before doing anything else.
To clear everything:
sudo ipset flush ddos_blocklist
sudo ipset flush ddos_ratelimitConfirm the sets exist and the rules are attached:
sudo ipset list ddos_blocklist
sudo iptables -L INPUT -n --line-numbers | grep ddos
sudo iptables -L FORWARD -n --line-numbers | grep ddosBoth chains should have a rule for each set. Stage 2 creates them at startup and logs a warning if it cannot.
The rate limit needs the kernel hashlimit module. If it is missing, blocks
will work and rate limits will not.
Note that both sets match on source address. Traffic is stopped based on where it came from, not where it was going.
Certificate warning. Expected with the self signed certificate the installer generates. Click through, or install a certificate issued for the host.
Connection refused. Check Stage 2 is running and nothing else holds port 8000.
Redirected to login repeatedly. Sessions last ten minutes of inactivity. If it happens immediately, the browser is refusing the session cookie. Over plain HTTP this can happen if the browser was previously served HTTPS from the same host.
Almost always a stale cached script from before an update. Force a full reload with Ctrl+Shift+R.
Recent versions tell the browser to revalidate its cached copies, so this should no longer occur. If it does after an update, the browser is holding files from before that change.
The dashboard polls every two seconds and the sensor reports on a matching heartbeat.
If one host's figures update and another's do not, the quiet one is simply reporting on its heartbeat while the busy one reports on every flagged window. That is expected.
If nothing updates at all, Stage 2 has probably lost the socket. Check the journal and restart Stage 2 first, then Stage 1.
If the journal shows enforcement happening but the log page does not list it, check for database errors:
journalctl -u ddos-stage2 | grep -i sqliteOlder versions could lose incident records under load while enforcement itself succeeded. Updating fixes it.
Stage 1 exits immediately. Usually the interface does not exist or capture rights are missing. The journal names the reason and lists available interfaces.
Stage 2 exits immediately. Usually a missing Python dependency after a
partial update. Re run scripts/update.sh.
Stage 1 runs but Stage 2 sees nothing. Stage 2 owns the socket, so start it first:
sudo systemctl restart ddos-stage2
sudo systemctl restart ddos-stage1There is no default account. If one was never created:
cd stage2
sudo venv/bin/python3 setup_admin.pyRepeated failed logins from one address lock that address out temporarily. Wait it out.
If the journal mentions a stored hash not being in the expected format, the
account predates the current password scheme. Re run setup_admin.py to reset
it.
Include the output of systemctl status for both services, the relevant
journal extract, a capture status line, your ExecStart line, and your
distribution and kernel version.
Redact real addresses if you would rather not publish them, but say what you replaced them with so the report still makes sense.
Security vulnerabilities go through the process in SECURITY.md, not the issue
tracker.