Reverse-Proxy-Rezepte und der Callback-Vertrag
Jeder Reverse-Proxy braucht dieselben zwei Teile: eine Autorisierer-Prüfung, die Caputchin fragt, ob eine Anfrage einen gültigen Pass trägt, und einen Callback auf deinem Origin, der einen gelösten Pass in das cpt_gate-Cookie verwandelt. Die nginx-Durchgehung zeigt die Form von Ende zu Ende; diese Seite gibt die anderen Proxys, den genauen Callback-Vertrag, und ein volles Authelia-Beispiel. Ersetze YOUR_SITE_KEY durchgehend durch deinen öffentlichen Key.
Die Endpunkte sind überall dieselben:
- Autorisierer:
GET https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY, mit weitergeleitetemCookie-Header des Besuchers.204heißt erlauben,401heißt Aufgabe. - Aufgabe: leite den Browser zu
https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<die ursprüngliche URL>um.
Der Autorisierer antwortet nur 204 oder 401. Alles andere, Timeout eingeschlossen, heißt, dass Caputchin nicht erreichbar ist, und was dann passiert, ist dein Fail-Modus: die Anfrage blockieren (fail closed, sicherer für ein Login-Portal) oder sie durchlassen (fail open). Setz ihn am Site-Key, und das erzeugte Snippet passt dazu. Gib der Autorisierer-Subrequest ein kurzes Timeout, damit ein Ausfall nicht jede Anfrage aufhalten kann, während er entscheidet.
Traefik
Nutze eine forwardAuth-Middleware für den Autorisierer. Traefik leitet den eingehenden Cookie-Header standardmäßig weiter. Bei einem 401 von der Middleware leite den Browser zur Aufgabe um (eine Error-Page-Middleware, die auf eine kleine Route zeigt, die den 302 ausgibt, oder behandle den 401 an deinem Edge).
http:
middlewares:
cpt-gate:
forwardAuth:
address: "https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY"
# The 401 from forwardAuth is your signal to send the browser to:
# https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<original-url>
routers:
portal:
rule: "Host(`auth.example.com`)"
middlewares: ["cpt-gate"]
service: your-appCaddy
Nutze forward_auth für den Autorisierer und handle_errors, um den 401 in eine Umleitung zu verwandeln. Das ist ein Ausgangspunkt; pass die Direktiven-Syntax an deine Caddy-Version an.
auth.example.com {
forward_auth https://verify.caputchin.com {
uri /v1/gate/authz?site=YOUR_SITE_KEY
copy_headers Cookie
}
handle_errors {
@challenge expression {http.error.status_code} == 401
redir @challenge https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return={scheme}://{host}{uri} 302
}
reverse_proxy your-app:8080
}Der Callback
Die gehostete Verifizierungsseite schließt ab, indem sie ein POST-Formular an https://<dein-origin>/__cpt/callback mit zwei Feldern im Body auto-absendet: cpt_gate (dem Pass) und to (wohin der Besucher geschickt wird). Hast du den Callback-Pfad am Site-Key geändert, geht der POST stattdessen dorthin. Füge diese eine Route zu deinem Origin hinzu (oder als eigene Location auf dem Proxy). Sie muss:
cpt_gateundtoaus dem POST-Body lesen, nie der URL (ein Pass in einer URL leckt in Logs und Referrer).- Bestätigen, dass
toauf deinem eigenen Origin liegt, und alles andere ablehnen, sodass der Callback nicht in einen Open Redirect verwandelt werden kann. - Das Cookie mit den Attributen unten setzen.
- (
303) zutoumleiten.
// Any tiny handler on your origin works. Express shown; ~15 lines.
app.post("/__cpt/callback", express.urlencoded({ extended: false }), (req, res) => {
const pass = String(req.body.cpt_gate || "");
const to = String(req.body.to || "/");
const target = new URL(to, `https://${req.headers.host}`);
if (target.host !== req.headers.host) return res.status(400).end(); // same-origin only
res.setHeader(
"Set-Cookie",
`cpt_gate=${pass}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=1800`
);
res.redirect(303, target.pathname + target.search);
});Die Cookie-Attribute sind das ganze Sicherheitsmodell. Weil der Pass nicht an ein Gerät gebunden ist, sind HttpOnly (blockt Skript-Diebstahl), Secure (nur HTTPS), SameSite=Lax, und eine kurze Max-Age (passend zu deiner Freigabe-TTL) das, was ihn schützt. Außerdem: logge den cpt_gate-Wert nicht in deinen Access-Logs, und behalte Referrer-Policy: no-referrer auf dem Callback, sodass der Pass nie in einem Referrer-Header mitreist.
Fail-Modus je Proxy
Caputchin sieht eine Fail-Modus-Entscheidung nie, also taucht sie nie in deiner Statistik auf: dein Proxy trifft sie lokal, wenn er den Autorisierer nicht erreicht.
- nginx:
proxy_intercept_errors on;pluserror_page 500 502 503 504 = @cpt_unreachable;, wobei diese benannte Locationreturn 403(geschlossen) oderreturn 204(offen) macht. - Traefik: die
forwardAuth-Middleware läuft bei einer nicht erreichbaren Adresse auf einen Fehler; route das auf einen Service, der403zurückgibt (geschlossen), oder nimm die Middleware hinter einem Healthcheck aus dem Router (offen). - Caddy: erweitere
handle_errorsum einen Matcher auf5xx, der entwederrespond 403(geschlossen) oderrespond 204(offen) macht.
Pfad-Scoping je Proxy
Nur diese Pfade abdecken und Diese Pfade nie abdecken formen die erzeugte Konfiguration; durchgesetzt werden sie von deinem Proxy.
- nginx: ein
location ^~ <Präfix>pro abgesichertem Pfad, undauth_request off;in jedem ausgeschlossenen. Ein Endungs-Muster wie*.phpwird zulocation ~* \.php$. - Traefik: häng die
cpt-gate-Middleware nur an die Router, deren Regeln auf die abgesicherten Pfade passen, und lass sie beim Rest weg. - Caddy: wickle
forward_authin einen Pfad-Matcher, zum Beispiel@gated path /admin/* /loginund dannforward_auth @gated ....
Sichere nie die Autorisierer-Subrequest oder deinen Callback-Pfad ab.
Durchgearbeitetes Beispiel: Authelia
Authelias Login-Portal ist eine kompilierte Single-Page-App ohne Platz, das Widget einzubetten, und ohne Plugin-Hook, also ist das Gate der Weg, es zu schützen. Authelia sitzt bereits hinter einem Reverse-Proxy (so funktioniert sein eigenes ForwardAuth), und dieser Proxy ist der Ort für das Gate. Authelia selbst bleibt völlig unverändert.
Setze das Gate auf den vhost des Portals (zum Beispiel auth.example.com):
- Sichere das Portal-HTML und den First-Factor-Login-Endpunkt (
/api/firstfactor) ab. - Schließe Authelias eigenen ForwardAuth-verify-Endpunkt (
/api/verify) aus, den der Proxy bei jeder geschützten Upstream-Anfrage aufruft. Ihn abzusichern würde jede geschützte App hinter Authelia brechen. - Schließe Health-Checks und die statischen Assets aus, die die Aufgabenseite selbst braucht.
- Füge die
/__cpt/callback-Route wie oben hinzu (oder deinen konfigurierten Callback-Pfad).
Genau das drücken die Pfad-Scope-Einstellungen aus: / und /api/firstfactor als abgesicherte Pfade, /api/verify und dein Healthcheck als ausgeschlossene.
Das Gate hält Bots vom Portal fern; Authelias eingebaute Regulation (Retry-Limit und Bann) deckelt weiterhin die Credential-Retries für jeden, der durchkommt, sodass die zwei Schichten sich stapeln. Das Gate schützt nur das interaktive Portal (die Login- und Consent-UI); es sichert die nicht-interaktiven Token-Endpunkte nicht ab, und sollte es auch nicht.
Siehe auch
- Das Proxy-Seiten-Gate einrichten: die nginx-Durchgehung und der Vorschaumodus-zuerst-Rollout.
- Die Aufgabe anpassen: Aufgabentyp, Sprache, Design, Cookie-Name, Callback-Pfad, Pfad-Scope.
- Überblick: das Konzept und das Freigabe-Cookie.
- Statistik: bestätige die Verdrahtung, indem du Aufgabe gegen Durchgang beobachtest.