From 5a8770e973b5389c6b412ed8ce567262247815a4 Mon Sep 17 00:00:00 2001 From: Stefan Hacker Date: Thu, 9 Apr 2026 15:51:39 +0200 Subject: [PATCH] Add README with CA install guides, add /ca.crt download endpoint - Detailed CA import instructions for Chrome, Firefox, Android, iOS/iPadOS, macOS, Windows, Linux - /ca.crt endpoint for easy browser download (no auth required) - Download button in WebUI header Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 240 +++++++++++++++++++++++++++++++++++++++ app/app.py | 12 +- app/templates/index.html | 5 +- 3 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..afcb89b --- /dev/null +++ b/README.md @@ -0,0 +1,240 @@ +# HTTPS Reverse Proxy mit selbstsigniertem 100-Jahre-Zertifikat + +Ein Docker-basierter HTTPS Reverse Proxy mit eigener CA (Certificate Authority), konfigurierbarer WebUI und REST API. + +## Features + +- Selbstsigniertes SSL-Zertifikat mit eigener CA (100 Jahre gueltig) +- WebUI zur Verwaltung von Proxy-Zielen +- REST API fuer automatisierte Konfiguration +- Domain-basiertes und IP/Port-basiertes Routing +- Host Network Mode (keine Port-Freigabe noetig) +- Alle Einstellungen ueber `.env` konfigurierbar +- CA-Download direkt ueber den Browser (`https://:8443/ca.crt`) + +## Schnellstart + +### 1. Konfiguration anpassen + +```bash +cp .env.example .env +nano .env +``` + +Einstellungen in der `.env`: + +| Variable | Beschreibung | Standard | +|---|---|---| +| `CERT_COUNTRY` | Land (2-Buchstaben-Code) | `DE` | +| `CERT_STATE` | Bundesland | `Bavaria` | +| `CERT_CITY` | Stadt | `Munich` | +| `CERT_ORG` | Organisation | `MyOrganization` | +| `CERT_OU` | Abteilung | `IT` | +| `CERT_CN` | Common Name | `proxy.local` | +| `CERT_DAYS` | Zertifikat-Gueltigkeit in Tagen | `36500` (~100 Jahre) | +| `WEBUI_PORT` | Port der WebUI | `8443` | +| `WEBUI_USERNAME` | Login-Benutzername | `admin` | +| `WEBUI_PASSWORD` | Login-Passwort | `admin123` | + +### 2. Container starten + +```bash +docker compose up -d --build +``` + +### 3. WebUI oeffnen + +``` +https://:8443 +``` + +Login mit den Zugangsdaten aus der `.env`. + +## CA-Zertifikat installieren + +Damit Browser und Geraete dem selbstsignierten Zertifikat vertrauen, muss die CA installiert werden. + +### CA-Zertifikat herunterladen + +Die CA kann direkt ueber den Browser heruntergeladen werden: + +``` +https://:8443/ca.crt +``` + +Alternativ liegt die Datei im Projektverzeichnis unter `certs/ca.crt`. + +--- + +### Google Chrome (Desktop) + +1. `chrome://settings/security` oeffnen +2. Auf **Zertifikate verwalten** klicken +3. Reiter **Zertifizierungsstellen** waehlen +4. **Importieren** klicken +5. Die heruntergeladene `ca.crt` auswaehlen +6. Haken bei **Diesem Zertifikat zur Identifizierung von Websites vertrauen** setzen +7. Mit **OK** bestaetigen +8. Browser neu starten + +### Mozilla Firefox (Desktop) + +1. `about:preferences#privacy` oeffnen +2. Runterscrollen zu **Zertifikate** +3. Auf **Zertifikate anzeigen...** klicken +4. Reiter **Zertifizierungsstellen** waehlen +5. **Importieren...** klicken +6. Die heruntergeladene `ca.crt` auswaehlen +7. Haken bei **Dieser CA vertrauen, um Websites zu identifizieren** setzen +8. Mit **OK** bestaetigen + +### Android + +1. `https://:8443/ca.crt` im Browser oeffnen +2. Die Datei wird heruntergeladen +3. **Einstellungen** > **Sicherheit** > **Verschluesselung und Anmeldedaten** oeffnen +4. **CA-Zertifikat installieren** waehlen +5. Die heruntergeladene `ca.crt` auswaehlen +6. Bei Aufforderung den Geraete-PIN/Passwort eingeben +7. Dem Zertifikat einen Namen geben und mit **OK** bestaetigen + +> **Hinweis:** Der genaue Pfad variiert je nach Android-Version und Hersteller. Suche in den Einstellungen nach "Zertifikat" falls der Pfad abweicht. + +### iPhone / iPad (iOS / iPadOS) + +1. `https://:8443/ca.crt` in **Safari** oeffnen (nicht Chrome!) +2. Es erscheint die Meldung **Profil geladen** -- auf **Schliessen** tippen +3. **Einstellungen** oeffnen +4. Oben erscheint **Profil geladen** -- darauf tippen +5. Auf **Installieren** tippen und den Geraete-Code eingeben +6. Nochmals **Installieren** bestaetigen +7. Danach: **Einstellungen** > **Allgemein** > **Info** > **Zertifikatsvertrauenseinstellungen** +8. Den Schalter neben dem CA-Zertifikat **aktivieren** +9. Mit **Weiter** bestaetigen + +> **Wichtig:** Schritt 7-9 wird oft vergessen! Ohne die Vertrauenseinstellung unter "Info" ist das Zertifikat zwar installiert, aber nicht aktiv. + +### macOS + +1. `https://:8443/ca.crt` im Browser oeffnen und herunterladen +2. Doppelklick auf die `ca.crt` -- die **Schluesselbuendverwaltung** oeffnet sich +3. Das Zertifikat wird unter **Anmeldung** hinzugefuegt +4. Doppelklick auf das importierte Zertifikat +5. **Vertrauen** aufklappen +6. **Bei Verwendung dieses Zertifikats** auf **Immer vertrauen** setzen +7. Fenster schliessen und mit Admin-Passwort bestaetigen + +### Windows + +1. `https://:8443/ca.crt` im Browser oeffnen und herunterladen +2. Doppelklick auf die `ca.crt` +3. Auf **Zertifikat installieren...** klicken +4. **Lokaler Computer** waehlen (fuer alle Benutzer) oder **Aktueller Benutzer** +5. **Alle Zertifikate in folgendem Speicher speichern** waehlen +6. **Durchsuchen** > **Vertrauenswuerdige Stammzertifizierungsstellen** waehlen +7. Mit **OK** / **Weiter** / **Fertig stellen** abschliessen +8. Browser neu starten + +### Linux + +```bash +# Debian/Ubuntu +sudo cp ca.crt /usr/local/share/ca-certificates/proxy-ca.crt +sudo update-ca-certificates + +# RHEL/CentOS/Fedora +sudo cp ca.crt /etc/pki/ca-trust/source/anchors/proxy-ca.crt +sudo update-ca-trust + +# Arch Linux +sudo cp ca.crt /etc/ca-certificates/trust-source/anchors/proxy-ca.crt +sudo trust extract-compat +``` + +> **Hinweis:** Firefox unter Linux verwendet einen eigenen Zertifikatsspeicher. Die CA muss dort separat importiert werden (siehe Firefox-Anleitung oben). + +## API-Nutzung + +Alle API-Endpunkte erfordern HTTP Basic Auth. + +### Alle Ziele auflisten + +```bash +curl -k -u admin:admin123 https://localhost:8443/api/targets +``` + +### Neues Ziel hinzufuegen + +```bash +curl -k -u admin:admin123 -X POST https://localhost:8443/api/targets \ + -H "Content-Type: application/json" \ + -d '{ + "name": "mein-webserver", + "target_host": "192.168.1.50", + "target_port": 80, + "target_scheme": "http", + "listen_port": 9443, + "domains": [ + {"domain": "app.example.local", "port": 443} + ] + }' +``` + +### Ziel aktualisieren + +```bash +curl -k -u admin:admin123 -X PUT https://localhost:8443/api/targets/0 \ + -H "Content-Type: application/json" \ + -d '{"name": "updated", "target_host": "10.0.0.5", "target_port": 3000, "enabled": true}' +``` + +### Ziel loeschen + +```bash +curl -k -u admin:admin123 -X DELETE https://localhost:8443/api/targets/0 +``` + +### Nginx neu laden + +```bash +curl -k -u admin:admin123 -X POST https://localhost:8443/api/reload +``` + +## Verzeichnisstruktur + +``` +. +├── .env # Konfiguration (nicht im Git) +├── .env.example # Konfigurationsvorlage +├── Dockerfile +├── docker-compose.yml +├── app/ +│ ├── app.py # Flask App (WebUI + API) +│ ├── requirements.txt +│ └── templates/ +│ └── index.html +├── certs/ # Generierte Zertifikate (nicht im Git) +│ ├── ca.crt # CA-Zertifikat +│ ├── ca.key # CA Private Key +│ ├── server.crt # Server-Zertifikat +│ ├── server.key # Server Private Key +│ └── generate-certs.sh # Generierungsskript +├── data/ # Proxy-Konfiguration (nicht im Git) +│ └── proxy_config.json +└── nginx/ + ├── nginx.conf + └── entrypoint.sh +``` + +## Zertifikate neu generieren + +Falls die Zertifikate neu generiert werden sollen (z.B. nach Aenderung der `.env`): + +```bash +rm -f certs/ca.* certs/server.* +docker compose up -d --build +``` + +## Lizenz + +MIT diff --git a/app/app.py b/app/app.py index 3e4228b..8f7c077 100644 --- a/app/app.py +++ b/app/app.py @@ -4,7 +4,7 @@ import subprocess from functools import wraps from pathlib import Path -from flask import Flask, jsonify, redirect, render_template, request, url_for +from flask import Flask, jsonify, redirect, render_template, request, send_file, url_for app = Flask(__name__) @@ -154,6 +154,16 @@ def index(): return render_template("index.html", config=config) +@app.route("/ca.crt") +def download_ca(): + """Download CA certificate - no auth required so devices can easily fetch it.""" + ca_path = "/certs/ca.crt" + if not os.path.exists(ca_path): + return "CA certificate not found", 404 + return send_file(ca_path, as_attachment=True, download_name="ca.crt", + mimetype="application/x-x509-ca-cert") + + @app.route("/target/add", methods=["POST"]) @check_auth def add_target(): diff --git a/app/templates/index.html b/app/templates/index.html index 99bec27..0a2baca 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -197,7 +197,10 @@

HTTPS Reverse Proxy

- Self-Signed SSL - 100 Jahre +
+ CA-Zertifikat herunterladen + Self-Signed SSL - 100 Jahre +