Authentifizierung
Was macht es?
Authentication kontrolliert wer auf eine Route zugreifen darf. GateControl bietet drei Stufen:
Keine Authentifizierung:
Client → Caddy → Backend ✓ (jeder hat Zugriff)
Basic Auth:
Client → Caddy → "Username/Passwort?" (Browser-Dialog) → Backend ✓
Route Auth:
Client → Caddy → Login-Seite (Email + Passwort + 2FA) → Session-Cookie → Backend ✓
Keine Authentifizierung
Die Route ist öffentlich erreichbar. Jeder mit der URL kann zugreifen.
Wann sinnvoll:
- Öffentliche Websites und APIs
- In Kombination mit Peer ACL (nur VPN-Zugang, kein Login nötig)
- Dienste die eigene Authentifizierung mitbringen (z.B. Nextcloud, Gitea)
Achtung: Ohne Auth und ohne ACL ist die Route für das gesamte Internet sichtbar. Das Backend sollte dann selbst eine Login-Funktion haben.
Basic Auth
HTTP Basic Authentication — der Browser zeigt einen nativen Anmelde-Dialog.
Wie funktioniert es technisch?
Caddy fügt einen authentication Handler vor allen anderen Handlern ein:
{
"handler": "authentication",
"providers": {
"http_basic": {
"accounts": [{
"username": "admin",
"password": "$2a$14$..."
}]
}
}
}
Ablauf:
- Client öffnet die Route
- Caddy antwortet mit
401 UnauthorizedundWWW-Authenticate: Basic - Browser zeigt nativen Login-Dialog
- Client sendet
Authorization: Basic <base64(user:pass)>Header - Caddy prüft Username gegen gespeicherten Wert und Passwort gegen bcrypt-Hash
- Bei Erfolg: Anfrage wird an Backend weitergeleitet
- Der
AuthorizationHeader wird bei jeder Anfrage mitgesendet (kein Session-Management)
Eigenschaften
| Eigenschaft | Wert |
|---|---|
| Passwort-Speicherung | bcrypt Hash (Admin-Login: argon2id) |
| Session-Management | Keines — Credentials bei jeder Anfrage |
| Logout | Nicht möglich (Browser cacht Credentials) |
| 2FA | Nicht möglich |
| Browser-Kompatibilität | Alle Browser |
| API-Kompatibilität | Alle HTTP-Clients (curl -u user:pass) |
| Accounts pro Route | 1 |
Use Cases
Entwickler-Tools schützen: Route phpmyadmin.example.com → phpMyAdmin. Basic Auth mit einem starken Passwort. Einfach, kein Setup, funktioniert mit jedem Browser und Tool.
API-Zugang absichern: curl -u admin:secret https://api.example.com/data — Basic Auth ist für APIs ideal, da kein Cookie/Session-Management nötig ist.
Route Auth
Eigene Login-Seite mit mehreren Authentifizierungsmethoden und optionaler Zwei-Faktor-Authentifizierung.
Wie funktioniert es technisch?
Route Auth nutzt Caddys forward_auth Mechanismus:
- Caddy leitet
/route-auth/*Pfade direkt an GateControl (Port 3000) weiter (Login-Seite, Assets) - Für alle anderen Pfade: Forward-Auth Subrequest an
GET /route-auth/verify - GateControl prüft den Session-Cookie
- Bei gültiger Session (2xx): Anfrage wird ans Backend weitergeleitet
- Bei ungültiger Session:
302 Redirectzur Login-Seite
{
"handler": "reverse_proxy",
"upstreams": [{ "dial": "127.0.0.1:3000" }],
"rewrite": { "method": "GET", "uri": "/route-auth/verify" },
"headers": {
"request": {
"set": {
"X-Route-Domain": ["app.example.com"],
"X-Forwarded-Method": ["{http.request.method}"],
"X-Forwarded-Uri": ["{http.request.uri}"]
}
}
}
}
Drei Login-Methoden
Email & Password
Klassischer Login mit Email-Adresse und Passwort.
- Passwort wird als bcrypt-Hash gespeichert
- Kein externer Dienst nötig
- Einfachste Methode
Email & Code
6-stelliger Einmalcode wird per Email gesendet.
- Erfordert konfiguriertes SMTP (Settings → Email)
- Code ist zeitlich begrenzt
- Kein Passwort nötig — nur Zugang zur Email
- Ideal für Benutzer die sich keine Passwörter merken wollen
TOTP (Time-based One-Time Password)
Authenticator-App generiert 6-stellige Codes.
- Kompatibel mit: Google Authenticator, Microsoft Authenticator, Authy, 1Password, etc.
- Kein Passwort, kein Email-Zugang nötig
- Erfordert einmalige QR-Code-Einrichtung
Zwei-Faktor-Authentifizierung (2FA)
Route Auth unterstützt optionale 2FA. Dabei wird Email & Password als erster Faktor kombiniert mit:
- Email Code als zweiter Faktor: Nach dem Passwort wird ein 6-stelliger Code per Email gesendet
- TOTP als zweiter Faktor: Nach dem Passwort wird ein TOTP-Code aus der Authenticator-App verlangt
Session-Management
| Eigenschaft | Wert |
|---|---|
| Session-Dauer | Konfigurierbar: 1h, 12h, 24h, 7d, 30d |
| Session-Speicherung | Cookie |
| Logout | Ja (zerstört Session) |
| Mehrere Geräte | Ja (separate Sessions) |
Custom Branding
Jede Route kann eine eigene Login-Seite haben:
- Logo (Upload oder URL)
- Titel und Beschreibungstext
- Farben (Primary, Background)
- Hintergrundbild
TOTP-Einrichtung (Schritt für Schritt)
- Route erstellen/bearbeiten → Auth Type: Route Auth
- Method: TOTP auswählen (oder als 2FA zweiter Faktor)
- Route speichern
- Route erneut im Edit-Modal öffnen
- Im TOTP-Abschnitt erscheint ein QR-Code
- QR-Code mit Authenticator-App scannen
- 6-stelligen Bestätigungscode eingeben
- TOTP ist aktiv
Wichtig: Der QR-Code wird nur angezeigt wenn die Route bereits gespeichert wurde. Beim Erstellen einer neuen Route muss nach dem ersten Speichern das Edit-Modal erneut geöffnet werden.
Vergleichstabelle
| Eigenschaft | Keine Auth | Basic Auth | Route Auth |
|---|---|---|---|
| Sicherheitsstufe | Keine | Mittel | Hoch |
| Login-UI | Keine | Browser-Dialog | Eigene Login-Seite |
| Passwort-Speicherung | — | bcrypt | bcrypt |
| 2FA möglich | Nein | Nein | Ja |
| Session/Logout | — | Nein/Nein | Ja/Ja |
| API-kompatibel | Ja | Ja (curl -u) |
Nein (Cookie-basiert) |
| Custom Branding | — | Nein | Ja |
| Accounts pro Route | — | 1 | 1 |
| Email nötig | Nein | Nein | Ja (für Email-Methoden) |
| SMTP nötig | Nein | Nein | Nur für Email Code |
| Funktioniert mit L4 | — | Nein | Nein |
Kombination mit anderen Features
| Kombination | Wirkung |
|---|---|
| Auth + ACL | Erst VPN-IP Prüfung, dann Login |
| Auth + Force HTTPS | Pflicht bei Basic Auth (sonst Credentials im Klartext!) |
| Auth + Rate Limiting | Basic Auth: Rate Limit vor Auth. Route Auth: Rate Limit nach Auth |
| Auth + IP-Filter | Route Auth + IP-Filter: IP wird im Forward-Auth geprüft. Basic Auth + IP-Filter: nicht kombinierbar |
Wichtige Hinweise
- Basic Auth und Route Auth sind gegenseitig exklusiv. Eine Route kann nur eine der beiden Methoden verwenden.
- Basic Auth ohne HTTPS ist unsicher. Das Passwort wird Base64-kodiert (nicht verschlüsselt) im
AuthorizationHeader gesendet. Force HTTPS muss aktiv sein. - Route Auth ist nicht API-kompatibel. Es basiert auf Session-Cookies und einer Login-Seite. Für API-Zugang verwende Basic Auth.
- Authentifizierung ist nur für HTTP-Routen verfügbar, nicht für L4 (TCP/UDP).
- Bei Route Auth: der Forward-Auth Subrequest wird bei jeder Anfrage ausgeführt (Session-Cookie Prüfung). Das addiert minimal Latenz (~1-5ms).
- Basic Auth hat keine Brute-Force-Schutz eingebaut. Kombiniere es mit Rate Limiting für zusätzliche Sicherheit.
- TOTP-Secrets werden in der Datenbank gespeichert. Ein Datenbank-Backup sichert auch die TOTP-Konfiguration.
Admin-Login
Unabhängig von Route Auth schützt GateControl das eigene Admin-UI (Port 3000 hinter Caddy) über POST /login:
- Passwort-Hash in
users.password_hashist argon2id. Ältere bcrypt-Hashes werden beim nächsten Login migriert. - Sessions sind Server-seitig (
express-session), bei erfolgreichem Login wird die Session-ID regeneriert (Session-Fixation-Schutz). - Nach zu vielen Fehlversuchen greift ein Lockout: 5 Versuche / 15 Minuten pro Username (konfigurierbar unter Settings → Security,
security.lockout.max_attempts/security.lockout.duration). - Lockouts werden in
login_attemptsgespeichert; nach Ablauf der Sperre ist der Account automatisch wieder freigegeben. Ein Admin kann einen gesperrten Account manuell freigeben (lockout.unlockAccount).
Details zu den Response-Codes und Payloads stehen in der kanonischen API.md (Abschnitt Auth).
API-Token und Machine-Fingerprint
API-Tokens (gc_…) sind scoped (siehe API.md → Token Scopes). Relevante Eigenschaften:
- Speicherung als SHA-256-Hash, Klartext-Token wird nur bei der Erstellung einmal angezeigt.
scopesist Pflicht (z. B.read-only,full-access,routes,client,gateway).- Optional:
expires_at, Bindung anuser_idoderpeer_id, und Machine-Fingerprint-Binding: beim ersten Einsatz wird der SHA-256-Fingerprint der aufrufenden Maschine gespeichert; spätere Aufrufe müssen den gleichen Fingerprint mitsenden oder werden abgelehnt. Reset nur per Admin-UI. - Route Auth nutzt dieselbe Lockout-Tabelle (
type = 'route_auth').