Skip to content

Troubleshooting 0x

AbdullahArmiyao edited this page Aug 15, 2026 · 1 revision

Troubleshooting (0.x)

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-stage2

The Sensor Captures Nothing

The 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 20

If 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_stage1

Packets Are Captured but Not Analysed

Compare 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.

Nothing Is Ever Flagged

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.

Legitimate Traffic Is Being Flagged

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:

  1. Raise --k so the boundary sits further from the average.
  2. Raise block_rate_floor_pps and ratelimit_rate_floor_pps so a low absolute rate cannot trigger enforcement whatever the baseline says.
  3. 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>

I Locked Myself Out

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_ratelimit

Enforcement Does Not Take Effect

Confirm 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 ddos

Both 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.

The Dashboard Will Not Load

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.

The Dashboard Loads but Renders Nothing

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.

Data Looks Stale

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.

Records Are Missing from the Event Log

If the journal shows enforcement happening but the log page does not list it, check for database errors:

journalctl -u ddos-stage2 | grep -i sqlite

Older versions could lose incident records under load while enforcement itself succeeded. Updating fixes it.

Services Will Not Start

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-stage1

Cannot Log In

There is no default account. If one was never created:

cd stage2
sudo venv/bin/python3 setup_admin.py

Repeated 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.

Filing a Bug

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.

Clone this wiki locally