216 lines
8.1 KiB
Markdown
216 lines
8.1 KiB
Markdown
# F2B Control Center
|
|
|
|
> Fail2Ban management dashboard for [Nginx Proxy Manager](https://nginxproxymanager.com) — bans scanners, bots, and exploit probers automatically, with a browser UI to monitor and control everything.
|
|
|
|
**Includes NPM.** The compose file spins up both Nginx Proxy Manager and the F2B dashboard together. See [nginxproxymanager.com](https://nginxproxymanager.com) for how to configure your proxy hosts.
|
|
|
|

|
|
|
|
```bash
|
|
# 1. Pull
|
|
git clone https://git.thisisfake.lol/mykey/Fail2Ban-Dashboard---NPM && cd Fail2Ban-Dashboard---NPM
|
|
|
|
# 2. Open docker-compose.yml — set SUBNETS_TO_IGNORE to your local network ranges
|
|
|
|
# 3. Run
|
|
docker compose up -d
|
|
```
|
|
|
|
Dashboard at `http://YOUR_HOST:4000` — no other setup required.
|
|
|
|
---
|
|
|
|
## What It Does
|
|
|
|
F2B Control Center runs alongside Nginx Proxy Manager as a single Docker container. It watches your NPM access logs in real time and automatically bans IPs that are:
|
|
|
|
- Using known scanner or hacking-tool user-agents (masscan, sqlmap, zgrab, etc.)
|
|
- Probing for common exploits — WordPress logins, `.env` files, admin panels, PHP shells
|
|
- Hammering your services with repeated HTTP errors
|
|
|
|
Bans are enforced at the **iptables level** — blocked IPs can't reach anything on the host, not just one service. Optionally, bans also push to **Cloudflare WAF** to block traffic before it even hits your server.
|
|
|
|
The dashboard gives you a live view of every active ban, lets you manually ban/unban IPs, scan logs for suspicious activity, check threat reputation via AbuseIPDB, and manage your trusted IP whitelist — all from the browser.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
- Docker + Docker Compose
|
|
- Linux host with iptables/nftables support
|
|
- Nginx Proxy Manager (or any reverse proxy writing NPM-format access logs)
|
|
- `xt_string` kernel module loaded on the host:
|
|
```bash
|
|
modprobe xt_string
|
|
echo xt_string >> /etc/modules # persist across reboots
|
|
```
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
git clone https://git.thisisfake.lol/mykey/Fail2Ban-Dashboard---NPM
|
|
cd f2b-control-center
|
|
```
|
|
|
|
Open `docker-compose.yml` and set `SUBNETS_TO_IGNORE` to your local network ranges — these IPs will never be scanned or banned. Everything else works out of the box.
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
| Service | URL |
|
|
|---|---|
|
|
| F2B Dashboard | `http://YOUR_HOST:4000` |
|
|
| NPM Admin UI | `http://YOUR_HOST:81` |
|
|
|
|
On first start the container populates a persistent config volume from the bundled defaults and begins monitoring NPM logs immediately. No manual fail2ban setup required.
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
All settings live in `docker-compose.yml`. Required fields are uncommented. Optional integrations are commented out — uncomment and fill in to enable them.
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `PORT` | `4000` | Dashboard port |
|
|
| `SUBNETS_TO_IGNORE` | RFC1918 ranges | Comma-separated CIDRs excluded from scanning and banning |
|
|
| `ABUSEIPDB_API_KEY` | *(optional)* | Enables AbuseIPDB threat scores and report submission |
|
|
| `CF_EMAIL` | *(optional)* | Cloudflare account email — enables WAF banning |
|
|
| `CF_APIKEY` | *(optional)* | Cloudflare Global API Key |
|
|
|
|
---
|
|
|
|
## Jails
|
|
|
|
| Jail | What triggers it | Default ban time |
|
|
|---|---|---|
|
|
| `badbot` | Known scanner/exploit user-agents | 24 hours |
|
|
| `http-errors` | 15+ 4xx/5xx errors in 5 minutes | 1 hour |
|
|
| `npm-probe` | Exploit path probing (.env, wp-login, admin panels, etc.) | 48 hours |
|
|
| `manual-bans` | Manually banned via dashboard or CLI | Permanent |
|
|
| `recidive` | Repeat offenders — 3 bans within 24h | 7 days *(disabled by default)* |
|
|
|
|
Jail thresholds (ban time, retry count, window) are tunable in the `fail2ban/jail.local` config, which persists in the `f2b-config` Docker volume across image updates. You can also edit it live through the dashboard's Jail Manager.
|
|
|
|
---
|
|
|
|
## How Banning Works
|
|
|
|
The container runs with `network_mode: host` and `NET_ADMIN`/`NET_RAW` capabilities so it can write iptables rules directly on the host network stack.
|
|
|
|
Each ban inserts two rules:
|
|
|
|
1. **DOCKER-USER chain** — drops forwarded traffic where the `X-Forwarded-For` header matches the banned IP. Catches traffic routed through Cloudflare or other CDNs.
|
|
2. **INPUT chain** — drops direct connections from the banned IP.
|
|
|
|
Bans survive container restarts (fail2ban reloads its state from disk). They do not survive host reboots unless you also enable the `recidive` jail or use persistent iptables (e.g., `iptables-persistent`).
|
|
|
|
### Cloudflare WAF (optional)
|
|
|
|
Uncomment `CF_EMAIL` and `CF_APIKEY` in `docker-compose.yml`. The container detects these on startup and activates Cloudflare banning automatically — no other config needed. Every ban also creates a Cloudflare firewall rule, blocking the IP at the edge before it reaches your server.
|
|
|
|
Get your Global API Key at: https://dash.cloudflare.com/profile/api-tokens
|
|
|
|
---
|
|
|
|
## Dashboard
|
|
|
|
See **[USERGUIDE.md](USERGUIDE.md)** for a plain-English walkthrough of every dashboard feature.
|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
---
|
|
|
|
## Log Format
|
|
|
|
Filters expect NPM access logs with the real client IP in a `[Client X.X.X.X]` field. This is the format NPM produces when sitting behind Cloudflare or any proxy that forwards `X-Forwarded-For`.
|
|
|
|
To verify your filters are working:
|
|
|
|
```bash
|
|
docker exec f2b-control-center \
|
|
fail2ban-regex /nginx-logs/proxy-host-1_access.log \
|
|
/etc/fail2ban/filter.d/http-errors.conf
|
|
```
|
|
|
|
---
|
|
|
|
## Volumes
|
|
|
|
| Volume | Container path | Contents |
|
|
|---|---|---|
|
|
| `f2b-data` | `/data` | Ban history, exemptions list |
|
|
| `f2b-config` | `/etc/fail2ban` | Jail and filter config (persists across image rebuilds) |
|
|
| bind mount | `/nginx-logs` | NPM log directory (read-only) |
|
|
|
|
To reset config to defaults: `docker volume rm f2b-control-center_f2b-config` then restart.
|
|
|
|
---
|
|
|
|
## CLI Reference
|
|
|
|
```bash
|
|
# Stream container logs
|
|
docker compose logs -f
|
|
|
|
# Reload fail2ban after manual config edits
|
|
docker exec f2b-control-center fail2ban-client reload
|
|
|
|
# Check jail status
|
|
docker exec f2b-control-center fail2ban-client status
|
|
docker exec f2b-control-center fail2ban-client status badbot
|
|
|
|
# Manual ban / unban
|
|
docker exec f2b-control-center fail2ban-client set manual-bans banip 1.2.3.4
|
|
docker exec f2b-control-center fail2ban-client set manual-bans unbanip 1.2.3.4
|
|
|
|
# Test a filter against your logs
|
|
docker exec f2b-control-center \
|
|
fail2ban-regex /nginx-logs/proxy-host-1_access.log \
|
|
/etc/fail2ban/filter.d/npm-probe.conf
|
|
```
|
|
|
|
---
|
|
|
|
## Credits
|
|
|
|
This project is built on and integrates the following open-source tools and services:
|
|
|
|
| | |
|
|
|---|---|
|
|
| [Fail2Ban](https://github.com/fail2ban/fail2ban) | IP ban engine and jail framework |
|
|
| [Nginx Proxy Manager](https://nginxproxymanager.com) — jc21 | The reverse proxy this was designed for |
|
|
| [AbuseIPDB](https://www.abuseipdb.com) | Threat intelligence API and reporting |
|
|
| [Express.js](https://expressjs.com) | Dashboard API server |
|
|
| [ipaddr.js](https://github.com/whitequark/ipaddr.js) | IP and CIDR address parsing |
|
|
| [VT323](https://fonts.google.com/specimen/VT323) | Retro terminal UI font (Google Fonts) |
|
|
| [supervisord](http://supervisord.org) | Multi-process management inside the container |
|
|
| [Docker](https://www.docker.com) | Container runtime |
|
|
|
|
### About This Project
|
|
|
|
This started as a personal setup I built to protect my own self-hosted services. The filters, iptables actions, and log parsing logic came out of real-world use on my own infrastructure.
|
|
|
|
The migration from personal scripts into a clean, shareable Docker project — packaging, entrypoint initialization, the dashboard UI, and this documentation — was done with significant help from [Claude](https://claude.ai) (Anthropic). If you're curious what AI-assisted development looks like in practice, this project is a fairly honest example.
|
|
|
|
If this saves you some headaches, you can buy me a coffee: [ko-fi.com/manicmedia](https://ko-fi.com/manicmedia)
|
|
|
|
---
|
|
|
|
## FAQ
|
|
|
|
See **[FAQ.md](FAQ.md)** for common questions including how to fix Cloudflare IP logging, bans not blocking traffic, and resetting to defaults.
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT — see [LICENSE](LICENSE).
|