mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-03-21 17:13:26 +01:00
Rewrite the documentation part 1
This commit is contained in:
29
CONTRIBUTING.md
Normal file
29
CONTRIBUTING.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Contributing
|
||||
|
||||
Thanks for contributing. This project is security-adjacent; changes should be deliberate and easy to review.
|
||||
|
||||
## Basic workflow
|
||||
|
||||
1. Fork the repository and create a feature branch:
|
||||
```bash
|
||||
git checkout -b feature/<name>
|
||||
```
|
||||
|
||||
2. Make changes with well described commits. (Run formatting and basic checks.)
|
||||
|
||||
3. Open a pull request:
|
||||
|
||||
* Describe what changed and why
|
||||
* Include screenshots for UI changes
|
||||
* Include migration notes if you changed configuration/DB behavior
|
||||
|
||||
## Coding and review expectations
|
||||
|
||||
* Prefer readable code over "clever code".
|
||||
* Keep public-facing behavior documented (docs or inline help).
|
||||
* Do not introduce new external network calls by default; make them opt-in where possible.
|
||||
* For changes affecting auth or callback handling, include a short threat-model note in the PR description.
|
||||
|
||||
## Reporting security issues
|
||||
|
||||
If you believe you found a security issue, please do not open a public issue. Use a private disclosure channel appropriate for the project (for example, contact Swissmakers GmbH via website) and provide reproduction steps and impact assessment.
|
||||
62
docs/api.md
Normal file
62
docs/api.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# API reference (summary)
|
||||
|
||||
This is a short index for operators. The UI primarily uses these endpoints. Paths and details may evolve; treat this as a practical reference.
|
||||
|
||||
## Authentication
|
||||
|
||||
- When OIDC is enabled, most `/api/*` endpoints require an authenticated session.
|
||||
- Callback endpoints are authenticated using `X-Callback-Secret`.
|
||||
|
||||
## Common headers
|
||||
|
||||
- `X-F2B-Server: <server-id>`
|
||||
Used by the UI to select the target server in multi-server setups (where applicable).
|
||||
|
||||
## Endpoints
|
||||
|
||||
Server management
|
||||
- `GET /api/servers`
|
||||
- `POST /api/servers`
|
||||
- `DELETE /api/servers/:id`
|
||||
- `POST /api/servers/:id/test`
|
||||
|
||||
Jails and configuration
|
||||
- `GET /api/summary`
|
||||
- `GET /api/jails/manage`
|
||||
- `POST /api/jails/manage`
|
||||
- `GET /api/jails/:jail/config`
|
||||
- `POST /api/jails/:jail/config`
|
||||
- `POST /api/jails/:jail/unban/:ip`
|
||||
- `POST /api/jails/:jail/ban/:ip`
|
||||
|
||||
Events and analytics
|
||||
- `GET /api/events/bans`
|
||||
- `GET /api/events/bans/stats`
|
||||
- `GET /api/events/bans/insights`
|
||||
|
||||
Settings
|
||||
- `GET /api/settings`
|
||||
- `POST /api/settings`
|
||||
- `POST /api/settings/test-email`
|
||||
|
||||
Filter debugging
|
||||
- `GET /api/filters`
|
||||
- `POST /api/filters/test`
|
||||
|
||||
Service control
|
||||
- `POST /api/fail2ban/restart`
|
||||
|
||||
Callbacks (Fail2Ban actions)
|
||||
- `POST /api/ban`
|
||||
- `POST /api/unban`
|
||||
|
||||
Callbacks require:
|
||||
- Header: `X-Callback-Secret: <secret>`
|
||||
- JSON body fields (typical): `serverId`, `ip`, `jail`, `hostname`, `failures`, `logs`
|
||||
|
||||
Authentication routes (OIDC)
|
||||
- `GET /auth/login`
|
||||
- `GET /auth/callback`
|
||||
- `GET /auth/logout`
|
||||
- `GET /auth/status`
|
||||
- `GET /auth/user`
|
||||
32
docs/architecture.md
Normal file
32
docs/architecture.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Architecture overview
|
||||
|
||||
Fail2Ban UI consists of :
|
||||
- a Go HTTP API (Gin)
|
||||
- a single-template web frontend (with static assets)
|
||||
- an embedded SQLite database for state and event history
|
||||
- optional integrations (Email, GeoIP/Whois, firewalls)
|
||||
|
||||
## Data flows
|
||||
|
||||
1) User -> UI -> API
|
||||
- Browser communicates with the backend via HTTP and WebSocket.
|
||||
- When OIDC is enabled, most UI routes require authentication.
|
||||
|
||||
2) Fail2Ban host -> UI callbacks
|
||||
- A custom Fail2Ban action posts ban/unban events to the UI.
|
||||
- The UI validates the callback secret, enriches (optional), stores, and broadcasts events.
|
||||
|
||||
3) UI -> Fail2Ban host (management operations)
|
||||
- Local: uses the Fail2Ban socket and local filesystem.
|
||||
- SSH: runs `fail2ban-client` and manages files via SSH.
|
||||
- Agent (preview): HTTP-based control plane (limited, in progress).
|
||||
|
||||
## Components (high level)
|
||||
|
||||
- REST API: server management, jail/filter config read/write, ban/unban actions, settings
|
||||
- WebSocket hub: streams ban/unban events and (optional) debug console logs
|
||||
- Storage: server definitions, settings, ban history, permanent block records
|
||||
|
||||
Additional resources:
|
||||
- Container deployment guide: `deployment/container/README.md`
|
||||
- systemd setup guide: `deployment/systemd/README.md`
|
||||
94
docs/configuration.md
Normal file
94
docs/configuration.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Configuration reference
|
||||
|
||||
This document describes common runtime settings. Some values are stored in the database via the UI; environment variables take precedence where noted.
|
||||
|
||||
## Network settings
|
||||
|
||||
- `PORT`
|
||||
TCP port for the HTTP server (default: 8080).
|
||||
|
||||
- `BIND_ADDRESS`
|
||||
Bind address for the HTTP server (default: `0.0.0.0`). Use `127.0.0.1` if you only publish through a reverse proxy on the same host.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
-e PORT=3080 -e BIND_ADDRESS=127.0.0.1
|
||||
````
|
||||
|
||||
## Callback URL and secret (Fail2Ban -> UI)
|
||||
|
||||
Fail2Ban UI receives ban/unban callbacks at:
|
||||
|
||||
* `POST /api/ban`
|
||||
* `POST /api/unban`
|
||||
|
||||
The callback action on each managed Fail2Ban host must be able to reach the UI callback URL.
|
||||
|
||||
* `CALLBACK_URL`
|
||||
The external URL that Fail2Ban hosts use for callbacks.
|
||||
Default behavior typically matches `http://127.0.0.1:<PORT>` (works for same-host deployments).
|
||||
|
||||
* `CALLBACK_SECRET`
|
||||
Shared secret for authenticating callbacks. If not set, the UI generates one on first start.
|
||||
Recommended: set a fixed secret in production and keep it private.
|
||||
|
||||
Example (container bridge / remote hosts):
|
||||
|
||||
```bash
|
||||
-e CALLBACK_URL=http://10.88.0.1:3080 \
|
||||
-e CALLBACK_SECRET='replace-with-a-random-secret'
|
||||
```
|
||||
|
||||
Callbacks must include:
|
||||
|
||||
* Header `X-Callback-Secret: <secret>`
|
||||
|
||||
## Privacy-related settings
|
||||
|
||||
* `DISABLE_EXTERNAL_IP_LOOKUP=true`
|
||||
Disables any external lookup used to display the host’s public IP address in the UI.
|
||||
|
||||
* `UPDATE_CHECK=false`
|
||||
Disables checking GitHub for a newer release.
|
||||
|
||||
## Fail2Ban config migration
|
||||
|
||||
* `JAIL_AUTOMIGRATION=true`
|
||||
Experimental: attempts to migrate a monolithic `jail.local` into `jail.d/`.
|
||||
Recommended: migrate manually on production systems.
|
||||
|
||||
## Email template selection
|
||||
|
||||
* `emailStyle=classic`
|
||||
Switches back alert emails from the modern template to the classic template.
|
||||
|
||||
## OIDC authentication
|
||||
|
||||
OIDC can protect the UI with an external identity provider.
|
||||
|
||||
Required:
|
||||
|
||||
* `OIDC_ENABLED=true`
|
||||
* `OIDC_PROVIDER=keycloak|authentik|pocketid`
|
||||
* `OIDC_ISSUER_URL=...`
|
||||
* `OIDC_CLIENT_ID=...`
|
||||
* `OIDC_CLIENT_SECRET=...`
|
||||
* `OIDC_REDIRECT_URL=https://<ui-host>/auth/callback`
|
||||
|
||||
Optional (common):
|
||||
|
||||
* `OIDC_SCOPES=openid,profile,email`
|
||||
* `OIDC_SESSION_SECRET=<32+ bytes recommended>` (random is generated if omitted)
|
||||
* `OIDC_SESSION_MAX_AGE=3600`
|
||||
* `OIDC_USERNAME_CLAIM=preferred_username`
|
||||
* `OIDC_SKIP_VERIFY=false` (development only)
|
||||
* `OIDC_SKIP_LOGINPAGE=false`
|
||||
|
||||
Provider notes:
|
||||
|
||||
* Keycloak: ensure your client allows the redirect URI (`/auth/callback`) and post-logout redirect (`/auth/login`).
|
||||
* Authentik/Pocket-ID: follow their OIDC client configuration and match the redirect URI exactly.
|
||||
|
||||
Additional resources:
|
||||
|
||||
* OIDC dev environment: `development/oidc/README.md`
|
||||
83
docs/installation.md
Normal file
83
docs/installation.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Installation
|
||||
|
||||
This document provides a short installation path and points to the full deployment guides in the repository.
|
||||
|
||||
Spoiler: They need to be reworked as well we already did with the main files here..
|
||||
|
||||
## Supported platforms
|
||||
|
||||
Fail2Ban UI targets Linux hosts. Typical environments include RHEL/Rocky/Alma, Debian/Ubuntu, and container environments in general.
|
||||
|
||||
## Container deployment
|
||||
|
||||
Additional resources:
|
||||
- Full guide: `deployment/container/README.md`
|
||||
- SELinux policies: `deployment/container/SELinux/`
|
||||
|
||||
### Option A: Pre-built image
|
||||
|
||||
Local connector example (Fail2Ban runs on the same host):
|
||||
```bash
|
||||
podman pull swissmakers/fail2ban-ui:latest
|
||||
|
||||
podman run -d --name fail2ban-ui --network=host \
|
||||
-v /opt/fail2ban-ui:/config:Z \
|
||||
-v /etc/fail2ban:/etc/fail2ban:Z \
|
||||
-v /var/run/fail2ban:/var/run/fail2ban \
|
||||
-v /var/log:/var/log:ro \
|
||||
swissmakers/fail2ban-ui:latest
|
||||
````
|
||||
|
||||
Notes:
|
||||
|
||||
* `/config` stores the SQLite DB, settings, and SSH keys used by the UI.
|
||||
* `/var/log` is used for log path tests and should be mounted read-only to the container.
|
||||
|
||||
### Option B: Docker Compose
|
||||
|
||||
Use one of the examples and adapt to your environment:
|
||||
|
||||
```bash
|
||||
cp docker-compose.example.yml docker-compose.yml
|
||||
# or
|
||||
cp docker-compose-allinone.example.yml docker-compose.yml
|
||||
|
||||
podman compose up -d
|
||||
```
|
||||
You can also start and test the full dev-stacks from the development folders, it you only want to try it out.
|
||||
|
||||
### Option C: Build the image yourself
|
||||
|
||||
```bash
|
||||
git clone https://github.com/swissmakers/fail2ban-ui.git
|
||||
cd fail2ban-ui
|
||||
podman build -t fail2ban-ui:dev .
|
||||
podman run -d --name fail2ban-ui --network=host \
|
||||
-v /opt/fail2ban-ui:/config:Z \
|
||||
-v /etc/fail2ban:/etc/fail2ban:Z \
|
||||
-v /var/run/fail2ban:/var/run/fail2ban \
|
||||
-v /var/log:/var/log:ro \
|
||||
localhost/fail2ban-ui:dev
|
||||
```
|
||||
|
||||
## systemd deployment (standalone)
|
||||
|
||||
Additional resources:
|
||||
|
||||
* Full guide: `deployment/systemd/README.md`
|
||||
|
||||
High-level procedure:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/swissmakers/fail2ban-ui.git /opt/fail2ban-ui
|
||||
cd /opt/fail2ban-ui
|
||||
|
||||
# Build static CSS assets
|
||||
./build-tailwind.sh
|
||||
|
||||
# Build the go-binery
|
||||
go build -o fail2ban-ui ./cmd/server/main.go
|
||||
```
|
||||
|
||||
Then follow `deployment/systemd/README.md` to install the unit file and configure permissions.
|
||||
|
||||
54
docs/security.md
Normal file
54
docs/security.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Security guidance
|
||||
|
||||
This project can perform security-sensitive operations (bans, configuration changes). Deploy it as you would deploy every other administrative interface.
|
||||
|
||||
## Recommended deployment posture
|
||||
|
||||
- Do not expose the UI directly to the Internet.
|
||||
- Prefer one of:
|
||||
- VPN-only access
|
||||
- Reverse proxy with strict allowlists
|
||||
- OIDC enabled (in addition to network controls)
|
||||
|
||||
If you must publish it, put it behind TLS and an authentication layer, and restrict source IPs.
|
||||
|
||||
## Callback endpoint protection
|
||||
|
||||
The fail2ban callback endpoints (`/api/ban`, `/api/unban`) are only reachable with a correct `CALLBACK_SECRET`. This secret must be atleast 20 characters long. If not specified a secure secret, will be automatically genereated on first start. It can be further protected by:
|
||||
|
||||
- Use even a stronger `CALLBACK_SECRET` than our default (32 characters)
|
||||
- Make network restrictions (only allow known Fail2Ban hosts to reach the callback endpoint)
|
||||
|
||||
Rotate the secret if you suspect leakage.
|
||||
|
||||
## SSH connector hardening
|
||||
|
||||
For SSH-managed hosts:
|
||||
|
||||
- Use a dedicated service account (not a human user).
|
||||
- Require key-based auth.
|
||||
- Restrict sudo to the minimum set of commands required to operate Fail2Ban (typically `fail2ban-client` and optionally `systemctl restart fail2ban`).
|
||||
- Use filesystem ACLs for `/etc/fail2ban` rather than broad permissions to allow full modification capabilities for the specific user.
|
||||
|
||||
## Least privilege and file access
|
||||
|
||||
Local connector deployments typically require access to:
|
||||
- `/var/run/fail2ban/fail2ban.sock`
|
||||
- `/etc/fail2ban/`
|
||||
- selected log paths (read-only, mounted to same place inside the container, where they are on the host.)
|
||||
|
||||
Avoid running with more privileges than necessary. If you run in a container, use the repository deployment guide and SELinux policies.
|
||||
|
||||
## SELinux
|
||||
|
||||
If SELinux is enabled, use the policies provided in (according to your specific setup they are not enough):
|
||||
- `deployment/container/SELinux/`
|
||||
|
||||
Do not disable SELinux as a shortcut. Fix always labeling and policy issues instead. -> Everytime you read "to disable SELinux" you can close that guide :)
|
||||
|
||||
## Audit and operational practices
|
||||
|
||||
- Back up `/config` (DB + settings) regularly.
|
||||
- Treat the database as sensitive operational data.
|
||||
- Keep the host and container runtime patched.
|
||||
- Review Fail2Ban actions deployed to managed hosts as part of change control.
|
||||
106
docs/troubleshooting.md
Normal file
106
docs/troubleshooting.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Troubleshooting
|
||||
|
||||
## UI not reachable
|
||||
|
||||
Check:
|
||||
- Container/service is running
|
||||
- Host firewall allows the configured port
|
||||
- Reverse proxy forwards correctly (if used)
|
||||
- Firewalld port allowed?
|
||||
|
||||
Examples:
|
||||
```bash
|
||||
podman ps
|
||||
podman logs fail2ban-ui
|
||||
|
||||
# systemd:
|
||||
systemctl status fail2ban-ui
|
||||
journalctl -u fail2ban-ui -f
|
||||
|
||||
# firewalld:
|
||||
firewall-cmd --list-all
|
||||
firewall-cmd --add-port=8080/tcp --permanent
|
||||
firewall-cmd --reload
|
||||
````
|
||||
|
||||
## Local connector fails
|
||||
|
||||
Check:
|
||||
|
||||
* Fail2Ban is running and socket exists
|
||||
* Container has the socket mounted
|
||||
* Permissions allow access to the socket
|
||||
* SELinux problems
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
systemctl status fail2ban
|
||||
ls -la /var/run/fail2ban/fail2ban.sock
|
||||
fail2ban-client status
|
||||
|
||||
# check the socked in the container:
|
||||
podman exec -it fail2ban-ui ls -la /var/run/fail2ban/fail2ban.sock
|
||||
|
||||
# SELinux check for alerts (needs "setroubleshoot" linux package):
|
||||
sealert -a /var/log/audit/audit.log
|
||||
```
|
||||
|
||||
## SSH connector fails
|
||||
|
||||
Check:
|
||||
|
||||
* Key-based SSH works outside the UI
|
||||
* Service account exists and has required sudo / facl permissions
|
||||
* ACLs also allow modifications under `/etc/fail2ban`
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/<key> <user>@<host>
|
||||
sudo -l -U <user>
|
||||
getfacl /etc/fail2ban
|
||||
|
||||
# Connect manually from the fail2ban-UI connector to the remote host: (this example uses the "development/ssh_and_local" dev stack)
|
||||
sudo podman exec -it fail2ban-ui ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -i /config/.ssh/id_rsa -p 2222 testuser@127.0.0.1
|
||||
```
|
||||
|
||||
## Bans fail due to firewall backend (nftables / firewalld)
|
||||
|
||||
Symptoms often mention `iptables (nf_tables)` or action startup errors.
|
||||
|
||||
Fix:
|
||||
|
||||
* Use Fail2Ban banactions matching your host firewall backend:
|
||||
|
||||
* firewalld (use on Rocky / Red Hat / Almalinux): `firewallcmd-rich-rules`, `firewallcmd-allports`
|
||||
* nftables: `nftables-multiport`, `nftables-allports`
|
||||
* legacy iptables: `iptables-multiport`, `iptables-allports`
|
||||
|
||||
## OIDC login problems
|
||||
|
||||
Check:
|
||||
|
||||
* Issuer URL is correct and reachable
|
||||
* Redirect URI matches exactly: `https://<host>/auth/callback`
|
||||
* Provider client configuration includes post-logout redirect to `https://<host>/auth/login`
|
||||
|
||||
Logs:
|
||||
|
||||
```bash
|
||||
podman logs fail2ban-ui
|
||||
# Also enable debug logging over env or over the webUI
|
||||
```
|
||||
|
||||
## Database issues
|
||||
|
||||
Check:
|
||||
|
||||
* `/config` is writable by the container/service user
|
||||
* SQLite file permissions are correct
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
ls -la /opt/fail2ban-ui
|
||||
sqlite3 /opt/fail2ban-ui/fail2ban-ui.db "PRAGMA integrity_check;"
|
||||
Reference in New Issue
Block a user