fix: reload/stop jail 404 + access list simulator
Task 1 — fix Stop/Reload Jail returning 404
Root cause: reload_jail and reload_all sent an empty config stream
(["reload", name, [], []]). In fail2ban's reload protocol the end-of-
reload phase deletes every jail still in reload_state — i.e. every jail
that received no configuration commands. An empty stream means *all*
affected jails are silently removed from the daemon's runtime, causing
everything touching those jails afterwards (including stop) to receive
UnknownJailException → HTTP 404.
Fixes:
- reload_jail: send ["start", name] in the config stream; startJail()
removes the jail from reload_state so the end phase commits instead of
deletes, and un-idles the jail.
- reload_all: fetch current jail list first, build a ["start", name]
entry for every active jail, then send reload --all with that stream.
- stop_jail: made idempotent — if the jail is already gone (not-found
error) the operation silently succeeds (200 OK) rather than returning
404, matching the user expectation that stop = ensure-stopped.
- Router: removed dead JailNotFoundError handler from stop endpoint.
391 tests pass (2 new), ruff clean, mypy clean (pre-existing
config.py error unchanged).
Task 2 — access list simulator
- Docker/simulate_accesses.sh: writes fake HTTP-scan log lines in
custom format (bangui-access: http scan from <IP> ...) to
Docker/logs/access.log so the bangui-access jail detects them.
- fail2ban/filter.d/bangui-access.conf: failregex matching the above.
- fail2ban/jail.d/bangui-access.conf: polling jail on access.log,
same settings as bangui-sim (maxretry=3, bantime=60s).
- .gitignore: whitelist new bangui-access.conf files.
- Docker/fail2ban-dev-config/README.md: added "Testing the Access
List Feature" section with step-by-step instructions and updated
Configuration Reference + Troubleshooting.
This commit is contained in:
@@ -248,7 +248,8 @@ async def stop_jail(
|
||||
"""Stop a running fail2ban jail.
|
||||
|
||||
The jail will no longer monitor logs or issue new bans. Existing bans
|
||||
may or may not be removed depending on fail2ban configuration.
|
||||
may or may not be removed depending on fail2ban configuration. If the
|
||||
jail is already stopped the request succeeds silently (idempotent).
|
||||
|
||||
Args:
|
||||
request: Incoming request (used to access ``app.state``).
|
||||
@@ -259,7 +260,6 @@ async def stop_jail(
|
||||
:class:`~app.models.jail.JailCommandResponse` confirming the stop.
|
||||
|
||||
Raises:
|
||||
HTTPException: 404 when the jail does not exist.
|
||||
HTTPException: 409 when fail2ban reports the operation failed.
|
||||
HTTPException: 502 when fail2ban is unreachable.
|
||||
"""
|
||||
@@ -267,8 +267,6 @@ async def stop_jail(
|
||||
try:
|
||||
await jail_service.stop_jail(socket_path, name)
|
||||
return JailCommandResponse(message=f"Jail {name!r} stopped.", jail=name)
|
||||
except JailNotFoundError:
|
||||
raise _not_found(name) from None
|
||||
except JailOperationError as exc:
|
||||
raise _conflict(str(exc)) from exc
|
||||
except Fail2BanConnectionError as exc:
|
||||
|
||||
Reference in New Issue
Block a user