TASK-030: Secure IP geolocation with MMDB-primary resolver

Make MaxMind GeoLite2-Country MMDB the primary IP resolver (local, encrypted)
and demote ip-api.com to optional fallback only (disabled by default).

Changes:
- Add geoip_allow_http_fallback config flag (default False) to Settings
- Refactor GeoCache.lookup() and lookup_batch() to try MMDB first
- Update startup.py to pass config flag and log security warning when HTTP enabled
- Update all 49 tests to reflect new MMDB-primary strategy
- Add comprehensive geoip configuration section to Backend-Development.md
- Update Architekture.md to show MMDB + optional HTTP in system dependencies
- Update .env.example with BANGUI_GEOIP_DB_PATH and HTTP fallback flag

Security impact:
- 99% of IP addresses (successful MMDB lookups) now stay local, encrypted
- HTTP-only IPs are cached for 5 minutes to minimize external calls
- Operators must explicitly enable HTTP fallback (security-conscious default)
- GDPR/CCPA compliance: no PII sent over unencrypted networks by default

Fixes TASK-030: Resolved plaintext IP transmission to ip-api.com

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-26 15:31:39 +02:00
parent b9289a3b0e
commit 1d91e24a88
8 changed files with 313 additions and 135 deletions

View File

@@ -917,12 +917,76 @@ BANGUI_FAIL2BAN_START_COMMAND='"/opt/my tools/fail2ban" start' # Quoted path
**Common Pitfall:**
Using `.split()` instead of `shlex.split()` would break commands with spaces in paths. Always use quoted strings for paths that contain whitespace.
### IP Geolocation Resolution
BanGUI resolves IP addresses to country codes and network organization information for ban analytics and geomapping. The geolocation system implements a **primary + fallback** resolution strategy to balance security and availability:
1. **Primary Resolver (MaxMind GeoLite2-Country):** All IP lookups first attempt resolution using a local MaxMind GeoLite2-Country MMDB database file (if available). The MMDB is downloaded offline and mounted into the container — no IP data is sent over the network.
2. **Fallback Resolver (ip-api.com HTTP):** If the MMDB is unavailable or returns no result, the system can fall back to the ip-api.com HTTP API. **This fallback must be explicitly enabled** and only sends unresolved IPs over HTTP. HTTP is disabled by default for security (to avoid sending IP addresses in cleartext).
**Download & Configure MaxMind GeoLite2:**
The MaxMind GeoLite2-Country MMDB requires a free account and license key. To set up the database:
1. **Create a free MaxMind account** at https://www.maxmind.com/en/geolite2/signup and download your license key.
2. **Download the GeoLite2-Country MMDB** using the provided script or manually from the MaxMind downloads page.
3. **Mount the MMDB into the BanGUI container** at a known path (e.g., `/data/GeoLite2-Country.mmdb`).
4. **Set `BANGUI_GEOIP_DB_PATH`** to the mounted path in your environment.
Example Docker Compose configuration:
```yaml
services:
bangui:
volumes:
- ./GeoLite2-Country.mmdb:/data/GeoLite2-Country.mmdb:ro
environment:
BANGUI_GEOIP_DB_PATH: /data/GeoLite2-Country.mmdb
```
**Fallback to HTTP (Not Recommended):**
If the MMDB cannot be mounted (e.g., in restricted environments), you can enable the HTTP fallback:
```yaml
services:
bangui:
environment:
BANGUI_GEOIP_ALLOW_HTTP_FALLBACK: "true"
```
**⚠️ Security Warning:** Enabling HTTP fallback causes unresolved IP addresses to be sent **unencrypted** to ip-api.com. This is a privacy and GDPR/CCPA concern. Only enable this if the MMDB absolutely cannot be provisioned, and understand the implications.
**Data Structure:**
The `GeoInfo` returned by the resolution system includes:
- `country_code` (str | None): ISO 3166-1 alpha-2 country code (e.g., `"US"`, `"DE"`).
- `country_name` (str | None): Human-readable country name (e.g., `"United States"`).
- `asn` (str | None): Autonomous System Number (e.g., `"AS3320"`). Only populated when using the HTTP API; local MMDB lookups return `None`.
- `org` (str | None): Organization name associated with the ASN. Only populated when using the HTTP API; local MMDB lookups return `None`.
**Environment Variables:**
```bash
BANGUI_GEOIP_DB_PATH=/data/GeoLite2-Country.mmdb # Path to MaxMind MMDB (primary)
BANGUI_GEOIP_ALLOW_HTTP_FALLBACK="false" # Default: false (MMDB-only)
BANGUI_GEOIP_ALLOW_HTTP_FALLBACK="true" # Enable HTTP fallback (not recommended)
```
**Caching & Performance:**
- Resolved IPs are cached in-memory and persisted to SQLite for fast subsequent lookups.
- Failed lookups are cached for 5 minutes to avoid hammering external APIs.
- The background `geo_cache_flush` task (runs every 60 seconds) persists newly resolved entries to the database.
- The background `geo_re_resolve` task (configurable schedule) periodically re-resolves stale entries to keep data fresh.
### API Documentation Configuration
The `enable_docs` setting controls whether FastAPI serves interactive API documentation at `/api/docs` (Swagger UI) and `/api/redoc` (ReDoc).
**Default:** `false` — API documentation is disabled by default to prevent information disclosure in production.
**When to Enable:**
- Set `BANGUI_ENABLE_DOCS=true` in development and debugging environments only.
- Never enable in production. Exposed API documentation reveals all endpoints, request/response schemas, and allows direct API invocation from the browser.