Korzen
Bot Protection
In dieser Dokumentation

First-Party-Modus

Der Tag, sein Beacon und die Challenge-Seite von Ihrer eigenen Domain, über ein SDK, einen Cloudflare Worker oder beide, für Besucher, deren Netz Korzen blockiert.

Optional. Ein DNS-Filter, ein Werbeblocker oder ein Netz, das den Host von Korzen blockiert, stoppt den Tag, seinen Beacon und die Challenge-Seite. Diese Besucher kommen weiterhin durch, beurteilt nur nach dem, was Ihr Server sendet, aber auf einer Route, die das Token des Tags verlangt, kommen sie nicht weiter. Der First-Party-Modus liefert alle drei unter einem Pfad Ihrer eigenen Domain aus, /kz, solange Sie keinen anderen wählen, und leitet sie mit der Adresse des Besuchers an Bot Protection weiter. Nichts blockiert einen Pfad einer Website, ohne die Website zu blockieren.

Es gibt zwei Wege, den Pfad auszuliefern, und Sie können beide nutzen:

Der WegWas Sie einschaltenWer /kz ausliefert
Nur das SDKfirstParty: true in Node, FirstParty: true in GoIhr Server
Nur der WorkerKORZEN_FIRST_PARTY = "1" und eine Route für /kz/*Ihr Cloudflare Worker
Worker und SDKbeides, mit demselben Pfadder Worker; Ihr Server schickt herausgeforderte Besucher zu ihm

Auf jedem Weg lädt die Seite den Tag von Ihrem Pfad statt vom Host von Korzen. Der Tag nimmt seine Adresse aus seinem eigenen src, also geht auch jede Anfrage, die er stellt, an /kz:

<script src="/kz/tag.js" data-site-key="YOUR_SITE_KEY" async></script>

Den Modus gibt es in jedem SDK: Node (und seinem Worker), Go, Python, PHP, Java und .NET, jeweils mit der Option in der README. Ein nach einem Framework-Leitfaden geschriebener Client hat keinen Forwarder: Nehmen Sie dort das SDK oder, hinter Cloudflare, den Worker allein, der den Modus einem Origin in jeder Sprache gibt.

Nur das SDK

Ihr Server liefert den Pfad aus. Geben Sie der Middleware, die Bot Protection schon fragt, die Option, und geben Sie dem Pfad einen eigenen Handler mit denselben Optionen. Der Client muss mit createClient erstellt sein, mit Ihrem API-Schlüssel: der Forwarder sendet ihn mit jeder Anfrage an Korzen.

// 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))
  • Was Sie einschalten. firstParty: true bei protect oder withKorzen (an nur, wenn es true ist); in Go Options.FirstParty. Dann wird der src des Tags auf Ihren Seiten zu /kz/tag.js. Die Adresse des Besuchers wird gelesen, wie die Entscheidung sie liest: die Option ip, in Go Options.IP.
  • Eine Adresse, die der Besucher nicht schreiben kann. Korzen vertraut der Adresse, die der Forwarder mit Ihrem Schlüssel sendet, also muss die Option ip eine lesen, die der Besucher nicht setzen kann: ipFrom.vercel nur auf Vercel, ipFrom.cloudflare (Go: korzen.CloudflareIP) nur, wenn Ihr Server Traffic ausschließlich von Cloudflare annimmt, ipFrom.lastForwarded hinter Ihrem eigenen Load Balancer oder nginx. Ein Header, den der Besucher schreiben kann, lässt ein Skript die Adresse wählen, die Korzen beurteilt.
  • Was sich für den Besucher ändert. Nichts, was er sieht. Sein Browser lädt den Tag und sendet seinen Beacon an Ihre Domain, also wird ein Besucher, dessen Netz Korzen blockiert, mit den Belegen des Tags beurteilt und kann eine Aktion ausführen, die dessen Token verlangt. Anfragen unter dem Pfad werden nie beurteilt und erreichen nie Ihre Handler; jeder andere Pfad wird beurteilt wie bisher.
  • Die Challenge-Seite. Ein herausgeforderter Seitenaufruf geht an /kz/challenge?c=…&r=… auf Ihrer Domain statt auf der von Korzen, und Ihr Server leitet die Seite, ihre Dateien und ihr Absenden weiter. Dieselbe Aufgabe, und der Besucher kommt zu der Seite zurück, die er aufgerufen hat.
  • Fail-open. Ist Bot Protection langsam, ausgefallen oder von Ihrem Server aus nicht erreichbar, antwortet jede Anfrage unter dem Pfad mit 503 und leerem Body, und der Tag verwirft dieses Signal; die Seite und Ihre anderen Routen warten auf nichts. Fail-open
  • Woran Sie erkennen, dass es läuft. curl -I https://shop.example/kz/tag.js antwortet 200, und das Netzwerk-Panel des Browsers zeigt die Anfragen des Tags an Ihre eigene Domain. Woran Sie erkennen, dass es läuft

Nur der Worker

Ihr Cloudflare Worker liefert den Pfad aus, ohne Änderung an Ihrem Server, für einen Origin in jeder Sprache. Richten Sie den Worker ein, wie Cloudflare Workers zeigt, schalten Sie dann den Modus ein und ergänzen Sie eine Route für den Pfad:

# 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
  • Was Sie einschalten. KORZEN_FIRST_PARTY auf 1 oder true (jeder andere Wert außer 0 oder false lässt ihn aus, mit einer Warnung im Log des Workers), eine Route für shop.example/kz/* und den src des Tags auf Ihren Seiten als /kz/tag.js. Die Adresse des Besuchers ist CF-Connecting-IP, die Cloudflare setzt.
  • Was sich für den Besucher ändert. Nichts, was er sieht. Der Tag und sein Beacon gehen an Ihre Domain und werden am Edge von Cloudflare beantwortet; Ihr Origin sieht diese Anfragen nie. Die Routen des Workers werden beurteilt wie bisher.
  • Die Challenge-Seite. Ein Seitenaufruf, den der Worker herausfordert, geht an /kz/challenge auf Ihrer Domain, die der Worker ausliefert.
  • Fail-open. Wie beim SDK: ein 503 mit leerem Body nur für diese Anfrage, und alle anderen gehen weiter an Ihren Origin. Fail-open
  • Woran Sie erkennen, dass es läuft. Wie unten; dazu listet npx wrangler tail die Anfragen unter /kz, während das Zugriffslog Ihres Origins keine davon zeigt. Woran Sie erkennen, dass es läuft

Worker und SDK

Steht ein Worker vor Ihrer Website und läuft das SDK in Ihrer Anwendung (für den context, den nur Ihre Anwendung kennt), schalten Sie den Modus in beiden ein, mit demselben Pfad.

  • Was Sie einschalten. Den Worker wie oben, mit seiner Route für /kz/*, und firstParty: true (Go: FirstParty: true) im SDK dahinter. Der Worker beantwortet /kz/* selbst, also sieht das SDK diese Anfragen nie.
  • Was sich für den Besucher ändert. Dasselbe wie mit dem Worker allein: der Tag, sein Beacon und die Challenge-Seite kommen von Ihrer Domain und werden am Edge beantwortet.
  • Die Challenge-Seite. Das firstParty des SDK schickt die Besucher, die es herausfordert, an /kz/challenge statt an den Host von Korzen, und der Worker liefert diese Seite aus. Ohne es geht ein vom SDK herausgeforderter Besucher an den Host von Korzen, den sein Netz blockieren kann.
  • Fail-open. Wer den Pfad ausliefert, gibt selbst auf und antwortet 503; keiner hält den anderen auf. Lassen die Routen des Workers /kz/* aus oder fällt der Worker weg, liefert das SDK den Pfad selbst aus: hinter Cloudflare geben Sie ihm dann ip: ipFrom.cloudflare (Go: korzen.CloudflareIP).
  • Woran Sie erkennen, dass es läuft. Wie unten; npx wrangler tail listet die Anfragen unter /kz, und das Log Ihres Servers zeigt keine davon.

Was der Pfad ausliefert

Der Forwarder, das SDK oder der Worker, beantwortet diese und sonst nichts:

Auf Ihrer DomainWas es ist
GET /kz/tag.jsder Tag, mit den Cache-Headern von Korzen
GET /kz/n, POST /kz/sdie Nonce des Tags und sein Beacon (ein Body von höchstens 64 KiB)
GET /kz/pingvom Forwarder selbst mit 204 beantwortet, nie weitergeleitet
GET und POST /kz/challenge, GET /kz/challenge/waitdie Challenge-Seite und ihr Absenden (höchstens 16 KiB)
GET /kz/static/…Skript, Stil und Schriften der Challenge-Seite

Jeder andere Pfad unter /kz ist ein 404, ein bekannter mit einer anderen Methode ein 405; keiner erreicht Bot Protection, also ist der Pfad nie ein offener Proxy. An Korzen sendet der Forwarder die eigenen Header des Browsers von einer kurzen Liste (User-Agent, Accept, Accept-Language, Content-Type, Origin, Sec-Fetch-*, die Client Hints, If-None-Match), Ihren API-Schlüssel als Bearer und die Adresse des Besuchers. Nie ein Cookie, den Authorization-Header des Browsers oder ein X-Forwarded-*. Was zurückkommt, behält die Cache- und Sicherheits-Header von Korzen, nie ein Set-Cookie.

Korzen nimmt die Adresse des Besuchers nur aus einer Anfrage auf diesen Routen an, die Ihren API-Schlüssel trägt, und beim Beacon nur für Ihren eigenen Site Key; alles andere wird mit 403 abgelehnt. Ihr Schlüssel erreicht nie den Browser.

Das Cookie _kz des Tags und sein Speicher bleiben auf Ihrer Domain, wie bisher; die Daten, die Korzen erhält, sind dieselben. Einige Belege, die Korzen nur liest, wenn der Browser sich direkt mit Korzen verbindet, fehlen über einen Forwarder; die übrigen Belege des Tags kommen an, und nichts von dem, was fehlt, spricht gegen einen Besucher.

Ein anderer Pfad

firstPartyPath (Go: Options.FirstPartyPath; der Worker: KORZEN_FIRST_PARTY_PATH) nennt einen anderen Pfad, etwa sobald eine Sperrliste /kz lernt. Er beginnt mit /, endet ohne, und hat höchstens 64 Zeichen in Segmenten aus A-Z a-z 0-9 . _ ~ -. Einer, der sich nicht lesen lässt, wird einmal geloggt, und der Modus bleibt aus. Verwenden Sie denselben Pfad im src des Tags, im SDK und im Worker.

Fail-open

Der Pfad hält nie Ihre Seite oder Ihre anderen Routen auf:

  • Jede weitergeleitete Anfrage gibt selbst auf: nach 1 s bei einem GET, nach 2,5 s bei einem POST. Ein Timeout, ein Netzwerkfehler, eine Antwort über 4 MiB oder ein Fehler im Forwarder ist ein 503 mit leerem Body und Cache-Control: no-store; Weiterleitungen werden nicht verfolgt. Die eigenen 4xx und 5xx von Bot Protection gehen unverändert durch.
  • Ohne die Adresse des Besuchers (die Option ip liest keine) antworten Nonce, Beacon und Challenge mit 503; der Tag und die Dateien der Challenge-Seite werden weiter ausgeliefert.
  • Der Tag verwirft dann dieses Signal, wie wenn der Host von Korzen ausgefallen ist. Ein Tag, der nicht berichtet hat, ist nie ein Beleg für einen Bot: der Besucher wird nach dem beurteilt, was Ihr Server sendet.

Woran Sie erkennen, dass es läuft

  • curl -I https://shop.example/kz/tag.js antwortet 200, und curl -I https://shop.example/kz/ping antwortet 204.
  • In den Entwicklertools des Browsers zeigt das Netzwerk-Panel auf einer Seite mit dem Tag /kz/tag.js, /kz/n, /kz/ping und /kz/s von Ihrer eigenen Domain, beantwortet mit 200 oder 204, und keine Anfrage an den Host von Korzen.
  • Führen Sie eine geschützte Aktion aus und klicken Sie dann auf der Einrichtungsseite auf Integration prüfen: Das Token des Tags in diesem Aufruf zeigt Erkannt. Ihre Entscheidungen erscheinen wie bisher auf der Seite Entscheidungen des Dashboards.
  • Mit einer Content-Security-Policy kann der Host von Korzen daraus verschwinden: script-src 'self'; connect-src 'self'; worker-src blob: genügt für den Tag. Der Tag

Häufige Fehler

  • Der Tag lädt noch vom Host von Korzen: der Modus liefert den Pfad aus, aber nur der src des Tags schickt den Browser dorthin.
  • Ein Body-Parser vor dem Forwarder in Express: der Body des Beacons wird gelesen, bevor der Forwarder ihn bekommt. Binden Sie ihn vor jedem Parser ein oder nur auf dem Pfad.
  • Der Worker mit KORZEN_FIRST_PARTY, aber ohne Route für /kz/*: die Anfragen erreichen Ihren Origin, der mit 404 antwortet, außer das SDK liefert den Pfad dort aus.
  • Zwei Pfade: der Worker auf dem einen, das SDK auf einem anderen. Das SDK schickt herausgeforderte Besucher dann an einen Pfad, den der Worker nicht ausliefert.
  • /v1/decide von Hand aufrufen: seine challenge.url ist immer der Host von Korzen. Nur die SDKs und der Worker schicken den Besucher an Ihren Pfad.