Facoltativa. Un filtro DNS, un ad blocker o una rete che blocca l'host di Korzen ferma il tag, il suo beacon e la pagina di sfida. Quei visitatori passano comunque, giudicati solo su ciò che invia il tuo server, ma su una route che richiede il token del tag non possono passare. La modalità first-party serve tutti e tre da un percorso del tuo dominio, /kz se non ne scegli un altro, e li inoltra a Bot Protection con l'indirizzo del visitatore. Niente blocca un percorso di un sito senza bloccare il sito.
Ci sono due modi di servire il percorso, e puoi usarli entrambi:
| Il modo | Cosa attivi | Chi serve /kz |
|---|---|---|
| Solo l'SDK | firstParty: true in Node, FirstParty: true in Go | il tuo server |
| Solo il Worker | KORZEN_FIRST_PARTY = "1" e una route per /kz/* | il tuo Cloudflare Worker |
| Il Worker e l'SDK | entrambi, con lo stesso percorso | il Worker; il tuo server gli manda i visitatori sfidati |
In ogni modo, la pagina carica il tag dal tuo percorso invece che dall'host di Korzen. Il tag prende il suo indirizzo dal proprio src, quindi ogni richiesta che fa va anch'essa a /kz:
<script src="/kz/tag.js" data-site-key="YOUR_SITE_KEY" async></script>
La modalità c'è in ogni SDK: Node (e il suo Worker), Go, Python, PHP, Java e .NET, ciascuno con la sua opzione nel README. Un client scritto da una guida di framework non ha un forwarder: lì usa l'SDK o, dietro Cloudflare, il solo Worker, che dà la modalità a un'origine in qualsiasi linguaggio.
Solo l'SDK
Il tuo server serve il percorso. Passa l'opzione al middleware che già interroga Bot Protection, e dai al percorso un handler suo con le stesse opzioni. Il client deve essere creato da createClient, con la tua chiave API: il forwarder la invia a Korzen con ogni richiesta.
// Express, with korzen.js as the Express guide sets it up const options = { client: korzen, ip: (_get, req) => req.ip, firstParty: true }; app.use("/kz", protect(options)); // before any body parser: it answers /kz/... itself app.use(express.urlencoded({ extended: false })); app.post("/signup", protect(options), signup); // Next.js: app/kz/[...path]/route.js serves the path const kz = withKorzen(() => new Response(null, { status: 404 }), { client, ip: ipFrom.vercel, firstParty: true }); export { kz as GET, kz as POST };
o := korzen.Options{IP: korzen.RemoteIP, FirstParty: true} mux.Handle("/kz/", bot.Protect(http.NotFoundHandler(), o)) // the path: Protect answers it itself mux.Handle("POST /signup", bot.Protect(http.HandlerFunc(signup), o))
- Cosa attivi.
firstParty: truesuprotectowithKorzen(attiva solo quando ètrue); in Go,Options.FirstParty. Poi ilsrcdel tag nelle tue pagine diventa/kz/tag.js. L'indirizzo del visitatore si legge come lo legge la decisione: l'opzioneip, in GoOptions.IP. - Un indirizzo che il visitatore non può scrivere. Korzen si fida dell'indirizzo che il forwarder invia con la tua chiave, quindi l'opzione
ipdeve leggerne uno che il visitatore non può impostare:ipFrom.vercelsolo su Vercel,ipFrom.cloudflare(Go:korzen.CloudflareIP) solo se il tuo server riceve traffico solo da Cloudflare,ipFrom.lastForwardeddietro il tuo load balancer o nginx. Un header che il visitatore può scrivere lascia a uno script la scelta dell'indirizzo che Korzen giudica. - Cosa cambia per il visitatore. Niente che veda. Il suo browser carica il tag e invia il beacon al tuo dominio, quindi un visitatore la cui rete blocca Korzen viene giudicato con le prove del tag e può compiere un'azione che richiede il suo token. Le richieste sotto il percorso non vengono mai giudicate e non arrivano mai ai tuoi handler; ogni altro percorso viene giudicato come prima.
- La pagina di sfida. Un caricamento di pagina sfidato va a
/kz/challenge?c=…&r=…sul tuo dominio invece che su quello di Korzen, e il tuo server inoltra la pagina, i suoi file e il suo invio. La stessa sfida, e il visitatore torna alla pagina che aveva chiesto. - Fail-open. Quando Bot Protection è lento, non disponibile o irraggiungibile dal tuo server, ogni richiesta sotto il percorso risponde
503con il corpo vuoto, e il tag lascia perdere quel segnale; la pagina e le altre route non aspettano nulla. Fail-open - Come capire che funziona.
curl -I https://shop.example/kz/tag.jsrisponde200, e il pannello di rete del browser mostra le richieste del tag verso il tuo dominio. Come capire che funziona
Solo il Worker
Il tuo Cloudflare Worker serve il percorso, senza modifiche al tuo server, per un'origine in qualsiasi linguaggio. Configura il Worker come mostra Cloudflare Workers, poi attiva la modalità e aggiungi una route per il percorso:
# wrangler.toml
routes = [
{ pattern = "shop.example/kz/*", zone_name = "shop.example" },
{ pattern = "shop.example/signup*", zone_name = "shop.example" },
]
[vars]
KORZEN_URL = "https://korzen.dev"
KORZEN_FIRST_PARTY = "1"
# KORZEN_FIRST_PARTY_PATH = "/kz" # the path, /kz unless set
- Cosa attivi.
KORZEN_FIRST_PARTYa1otrue(qualsiasi altro valore tranne0ofalsela lascia disattivata, con un avviso nel log del Worker), una route pershop.example/kz/*, e ilsrcdel tag nelle tue pagine come/kz/tag.js. L'indirizzo del visitatore èCF-Connecting-IP, che imposta Cloudflare. - Cosa cambia per il visitatore. Niente che veda. Il tag e il suo beacon vanno al tuo dominio, serviti all'edge di Cloudflare; la tua origine non vede mai quelle richieste. Le route del Worker vengono giudicate come prima.
- La pagina di sfida. Un caricamento di pagina che il Worker sfida va a
/kz/challengesul tuo dominio, che serve il Worker. - Fail-open. Come per l'SDK: un
503con il corpo vuoto solo per quella richiesta, e tutte le altre proseguono verso la tua origine. Fail-open - Come capire che funziona. Come sotto; e
npx wrangler tailelenca le richieste sotto/kz, mentre il log degli accessi della tua origine non ne mostra nessuna. Come capire che funziona
Il Worker e l'SDK
Quando un Worker sta davanti al tuo sito e l'SDK gira nella tua applicazione (per il context che solo la tua applicazione conosce), attiva la modalità in entrambi, con lo stesso percorso.
- Cosa attivi. Il Worker come sopra, con la sua route per
/kz/*, efirstParty: true(Go:FirstParty: true) sull'SDK dietro di esso. Il Worker risponde da sé a/kz/*, quindi l'SDK non vede mai quelle richieste. - Cosa cambia per il visitatore. Lo stesso che con il solo Worker: il tag, il suo beacon e la pagina di sfida arrivano dal tuo dominio, serviti all'edge.
- La pagina di sfida. Il
firstPartydell'SDK manda i visitatori che sfida a/kz/challengeinvece che all'host di Korzen, e il Worker serve quella pagina. Senza, un visitatore che l'SDK sfida va all'host di Korzen, che la sua rete può bloccare. - Fail-open. Chi serve il percorso rinuncia da sé e risponde
503; nessuno trattiene l'altro. Se le route del Worker lasciano fuori/kz/*, o il Worker viene tolto, l'SDK serve il percorso da sé: dietro Cloudflare, dagli alloraip: ipFrom.cloudflare(Go:korzen.CloudflareIP). - Come capire che funziona. Come sotto;
npx wrangler tailelenca le richieste sotto/kz, e il log del tuo server non ne mostra nessuna.
Cosa serve il percorso
Il forwarder, l'SDK o il Worker, risponde a queste e a nient'altro:
| Sul tuo dominio | Cos'è |
|---|---|
GET /kz/tag.js | il tag, con gli header di cache di Korzen |
GET /kz/n, POST /kz/s | il nonce del tag e il suo beacon (un corpo di al massimo 64 KiB) |
GET /kz/ping | risposto 204 dal forwarder stesso, mai inoltrato |
GET e POST /kz/challenge, GET /kz/challenge/wait | la pagina di sfida e il suo invio (al massimo 16 KiB) |
GET /kz/static/… | lo script, lo stile e i font della pagina di sfida |
Qualsiasi altro percorso sotto /kz è un 404, e uno noto con un altro metodo un 405; nessuno dei due arriva a Bot Protection, quindi il percorso non è mai un proxy aperto. A Korzen il forwarder invia gli header del browser da una lista breve (User-Agent, Accept, Accept-Language, Content-Type, Origin, Sec-Fetch-*, i client hint, If-None-Match), la tua chiave API come bearer e l'indirizzo del visitatore. Mai un cookie, l'Authorization del browser o un X-Forwarded-*. Ciò che torna mantiene gli header di cache e di sicurezza di Korzen, mai un Set-Cookie.
Korzen accetta l'indirizzo del visitatore solo da una richiesta su queste route che porta la tua chiave API, e sul beacon solo per la tua site key; tutto il resto viene rifiutato con 403. La tua chiave non arriva mai al browser.
Il cookie _kz del tag e il suo storage restano sul tuo dominio, come prima; i dati che Korzen riceve sono gli stessi. Alcune prove che Korzen legge solo quando il browser si collega direttamente a Korzen mancano attraverso un forwarder; il resto delle prove del tag arriva, e niente di ciò che manca conta contro un visitatore.
Un altro percorso
firstPartyPath (Go: Options.FirstPartyPath; il Worker: KORZEN_FIRST_PARTY_PATH) indica un altro percorso, per esempio quando una lista di blocco impara /kz. Inizia con /, finisce senza, ed è di al massimo 64 caratteri in segmenti di A-Z a-z 0-9 . _ ~ -. Uno che non si legge viene registrato nel log una volta, e la modalità resta disattivata. Usa lo stesso percorso nel src del tag, nell'SDK e nel Worker.
Fail-open
Il percorso non trattiene mai la tua pagina né le altre route:
- Ogni richiesta inoltrata rinuncia da sé: dopo 1 s per un
GET, 2,5 s per unPOST. Un timeout, un errore di rete, una risposta oltre i 4 MiB o un guasto del forwarder è un503con il corpo vuoto eCache-Control: no-store; i redirect non vengono seguiti. I4xxe5xxdi Bot Protection stesso passano così come sono. - Senza l'indirizzo del visitatore (l'opzione
ipnon ne legge nessuno), il nonce, il beacon e la sfida rispondono503; il tag e i file della pagina di sfida vengono comunque serviti. - Il tag lascia allora perdere quel segnale, come quando l'host di Korzen non è disponibile. Un tag che non ha riferito non è mai una prova di un bot: il visitatore viene giudicato su ciò che invia il tuo server.
Come capire che funziona
curl -I https://shop.example/kz/tag.jsrisponde200, ecurl -I https://shop.example/kz/pingrisponde204.- Negli strumenti per sviluppatori del browser, su una pagina con il tag, il pannello di rete mostra
/kz/tag.js,/kz/n,/kz/pinge/kz/ssul tuo dominio, con risposta200o204, e nessuna richiesta all'host di Korzen. - Compi un'azione protetta e poi premi Verifica l'integrazione nella pagina Configurazione: Il token del tag in quella chiamata indica Rilevato. Le tue decisioni compaiono come prima nella pagina Decisioni della dashboard.
- Con una
Content-Security-Policy, l'host di Korzen può uscirne:script-src 'self'; connect-src 'self'; worker-src blob:basta per il tag. Il tag
Errori comuni
- Il tag ancora caricato dall'host di Korzen: la modalità serve il percorso, ma solo il
srcdel tag ci porta il browser. - Un body parser prima del forwarder in Express: il corpo del beacon viene letto prima che il forwarder lo riceva. Montalo prima di qualsiasi parser, o solo sul percorso.
- Il Worker con
KORZEN_FIRST_PARTYma senza route per/kz/*: le richieste arrivano alla tua origine, che risponde404a meno che l'SDK non serva lì il percorso. - Due percorsi: il Worker su uno e l'SDK su un altro. L'SDK manda allora i visitatori sfidati a un percorso che il Worker non serve.
- Chiamare
/v1/decidea mano: il suochallenge.urlè sempre l'host di Korzen. Solo gli SDK e il Worker mandano il visitatore al tuo percorso.