feat: add localhost web UI for scans, blocklist, and firewall management

This commit is contained in:
zwitschi committed 2026-08-05 20:34:34 +02:00
1 parent a9dc560f80
commit 4ef6892916
19 files changed
+1934 -117

No files matched your search

+49 -10
View File
@@ -55,7 +55,11 @@ intrusion-detection/
│ ├── whois.py query_whois_subnet, consolidate_by_subnet
│ ├── mikrotik.py RouterOS .rsc script generation
│ ├── files.py read_lines, find_logs, write_csv/json/lines
│ └── reporting.py Column, render_table, render_kv, timestamp_name
│ ├── reporting.py Column, render_table, render_kv, timestamp_name
│ ├── web.py Flask web UI (app factory, JSON API, pages)
│ ├── web_scan.py background scan runner + in-memory job store
│ ├── templates/ Jinja2 page templates (dashboard, scan, reports, …)
│ └── static/ style.css + app.js (dark-theme UI)
├── data/ whitelist source files (cached locally)
│ ├── openfactory/
│ │ └── geofeed.csv
@@ -88,6 +92,8 @@ Core responsibilities by module:
| `app/whois.py` | `query_whois_subnet`, `consolidate_by_subnet` |
| `app/mikrotik.py` | `mikrotik_script`, `write_mikrotik`, `split_cidr_versions` |
| `app/firewall.py` | `MikrotikFirewall` — SSH connect, sync blocklist, audit state |
| `app/web.py` | Flask app factory, JSON API routes, page rendering |
| `app/web_scan.py` | background scan runner, in-memory job store, single-scan busy lock |
| `app/files.py` | `read_lines`, `find_logs`, `validate_dir`, `ensure_dirs`, `write_csv/json/lines` |
| `app/reporting.py` | `Column`, `render_table`, `render_kv`, `timestamp_name` |
@@ -96,7 +102,7 @@ Console output and saved reports are the **same string** (`Analyzer.text_report(
## Requirements
- Python 3.10+
- `paramiko` (MikroTik SSH), `python-dotenv` (`.env` loading)
- `paramiko` (MikroTik SSH), `python-dotenv` (`.env` loading), `flask` (web UI)
```powershell
pip install -r requirements.txt
@@ -126,6 +132,8 @@ production can set the same variables via the OS and skip `.env` entirely.
| `ROUTER_PASSWORD` | _(set in .env)_ | MikroTik connection |
| `BLOCKLIST_NAME` | `Blocked` | MikroTik address list |
| `WHITELIST_NAMES` | `Cloudflare,Openfactory` | MikroTik whitelists |
| `WEB_HOST` | `127.0.0.1` | web UI bind host |
| `WEB_PORT` | `54666` | web UI port |
See `.env.example` for the complete list of supported variables (WHOIS
tuning, scan thresholds, whitelist source URLs, and more).
@@ -133,11 +141,15 @@ tuning, scan thresholds, whitelist source URLs, and more).
## Usage
```powershell
# unified entry point (both sources, optional firewall sync)
# web UI (default entry point)
python app.py
python app.py --quiet
python app.py --update-firewall --dry-run
python app.py --update-firewall
python app.py --web-port 54666
# consolidated CLI scan (scan subcommand)
python app.py scan
python app.py scan --quiet
python app.py scan --update-firewall --dry-run
python app.py scan --update-firewall
# individual scanners (still runnable directly)
python -m app.copyparty
@@ -157,19 +169,46 @@ All scripts accept CLI overrides:
| `--min-denied N` | `1` (`copyparty.py`) | denied-hit threshold |
| `--update-firewall` | off | sync blocklist to MikroTik via SSH |
| `--dry-run` | off | preview firewall changes, no apply |
| `--web-host` | `127.0.0.1` | web UI bind host |
| `--web-port` | `54666` | web UI port |
`app.py` accepts all flags from both scanners plus `--copyparty-log-path`,
`--copyparty-report-dir`, `--npm-log-path`, `--npm-report-dir`, and
`--report-dir` for the consolidated output.
`python app.py scan` accepts all flags from both scanners plus
`--copyparty-log-path`, `--copyparty-report-dir`, `--npm-log-path`,
`--npm-report-dir`, and `--report-dir` for the consolidated output.
Examples:
```powershell
python -m app.npm --log-path D:\logs\npm --min-errors 10 --error-ratio 0.8
python -m app.copyparty --top 100
python app.py --quiet --update-firewall --dry-run
python app.py scan --quiet --update-firewall --dry-run
```
## Web UI
`python app.py` starts a **localhost-only** Flask web UI (default
`http://127.0.0.1:54666`) for running scans and managing the MikroTik
blocklist / firewall. It is bound to `127.0.0.1` — do **not** expose
`WEB_HOST` beyond localhost.
Pages:
| Route | Purpose |
| ------------ | ----------------------------------------------------- |
| `/` | dashboard — status cards + latest scans |
| `/scan` | run copyparty / npm / consolidated scans (background) |
| `/reports` | browse reports per source |
| `/blocklist` | view the consolidated blocklist, add/remove entries |
| `/firewall` | view address lists + rules, preview/apply a sync |
| `/whitelist` | view/manage provider whitelist CIDRs |
Scans run in a background thread (only one at a time) and report progress via
the JSON API, so the UI never blocks. Firewall sync is **dry-run by default**
from the UI — applying changes is an explicit action. The main JSON endpoints
(`/api/status`, `/api/scan/*`, `/api/reports/*`, `/api/blocklist`,
`/api/firewall/*`, `/api/whitelist`) are also usable directly from a REST
client.
## Output
Each script writes to its own report directory. `app.py` also writes