Resep reverse proxy dan kontrak callback
Tiap reverse proxy butuh dua bagian yang sama: sebuah pemeriksaan otorisator yang bertanya ke Caputchin apakah sebuah permintaan membawa pass sah, dan sebuah callback pada origin-mu yang mengubah pass terpecahkan menjadi cookie cpt_gate. Penelusuran nginx menunjukkan bentuknya ujung ke ujung; halaman ini memberi proxy lain, kontrak callback yang tepat, dan contoh Authelia lengkap. Ganti YOUR_SITE_KEY dengan kunci publikmu di mana-mana.
Endpoint-nya sama di mana-mana:
- Otorisator:
GET https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY, dengan headerCookiepengunjung diteruskan.204berarti izinkan,401berarti tantangan. - Tantangan: alihkan peramban ke
https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<URL asli>.
Otorisator hanya menjawab 204 atau 401. Apa pun selainnya, termasuk timeout, berarti Caputchin tak terjangkau, dan apa yang terjadi kemudian adalah mode gagal-mu: memblokir permintaan (fail closed, lebih aman untuk portal login) atau meloloskannya (fail open). Setel pada kunci situs dan cuplikan yang dihasilkan akan cocok. Beri sub-permintaan otorisator timeout pendek agar sebuah gangguan tak bisa menahan tiap permintaan selagi ia memutuskan.
Traefik
Pakai middleware forwardAuth untuk otorisator. Traefik meneruskan header Cookie yang masuk secara default. Pada 401 dari middleware, alihkan peramban ke tantangan (sebuah middleware halaman-galat yang menunjuk rute kecil yang mengeluarkan 302, atau tangani 401 di edge-mu).
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
Pakai forward_auth untuk otorisator dan handle_errors untuk mengubah 401 menjadi pengalihan. Ini titik awal; sesuaikan sintaks direktif untuk versi Caddy-mu.
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
}Callback
Halaman verifikasi terhosting menyelesaikan dengan auto-mengirim sebuah formulir POST ke https://<origin-mu>/__cpt/callback dengan dua field di body: cpt_gate (pass) dan to (ke mana mengirim pengunjung). Jika kamu mengubah jalur callback pada kunci situs, POST-nya pergi ke sana. Tambahkan satu rute ini ke origin-mu (atau sebagai location khusus pada proxy). Ia harus:
- Membaca
cpt_gatedantodari body POST, tak pernah dari URL (pass di URL bocor ke log dan perujuk). - Memastikan
toada di origin-mu sendiri, dan menolak apa pun selainnya, agar callback tak bisa diubah menjadi open redirect. - Men-set cookie dengan atribut di bawah.
- Mengalihkan (
303) keto.
// 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);
});Atribut cookie adalah keseluruhan model keamanan. Karena pass tak terikat ke perangkat, HttpOnly (memblokir pencurian oleh skrip), Secure (hanya HTTPS), SameSite=Lax, dan Max-Age pendek (cocokkan dengan TTL izin lewat-mu) adalah yang melindunginya. Juga: jangan catat nilai cpt_gate di access log-mu, dan pertahankan Referrer-Policy: no-referrer pada callback agar pass tak pernah ikut menumpang di header perujuk.
Mode gagal per proxy
Caputchin tak pernah melihat keputusan mode gagal, jadi ia tak pernah muncul di statistikmu: proxy-mu mengambilnya secara lokal saat tak bisa menjangkau otorisator.
- nginx:
proxy_intercept_errors on;ditambaherror_page 500 502 503 504 = @cpt_unreachable;, dengan location bernama itu berisireturn 403(tertutup) ataureturn 204(terbuka). - Traefik: middleware
forwardAuthgalat pada alamat yang tak terjangkau; rutekan itu ke sebuah service yang mengembalikan403(tertutup), atau lepas middleware dari router di balik sebuah healthcheck (terbuka). - Caddy: perluas
handle_errorsdengan matcher pada5xxyang melakukanrespond 403(tertutup) ataurespond 204(terbuka).
Pelingkupan jalur per proxy
Lindungi hanya jalur ini dan Jangan pernah lindungi jalur ini membentuk konfigurasi yang dihasilkan; yang menegakkannya adalah proxy-mu.
- nginx: satu
location ^~ <awalan>per jalur bergerbang, danauth_request off;di dalam tiap jalur yang dikecualikan. Pola ekstensi seperti*.phpmenjadilocation ~* \.php$. - Traefik: pasang middleware
cpt-gatehanya pada router yang aturannya cocok dengan jalur bergerbang, dan biarkan sisanya tanpa itu. - Caddy: bungkus
forward_authdalam sebuah matcher jalur, misalnya@gated path /admin/* /loginlaluforward_auth @gated ....
Jangan pernah gerbangi sub-permintaan otorisator atau jalur callback-mu.
Contoh terpecahkan: Authelia
Portal login Authelia adalah app mono-halaman terkompilasi tanpa tempat untuk menyisipkan widget dan tanpa hook plugin, jadi gerbang adalah cara melindunginya. Authelia sudah duduk di balik sebuah reverse proxy (begitulah ForwardAuth-nya sendiri bekerja), dan proxy itulah tempat gerbang berada. Authelia sendiri dibiarkan sepenuhnya tanpa modifikasi.
Pasang gerbang pada vhost portal (misalnya auth.example.com):
- Gerbangi HTML portal dan endpoint login faktor-pertama (
/api/firstfactor). - Kecualikan endpoint verify milik ForwardAuth Authelia sendiri (
/api/verify), yang proxy panggil untuk tiap permintaan upstream terlindungi. Menggerbanginya akan merusak tiap app terlindungi di balik Authelia. - Kecualikan health check dan aset statis yang halaman tantangan itu sendiri butuhkan.
- Tambahkan rute
/__cpt/callbackseperti di atas (atau jalur callback yang kamu konfigurasikan).
Keempat butir itu persis yang diungkapkan pengaturan lingkup jalur: / dan /api/firstfactor sebagai jalur bergerbang, /api/verify dan healthcheck-mu sebagai jalur yang dikecualikan.
Gerbang menjauhkan bot dari portal; Regulation bawaan Authelia (batas percobaan ulang dan ban) tetap membatasi percobaan ulang kredensial bagi siapa pun yang lolos, jadi kedua lapisan bertumpuk. Gerbang melindungi hanya portal interaktif (UI login dan persetujuan); ia tak menggerbangi, dan tak seharusnya, endpoint token non-interaktif.
Lihat juga
- Siapkan gerbang halaman proxy: penelusuran nginx dan rollout mode-pratinjau-dulu.
- Sesuaikan tantangan: jenis tantangan, bahasa, tema, nama cookie, jalur callback, lingkup jalur.
- Ikhtisar: konsepnya dan cookie izin lewat.
- Statistik: pastikan penyambungan dengan mengamati tantangan lawan lolos langsung.