The container init script (init-fail2ban-config) copies jail.conf from the image's /defaults/ on every start, overwriting any direct edits. The correct fix is jail.local, which is not present in the image defaults and therefore persists across restarts. Changes: - Add Docker/fail2ban-dev-config/fail2ban/jail.local with [DEFAULT] overrides for banaction = iptables-multiport and banaction_allports = iptables-allports. fail2ban loads jail.local after jail.conf so these values are available to all jails during %(action_)s interpolation. - Untrack jail.local from .gitignore so it is committed to the repo. - Fix TypeError in config_file_service: except jail_service.JailNotFoundError failed when jail_service was mocked in tests because MagicMock attributes are not BaseException subclasses. Import JailNotFoundError directly instead. - Mark BUG-001 as Done in Tasks.md.
BanGUI — Fail2ban Dev Test Environment
This directory contains the fail2ban configuration and supporting scripts for a
self-contained development test environment. A simulation script writes fake
authentication-failure log lines, fail2ban detects them via the bangui-sim
jail, and bans the offending IP — giving a fully reproducible ban/unban cycle
without a real service.
Prerequisites
- Docker or Podman installed and running.
docker compose(v2) orpodman-composeavailable on thePATH.- The repo checked out; all commands run from the repo root.
Quick Start
1 — Start the fail2ban container
docker compose -f Docker/compose.debug.yml up -d fail2ban
# or: make up (starts the full dev stack)
Wait ~15 s for the health-check to pass (docker ps shows healthy).
2 — Run the login-failure simulation
bash Docker/simulate_failed_logins.sh
Default: writes 5 failure lines for IP 192.168.100.99 to
Docker/logs/auth.log.
Optional overrides:
bash Docker/simulate_failed_logins.sh <COUNT> <SOURCE_IP> <LOG_FILE>
# e.g. bash Docker/simulate_failed_logins.sh 10 203.0.113.42
3 — Verify the IP was banned
bash Docker/check_ban_status.sh
The output shows the current jail counters and the list of banned IPs with their ban expiry timestamps.
4 — Unban and re-test
bash Docker/check_ban_status.sh --unban 192.168.100.99
One-command smoke test (Makefile shortcut)
make dev-ban-test
Chains steps 1–3 automatically with appropriate sleep intervals.
Configuration Reference
| File | Purpose |
|---|---|
fail2ban/filter.d/bangui-sim.conf |
Defines the failregex that matches simulation log lines |
fail2ban/jail.d/bangui-sim.conf |
Jail settings: maxretry=3, bantime=60s, findtime=120s |
Docker/logs/auth.log |
Log file written by the simulation script (host path) |
Inside the container the log file is mounted at /remotelogs/bangui/auth.log
(see fail2ban/paths-lsio.conf — remote_logs_path = /remotelogs).
To change sensitivity, edit fail2ban/jail.d/bangui-sim.conf:
maxretry = 3 # failures before a ban
findtime = 120 # look-back window in seconds
bantime = 60 # ban duration in seconds
Troubleshooting
Log file not detected
The jail uses backend = polling for reliability inside Docker containers.
If fail2ban still does not pick up new lines, verify the volume mount in
Docker/compose.debug.yml:
- ./logs:/remotelogs/bangui
and confirm Docker/logs/auth.log exists after running the simulation script.
Filter regex mismatch
Test the regex manually:
docker exec bangui-fail2ban-dev \
fail2ban-regex /remotelogs/bangui/auth.log bangui-sim
The output should show matched lines. If nothing matches, check that the log
lines match the corresponding failregex pattern:
# bangui-sim (auth log):
YYYY-MM-DD HH:MM:SS bangui-auth: authentication failure from <IP>
iptables / permission errors
The fail2ban container requires NET_ADMIN and NET_RAW capabilities and
network_mode: host. Both are already set in Docker/compose.debug.yml. If
you see iptables errors, check that the host kernel has iptables loaded:
sudo modprobe ip_tables
IP not banned despite enough failures
Check whether the source IP falls inside the ignoreip range defined in
fail2ban/jail.d/bangui-sim.conf:
ignoreip = 127.0.0.0/8 ::1 172.16.0.0/12
The default simulation IP 192.168.100.99 is outside these ranges and will be
banned normally.