feat: add rate limiting requirements and implementation plan for public tile server

This commit is contained in:
Conrad Schulz 2026-06-10 08:00:27 +00:00
parent 6a20e311f4
commit f56f9c21b8
3 changed files with 188 additions and 7 deletions

View file

@ -0,0 +1,143 @@
# Anforderungen rd13_tile_server
Letzte Aktualisierung: 2026-06-10
---
## REQ-001 Tile Server öffentlich erreichbar
**Status:** ✅ umgesetzt
Der Tile Server muss über HTTPS unter einer öffentlichen Domain erreichbar sein,
damit externe Dienste (MediaWiki, Home Assistant, Nextcloud) Karten laden können.
**Akzeptanzkriterien:**
- Erreichbar unter `https://tile.rd13server.de`
- SSL-Terminierung via NPM
- Health-Endpunkt antwortet mit HTTP 200
---
## REQ-002 Rate Limiting für den öffentlichen Tile-Endpunkt
**Status:** 🔴 offen Implementierung erforderlich vor Live-Gang
Da der Server unter `https://tile.rd13server.de` öffentlich erreichbar ist, muss
er gegen unautorisierten Massenkonsum und DoS-Angriffe geschützt werden.
### Anforderungen
| ID | Anforderung | Priorität |
|---|---|---|
| REQ-002.1 | Rate Limiting: max. 10 Tile-Requests/Sekunde pro IP, Burst 60 | hoch |
| REQ-002.2 | Verbindungslimit: max. 20 gleichzeitige Verbindungen pro IP | hoch |
| REQ-002.3 | WebUI (`/`) nur aus LAN (192.168.178.0/24) erreichbar | mittel |
| REQ-002.4 | `/health` und `/catalog` nur aus LAN erreichbar | mittel |
| REQ-002.5 | HTTP-Antwort 429 bei Überschreitung mit Retry-After-Header | mittel |
| REQ-002.6 | Caching-Header für Tiles (max-age 24h) zur Lastreduzierung | mittel |
### Implementierungsplan
**Schicht 1 NPM Advanced Config (primärer Schutz)**
Rate Limiting passiert im Nginx Proxy Manager auf Proxy-Host-Ebene.
NPM erlaubt freie nginx-Direktiven im Feld „Advanced".
```nginx
# -- Rate Limiting --
# Speicher: 10 MB reicht fuer ~160.000 IP-Adressen
limit_req_zone $binary_remote_addr zone=tiles:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=tile_conn:10m;
# Burst von 60 erlaubt schnellen Kartenaufbau beim ersten Laden
limit_req zone=tiles burst=60 nodelay;
limit_conn tile_conn 20;
# 429 statt 503 zurueckgeben
limit_req_status 429;
limit_conn_status 429;
# -- Caching-Header fuer Tile-Endpunkte --
add_header Cache-Control "public, max-age=86400, stale-while-revalidate=3600" always;
add_header Vary "Accept-Encoding" always;
# -- Sicherheits-Header --
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
```
**Schicht 2 Interne Endpunkte abschirmen (im selben NPM Advanced Block)**
WebUI, Health und Catalog sollen von außen nicht erreichbar sein.
Da NPM keinen bedingten Block pro Location direkt unterstuetzt, wird ein
zweiter Proxy-Host fuer interne Endpunkte empfohlen:
```
Oeffentlicher Proxy-Host: tile.rd13server.de -> http://HOST:9982
→ nur Tile-Pfade freigeben, alle anderen 403
→ Rate Limiting aktiv
Interner Proxy-Host (kein SSL nötig):
tiles-internal.lan -> http://192.168.178.5:9982
→ kein Rate Limiting
→ nur aus LAN erreichbar (Firewall / Access List im NPM)
```
Alternativ: Einzelner Proxy-Host mit NPM Access List „LAN only" fuer `/` und `/catalog`.
**Schicht 3 fail2ban (optionaler zweiter Layer)**
```ini
# /etc/fail2ban/filter.d/nginx-tile-ratelimit.conf
[Definition]
failregex = limiting requests, excess.* by zone "tiles".* client: <HOST>
ignoreregex =
# /etc/fail2ban/jail.local
[nginx-tile-ratelimit]
enabled = true
port = http,https
filter = nginx-tile-ratelimit
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 60
bantime = 3600
```
### Reihenfolge der Umsetzung
1. NPM Proxy-Host fuer `tile.rd13server.de` anlegen (falls noch nicht vorhanden)
2. Rate-Limiting-Block in NPM Advanced Config eintragen
3. NPM Access List „LAN" anlegen und auf `/` + `/catalog` anwenden
4. Test: `ab -n 200 -c 10 https://tile.rd13server.de/osm/10/0/0` → 429 nach Burst
5. fail2ban optional installieren und konfigurieren
---
## REQ-003 Caching (nicht-funktional)
**Status:** 🔴 offen
Tiles sollen gecacht werden, um wiederholte Requests zu vermeiden und
die Last auf den Server zu reduzieren.
**Akzeptanzkriterien:**
- Cache-Control-Header auf allen Tile-Responses: `public, max-age=86400`
- NPM leitet Header durch (keine Überschreibung)
---
## REQ-004 MediaWiki Integration
**Status:** ✅ umgesetzt (LocalSettings konfiguriert)
Kartographer nutzt `https://tile.rd13server.de` als Tile-Server.
---
## REQ-005 Home Assistant Integration
**Status:** 📋 dokumentiert, nicht getestet
Satellit-Tiles als Raster-Layer in HA-Map-Card einbindbar.
Wartet auf `satellite.mbtiles` Download.

View file

@ -83,6 +83,40 @@ Branch: main
### Antwort 4
Bestaetigt: alle drei geaenderten Dateien werden in den Commit aufgenommen. Danach Wechsel in das MediaWiki-Repo und dortige Anpassungen mit eigenem Commit.
---
### Prompt 5
«ok pushe beides nur zu origin»
### Antwort 5
Beide Repos auf origin gepusht.
```bash
git -C /mnt/services-data/rd13_tile_server push origin main
git -C /mnt/services-data/rd13_media_wiki push origin main
```
Outputs:
```text
rd13_tile_server: 0488053..6a20e31 main -> main
rd13_media_wiki: d3eae3d..87258aa main -> main
```
---
### Prompt 6
«Da ich den Tile server jetzt öffentlich legen muss unter tile.rd13server.de brauchen wir noch security auf dem server das nicht jeder den server mit anfragen bombadieren kann. Nehme das als anforderung für zukünftige änderungen mit auf. Erstelle auch gerne schon einen plan dazu.»
### Antwort 6
Requirements-Datei `docs/requirements/REQUIREMENTS.md` erstellt mit:
- REQ-001 öffentliche Erreichbarkeit
- REQ-002 Rate Limiting (NPM Advanced Config + fail2ban) mit konkretem nginx-Snippet
- REQ-003 Caching
- REQ-004 MediaWiki Integration
- REQ-005 HA Integration
PROJECT_CONTEXT.md und Session-Log aktualisiert, alles committed und gepusht.
Ausgefuehrte Kommandos:
```bash
git add config/martin.yaml docker-compose.yml docs/mediawiki-config.php history/prompts/2026-06-10_tile-mediawiki-integration_session.md history/summary/PROJECT_CONTEXT.md

View file

@ -1,6 +1,6 @@
# PROJECT_CONTEXT rd13_tile_server
**Letzte Aktualisierung:** 2026-06-10 Martin laeuft healthy, WebUI aktiv, MediaWiki-Integration vorbereitet
**Letzte Aktualisierung:** 2026-06-10 Martin laeuft healthy, WebUI aktiv, MediaWiki integriert, Rate-Limiting-Anforderung aufgenommen
---
@ -44,9 +44,10 @@ Nextcloud, Home Assistant und andere Dienste Vektorkarten bereitstellt.
## Nächste Schritte (fuer naechsten Agenten)
1. **MediaWiki-Repo anpassen und committen:**
- Kartographer-Block in LocalSettings auf tile server URL setzen
- Testseite mit `mapframe`/`maplink` anlegen
1. **REQ-002 Rate Limiting im NPM UI eintragen** (manuell):
- Proxy-Host: `https://tile.rd13server.de``http://HOST:9982`
- Advanced Config: Rate-Limiting-Block aus `docs/requirements/REQUIREMENTS.md` einfügen
- NPM Access List „LAN" für `/` und `/catalog` anlegen
2. **Satellit-Download starten** (optional, ~10 GB, Zoom 010):
```bash
@ -84,13 +85,16 @@ Nextcloud, Home Assistant und andere Dienste Vektorkarten bereitstellt.
- [x] Martin WebUI aktiviert (`--webui enable-for-all`)
- [x] Endpunkte verifiziert (`/health`, `/catalog`, Root 200)
- [x] MediaWiki-Kartographer Doku in `docs/mediawiki-config.php` erweitert
- [x] MediaWiki-Repo auf Martin umgestellt und committed
- [x] Rate-Limiting-Anforderungen in `docs/requirements/REQUIREMENTS.md` aufgenommen
---
## Offene Aufgaben
- [ ] MediaWiki-Repo umstellen und dort committen
- [ ] Satellit-Download (optional)
- [ ] NPM-Konfiguration (manuell)
- [ ] **REQ-002 Rate Limiting** NPM Advanced Config für `tile.rd13server.de` eintragen (Details: `docs/requirements/REQUIREMENTS.md`)
- [ ] NPM Proxy-Host für `tile.rd13server.de` anlegen (manuell im NPM UI)
- [ ] fail2ban optional konfigurieren (REQ-002 Schicht 3)
- [ ] Satellit-Download (optional, REQ-005)
- [ ] Hook-Verteilung auf alle Repos (install-hooks.sh)
- [ ] Martin mit Satellit-Daten testen