Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ Thanks for contributing. This project is security-adjacent; changes should be de
git checkout -b feature/<name>
```

2. Make changes with well described commits. (Run formatting and basic checks.)
2. Make changes with well described commits. Before opening the PR, run:
```bash
gofmt -l . # must print nothing
go vet ./...
go test ./...
./build-tailwind.sh # only if you touched templates or Tailwind classes
```

3. Open a pull request:

Expand All @@ -23,6 +29,7 @@ Thanks for contributing. This project is security-adjacent; changes should be de
* 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.
* To add a UI language, copy `pkg/web/locales/en.json`, translate every value, and save it as `pkg/web/locales/<lang>.json` with a lowercase locale code (for example `ch`, `ch_de`, `es`, `pt_br`).

## Reporting security issues

Expand Down
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Fail2Ban UI does not replace Fail2Ban. Ban decisions are still made by the Fail2
* Centralized search, ban, and unban operations across all jails and servers
* Remote jail and filter configuration management (depending on connector capabilities)
* Filter debugging with live log-pattern testing
* Ban insights, including country-level analytics on an interactive 3D globe
* Ban insights with a Kibana-like ban/unban timeline, incident comparison to isolate repeat attackers, one-click permanent blocking of a whole time range, and country-level analytics
* Recurring-offender handling with permanent blocks on MikroTik, pfSense, and OPNsense
* Persistent event history and permanent-block records, with data management built in
* Configurable alerts over Email (SMTP), Webhook, and Elasticsearch, with GeoIP/Whois enrichment and country filtering
Expand All @@ -44,7 +44,7 @@ See [docs/architecture.md](docs/architecture.md) for the data-flow description.
| Connector | Typical use | Notes |
|-----------|-------------|-------|
| Local | Fail2Ban runs on the same host as the UI | Uses the Fail2Ban Unix socket and local files |
| SSH | Manage remote hosts without installing an agent | Key-based SSH and remote `fail2ban-client`; requires a dedicated service account with minimal sudo rules |
| SSH | Manage remote hosts without installing an agent | Key-based SSH and remote `fail2ban-client`; requires a dedicated service account with minimal sudo rules. Can optionally open a reverse SSH tunnel so ban callbacks reach the UI from hosts that cannot connect to it directly (NAT, isolated DMZ) |
| Agent | Environments where SSH from the UI host is not desired | HTTP agent runs on the Fail2Ban host; see [fail2ban-ui-agent](https://github.com/swissmakers/fail2ban-ui-agent) and the prebuilt image [swissmakers/fail2ban-ui-agent](https://hub.docker.com/r/swissmakers/fail2ban-ui-agent) |

## Quick start (container)
Expand Down Expand Up @@ -124,7 +124,7 @@ Overview of all active jails, banned IPs, and real-time statistics, total bans,

#### Unban IP
![Unban IP](screenshots/0.1_Dashboard_unban_IP.png)
Unbanning a IP addresses directly from the dashboard. Shows the unban confirmation dialog.
Unban an IP address directly from the dashboard. A confirmation dialog shows the affected jail before the unban runs.

### Server Management
![Manage Servers](screenshots/1_Dashboard_Manage_Servers.png)
Expand All @@ -136,11 +136,11 @@ Overview of all configured jails with their enabled/disabled status. Allows cent

#### Edit Jail Configuration
![Edit Jail](screenshots/1.2_Dashboard_Manage_Jails_Edit.png)
When clicking on "Edit Filter / Jail" the Jail configuration editor is opened. It shows the current filter and jail configuration with all options to modify the settings, test or add / modify the logpaths, and save changes.
Clicking **Edit Filter / Jail** opens the configuration editor. Edit the jail and filter settings, add or change log paths and test them, then save -> the change is pushed to the managed host and Fail2Ban is reloaded.

#### Logpath Test
![Logpath Test](screenshots/1.3_Dashboard_Manage_Jails_Edit_Logpathtest.png)
Logpath testing functionality that verifies log file paths and checks if files are accessible. Shows test results with visual indicators (yes/no) for each log path.
Logpath testing resolves the configured paths, including wildcards and Fail2Ban variables, and reports one of three results per path: found (green, with the matched files), not found (red), or cannot verify (yellow). The yellow state means the connector's SSH user cannot read the log directory. It is a warning, not a failure. Fail2Ban runs as root on the managed host and will still read the path, so the jail can be enabled.

#### Create new Filter
![Create Filter](screenshots/1.4_Dashboard_Manage_Jails_Create_Filter.png)
Expand All @@ -152,7 +152,7 @@ The second button opens the jail creation modal for setting up new jails. It sup

### Search Functionality
![Search](screenshots/1.6_Dashboard_search.png)
Search for a specific IPs, that where blocked in a specific jail, searches in all active jails. Provides a quick and painless filtering.
Search for an IP address across all active jails of every configured server. The result lists each jail that currently bans the address, so it can be unbanned in the right place.

### Internal Log Overview
![Log Overview](screenshots/2_Dashboard_Log_Overview.png)
Expand All @@ -166,6 +166,19 @@ Whois lookup modal displaying detailed information about banned IP addresses, in
![Ban Logs](screenshots/2.2_Dashboard_Log_Overview_BanLogs.png)
Detailed ban log view showing log lines that triggered the ban, timestamps, and context information for each security event.

#### Ban Insights

[![Ban Insights](screenshots/2.3_Dashboard_Log_Overview_BanInsights.png)](screenshots/2.3_Dashboard_Log_Overview_BanInsights.png)

Ban Insights brings SIEM-like analysis to environments without a full SIEM. The ban and unban activity timeline works similar like the one in Kibana -> drag to zoom into a time range, use presets from 8 hours to 30 days, or define a custom range of up to 12 months, so spikes and attack patterns become visible at a glance.

Typical workflows:

* **Correlate two incidents.** Pin one spike as Incident A and another as Incident B -> for example, last week's attack and this week's. The incident compare lists the IPs present in both. Addresses that return across incidents are repeat attackers rather than false positives, and can be banned permanently right to the recurring-offenders list.
* **Block a botnet in one click.** Select a time range in which no legitimate user is normally active, such as a nightly spike, and permanently block every IP in it on the configured firewall integration (MikroTik, pfSense, OPNsense).

The modal also suggests similar past periods, exports IP lists as CSV or JSON, and shows country-level analytics on an interactive 3D globe together with the top recurring IPs.

### Filter Debugging
![Filter Debug](screenshots/3_Filter_Debug.png)
Filter debugging interface for testing Fail2Ban filter regex patterns against log lines. Helps validate filter configurations before deployment.
Expand All @@ -180,7 +193,7 @@ Main settings page with sections for different configuration categories includin

#### Debug Console
![Debug Console](screenshots/4.1_Settings_DebugConsole.png)
When enabled the Debug console showing real-time application logs, system messages, and debugging information. Useful for troubleshooting and monitoring without the need to query the container logs manually everytime.
When enabled, the debug console streams the live application log into the browser -> useful for troubleshooting without querying the container logs manually. Leave it disabled in normal operation.

#### Advanced ban actions

Expand Down
20 changes: 12 additions & 8 deletions deployment/container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@ This guide covers building and running Fail2Ban UI with Podman or Docker.

### Pull the image

From Docker Hub (default):
The image is published to three registries. Use whichever your environment prefers:

```bash
# Docker Hub (default)
podman pull swissmakers/fail2ban-ui:latest
# or with Docker:
docker pull swissmakers/fail2ban-ui:latest
```

From the Swissmakers registry (fallback):
# GitHub Container Registry
podman pull ghcr.io/swissmakers/fail2ban-ui:latest

```bash
# Swissmakers registry (fallback)
podman pull registry.swissmakers.ch/infra/fail2ban-ui:latest
# or with Docker:
docker pull registry.swissmakers.ch/infra/fail2ban-ui:latest
```

Replace `podman` with `docker` if you use Docker.

All three receive the same multi-arch manifest (`linux/amd64` and `linux/arm64`) from the same CI build, and each push is tagged three ways: `latest`, the release version (for example `v1.5.3`), and the build commit SHA. Pin to a version tag for reproducible deployments. The images carry OCI metadata labels (`org.opencontainers.image.version`, `.revision`, `.created`, `.source`, `.licenses`), so `podman inspect` or `docker inspect` tells you exactly which build you are running.

### Run the container

```bash
Expand Down Expand Up @@ -206,6 +207,9 @@ services:
# Pre-built image from Docker Hub (default)
image: swissmakers/fail2ban-ui:latest

# Alternative: GitHub Container Registry
# image: ghcr.io/swissmakers/fail2ban-ui:latest

# Alternative: Swissmakers registry (fallback)
# image: registry.swissmakers.ch/infra/fail2ban-ui:latest

Expand Down
4 changes: 2 additions & 2 deletions development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Complete OIDC authentication setup with Keycloak and Pocket-ID for testing authe
### 2. For SSH, Local and Agent connector testing (`ssh_and_local/`)

Stack for testing Fail2ban UI with:
- Local Fail2ban instance (container)
- Local Fail2ban instances (two containers: primary on the host network, secondary on bridge)
- Remote Fail2ban instance via SSH (container)
- **Fail2ban Agent:** prebuilt image [`swissmakers/fail2ban-ui-agent`](https://hub.docker.com/r/swissmakers/fail2ban-ui-agent) (sources: [`github.com/swissmakers/fail2ban-ui-agent`](https://github.com/swissmakers/fail2ban-ui-agent))

Expand All @@ -40,7 +40,7 @@ Stack for testing Fail2ban UI with:
```

4. **Access the services:**
- Fail2ban UI: `http://localhost:3080` (or configured port)
- Fail2ban UI: `http://localhost:3080` (or configured port). The `ssh_and_local` stack serves it under `BASE_PATH=/dev`, so use `http://localhost:3080/dev/` there.
- OIDC Provider (Pocket-ID): `http://localhost:3000` (if using OIDC setup)

## Notes
Expand Down
55 changes: 40 additions & 15 deletions development/ssh_and_local/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This stack provides a complete test environment covering all three connector types:

- a **local Fail2Ban instance** (container) for the local connector,
- **two local Fail2Ban instances** (containers) for testing one or two local connectors side by side,
- a **remote Fail2Ban instance over SSH** (container) for the SSH connector,
- **Fail2Ban plus fail2ban-ui-agent** (container) for the HTTP agent connector.

Expand All @@ -22,6 +22,22 @@ This stack provides a complete test environment covering all three connector typ
| Socket | `./f2b-run-local/` |


### Fail2ban-Local-Secondary


| Property | Value |
| ------------------------------- | ------------------------------------------------------------------------ |
| Container | `DEV_fail2ban-local-secondary` |
| Purpose | Second local Fail2Ban instance, for testing two independent local connectors at once |
| Network | bridge mode, unlike the primary, which uses host mode |
| Config | `./fail2ban-config-local-secondary/` |
| Socket | `./f2b-run-local-secondary/` |
| Paths inside `DEV_fail2ban-ui` | `/etc/fail2ban-secondary` (config) and `/var/run/fail2ban-secondary` (socket) |


Configure it in the UI as a second server of type **Local**, pointing at the `-secondary` config and socket paths above. The primary instance uses the default `/etc/fail2ban` and `/var/run/fail2ban`.


### Fail2ban-SSH


Expand Down Expand Up @@ -51,12 +67,13 @@ This stack provides a complete test environment covering all three connector typ
### Fail2ban-UI


| Property | Value |
| --------- | ------------------------------------------------------------- |
| Container | `DEV_fail2ban-ui` |
| Port | `3080` |
| URL | `http://172.16.10.18:3080`, or your configured `BIND_ADDRESS` |
| Purpose | The application under test, managing all three instances |
| Property | Value |
| --------- | ------------------------------------------------------------------------------------------------------------ |
| Container | `DEV_fail2ban-ui` |
| Port | `3080`, bound to `0.0.0.0` |
| Base path | `/dev` (`BASE_PATH=/dev`), so the UI lives at `http://localhost:3080/dev/`; visiting `/` redirects there |
| Callback | `CALLBACK_URL=http://10.88.0.1:3080/dev` - the Podman default bridge gateway; change it if your bridge differs |
| Purpose | The application under test, managing all local, SSH and agent instances |


## Setup
Expand Down Expand Up @@ -101,7 +118,7 @@ podman logs DEV_fail2ban-ssh

### 4. Configure Fail2Ban UI

1. **Open the UI** at `http://172.16.10.18:3080` (or your configured `BIND_ADDRESS:PORT`; with host networking also `http://localhost:3080`).
1. **Open the UI** at `http://localhost:3080/dev/`. The stack sets `BASE_PATH=/dev`, so visiting `http://localhost:3080/` redirects there. With `BIND_ADDRESS=0.0.0.0` and host networking, the UI is also reachable on the host's other addresses.
2. **Add the local server.** Under **Manage Servers**, the local Fail2Ban instance should be auto-detected; enable the local connector.
3. **Add the SSH server.** Under **Manage Servers**, click **Add Server** and configure:

Expand Down Expand Up @@ -149,11 +166,16 @@ Edit `container-compose.yml` to customize:
```yaml
environment:
- PORT=3080
- BIND_ADDRESS=172.16.10.18 # Change to your IP, or 0.0.0.0
# OIDC settings (when testing OIDC)
- OIDC_ENABLED=false # Set to true to enable OIDC
- BIND_ADDRESS=0.0.0.0
- BASE_PATH=/dev # remove to serve the UI at the root
- CALLBACK_URL=http://10.88.0.1:3080/dev # must include BASE_PATH
- CALLBACK_SECRET=same-as-ui-callback-secret
- AUTODARK=true
# - OIDC_ENABLED=true # use development/oidc/ for a full OIDC stack
```

If you remove `BASE_PATH`, drop the `/dev` suffix from `CALLBACK_URL` as well. See [docs/configuration.md](../../docs/configuration.md#http-base-path-subpath-deployment).

### SSH container

The SSH container is pre-configured with:
Expand All @@ -170,10 +192,12 @@ To modify the SSH configuration, edit the `command` section in `container-compos
```
./config/ # Fail2Ban UI configuration and database
./ssh-keys/ # SSH key pair (shared between containers)
./fail2ban-config-local/ # Local Fail2Ban configuration
./f2b-run-local/ # Local Fail2Ban socket directory
./fail2ban-config-ssh/ # SSH Fail2Ban configuration
./fail2ban-config-agent/ # Agent Fail2Ban configuration
./fail2ban-config-local/ # Local Fail2Ban configuration (primary)
./f2b-run-local/ # Local Fail2Ban socket directory (primary)
./fail2ban-config-local-secondary/ # Local Fail2Ban configuration (secondary)
./f2b-run-local-secondary/ # Local Fail2Ban socket directory (secondary)
./fail2ban-config-ssh/ # SSH Fail2Ban configuration
./fail2ban-config-agent/ # Agent Fail2Ban configuration
```

## Test scenarios
Expand Down Expand Up @@ -213,6 +237,7 @@ To modify the SSH configuration, edit the `command` section in `container-compos
3. Switch between servers.
4. Verify each server's jails are isolated.
5. Test operations on each server independently.
6. Add the secondary local instance as a third server (type **Local**, config `/etc/fail2ban-secondary`, socket `/var/run/fail2ban-secondary`) and verify that jail lists, bans, and configuration edits stay isolated between the two local connectors.

## Troubleshooting

Expand Down
2 changes: 2 additions & 0 deletions docker-compose-allinone.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ services:
fail2ban-ui:
# Use pre-built image from Docker Hub (default)
image: swissmakers/fail2ban-ui:latest
# Alternative: Use GitHub Container Registry
# image: ghcr.io/swissmakers/fail2ban-ui:latest
# Alternative: Use Swissmakers registry (fallback)
# image: registry.swissmakers.ch/infra/fail2ban-ui:latest
# Or build from source (uncomment to use):
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ services:
# Use pre-built image from Docker Hub (default)
image: swissmakers/fail2ban-ui:latest

# Alternative: Use GitHub Container Registry
# image: ghcr.io/swissmakers/fail2ban-ui:latest

# Alternative: Use Swissmakers registry (fallback)
# image: registry.swissmakers.ch/infra/fail2ban-ui:latest

Expand Down
Loading