-
Notifications
You must be signed in to change notification settings - Fork 0
Installation
For the 1.x line. Running 0.5.5 or earlier? See Installation 0.x.
Operating system. Linux. Stage 1 uses libpcap for raw capture and Stage 2
shells out to iptables and ipset, so neither works on macOS or Windows. The
installer supports apt and dnf based distributions and installs systemd units.
Privileges. Root, for packet capture and firewall control.
Hardware. Modest. The sensor is a few threads doing arithmetic. What matters is that the machine sits on the traffic path.
The installer handles the package dependencies itself, but for reference:
| Component | Needs |
|---|---|
| Stage 1 | Rust toolchain, libpcap headers |
| Stage 2 | Python 3, pip, venv |
| Enforcement | iptables, ipset, the kernel hashlimit module |
| TLS | openssl, optional but recommended |
| Kernel capture | LLVM and clang, optional |
The last row is for the kernel level capture backend. The installer sets it up when the pieces are available, choosing versions that match what your distribution ships. If they are not, the sensor still installs and runs using the standard capture path, and the installer says so rather than failing.
This is the part that most often goes wrong, so read it before installing.
FLOD only sees traffic that is routed through it. If the traffic source and the protected host sit on the same bridge and the same subnet, they talk directly at Layer 2. The virtual switch forwards frames between their ports and the gateway never sees a single packet, even if it is configured as their default gateway.
The working layout puts them in different subnets with the gateway routing between:
[ Traffic source ] [ FLOD gateway ] [ Protected host ]
Subnet A routes A to B Subnet B
| | |
[bridge 1] <-------------> [ingress iface] |
[egress iface] <-----------> [bridge 2]
Because the two ends are on different subnets, traffic is forced through the gateway. Capture runs on the ingress interface, where traffic first arrives.
The egress interface is optional. Configuring it lets FLOD compare what arrived against what was forwarded, which is how it measures the drop rate its own enforcement is achieving.
Clone the repository and run the installer:
git clone https://github.com/DevInBlack001/ddos-reduction-system.git
cd ddos-reduction-system
sudo bash scripts/install.sh --interface ens19 --victim-ips 10.0.0.3,10.0.0.4Replace the interface with your ingress interface and the addresses with the hosts you are protecting.
To protect a whole subnet instead of a list:
sudo bash scripts/install.sh --interface ens19 --victim-subnet 10.0.0.0/24| Option | Purpose |
|---|---|
--interface <IFACE> |
Ingress interface to capture on |
--victim-ips <IPs> |
Comma separated list of protected hosts |
--victim-subnet <CIDR> |
Protect an entire range instead |
--no-service |
Skip systemd unit installation |
The installer builds Stage 1 in release mode, which takes a few minutes on first run.
- Installs system packages
- Installs the Rust toolchain into the invoking user's own
~/.cargo, not root's, and builds Stage 1 as that user rather than as root - Installs the built binary to
/usr/local/bin/ddos_stage1 - Copies Stage 2's code and creates its Python virtual environment under
/opt/flod/stage2, root owned, not left in the checkout: the account that rangit cloneshould not be able to modify the code or the venv the root owned service later trusts and executes - Creates
/var/lib/flod, also root owned, for the database, the trained models, and Stage 2's JSON configuration - Generates a self signed TLS certificate in
/etc/ddos_stage2/tls - Writes systemd units for both services
The checkout itself is left as source only after this. Stage 2 runs from
/opt/flod/stage2, never from the directory you cloned into.
There is no default password. The account must be created before the dashboard
will let anyone in. install.sh already does this as its last step, but to
do it again later, run it the same way the installer does, against the
installed copy, not the checkout:
sudo DB_PATH=/var/lib/flod/stage2.db /opt/flod/stage2/venv/bin/python3 /opt/flod/stage2/setup_admin.pyIt prompts for a username and password, and will generate a strong password if you press Enter at the prompt. Write it down; it is stored only as a bcrypt hash.
sudo systemctl enable --now ddos-stage2
sudo systemctl enable --now ddos-stage1Start Stage 2 first. It owns the socket that Stage 1 connects to.
Check both came up:
systemctl status ddos-stage1 ddos-stage2Open https://<gateway-ip>:8000 in a browser.
The certificate the installer generates is self signed, so the browser will
warn on first connect. That is expected. Click through, or replace
/etc/ddos_stage2/tls/cert.pem and key.pem with a certificate issued for
that host.
If no certificate exists, Stage 2 refuses to start rather than fall back to
plain HTTP, since credentials and session cookies would otherwise travel
unencrypted. Setting FLOD_ALLOW_INSECURE_HTTP=1 opts back into plain HTTP
explicitly, for a trusted lab network or local testing only.
Watch the sensor:
journalctl -fu ddos-stage1Every few seconds it prints a capture status line:
Capture: status | interface=ens19 | raw_captured=23535 | timeouts=0 |
parse_failed=0 | non_ip=0 | truncated=0 | forwarded=23535
raw_captured climbing means packets are arriving. forwarded should track it
closely; that is the count reaching analysis. If raw_captured stays at zero,
traffic is not reaching the interface, and the network placement section above
is where to look.
On --capture-mode kernel the equivalent line reads:
Kernel: status | interface=ens19 | ingress=23535 | egress=23180 |
sources=412 (0.6% of map) | flows=88 | drains=20 | errors=0
The sensor then spends a warm up period learning your baseline before it will flag anything. Until it finishes, no enforcement happens by design.
The defaults work, and the sensor relearns your traffic baseline on its own, so this is not a required step. If ordinary traffic starts getting flagged, let the system measure your network rather than guessing at values:
sudo python3 scripts/calibrate.py --auto-debug --applyIt samples 1000 ordinary windows per protected host, roughly 8 to 17 minutes,
and writes what it finds to /etc/ddos_stage1/tuning.env. Run it without
--apply to see the numbers first, and --reset to undo it. Configuration
covers the options.
sudo bash scripts/update.shRebuilds Stage 1, copies the updated Stage 2 code into /opt/flod/stage2,
updates Python dependencies there, migrates the database, and restarts
both services. Runtime state, the database, the whitelist, the target
list, and the saved configuration, lives in /var/lib/flod, separate
from the code, so re-running the installer or the updater does not touch
your accounts or history.
If you sync your own checkout to the machine before running the installer or updater (rather than cloning directly on it), exclude your local build artifacts and virtual environment so they are not copied somewhere they do not belong:
rsync -avh --exclude="venv" --exclude="target" --exclude=".git" \
--exclude="*.db*" --exclude="*.log" --exclude="__pycache__" \
ddos-reduction-system user@host:~/That copies source only. The installer or updater still does the real
work of putting Stage 2 into /opt/flod/stage2 and its state into
/var/lib/flod on the target machine.
sudo bash scripts/uninstall.shRemoves binaries, the virtual environment, service units, and the socket. Add
--remove-build to clear the build cache, and --remove-rust to remove the
toolchain as well.