Korzen
Bot Protection

monitor mode と block mode

すべてのアカウントは monitor mode で始まります。Bot Protection が何を止めるかを確認してから block mode をオンにし、クラスごとのアクションを選びます。

Bot Protection が自分から何かを実行することはありません。応答された action を適用するのはお客様のサーバーです。そのアクションが何になるかを決めるのがモードです。

monitor mode

新しいアカウントはすべてここから始まります。応答の action は常に allow なので誰も止められず、intended_action に block mode だった場合のアクションが入ります。dashboard の概要には、block mode だったらブロックやチャレンジの対象になっていた判定の件数が表示されます。呼び出しを組み込んで deploy し、数日間様子を見てください。

block mode

block mode は、ドメインのいずれかが保護されてから有効にできます。ページの訪問者についてお客様のサーバーが bot ではないと判定される最初の判定でドメインが追加され、challenge ページは訪問者を保護中のドメインにしか戻しません。block mode がオンの間は、最後の保護中ドメインを削除できません。ご自身のマシンでは、タグが localhost のページで動いた時点で有効にできます。その場合、ドメインのいずれかが保護されるまで、challenge ページはそのマシン上の訪問者だけを戻します。Set-up ページでドメインを手動で追加することもできます。

セットアップページの「モード」カードでオンにすると、次のリクエストから有効になります。以降の action は、訪問者のクラスに設定したアクションになります。

クラスデフォルトのアクション意味
human highallow人間。セッション外からの証拠あり
humanallowお客様自身のフィードバックで人間と裏付けられた訪問者
unknownallowどちらとも言える証拠が足りない。初回訪問の大半
botchallengeクライアントの挙動から見た自動化
bot highblock強い証拠のある自動化

各クラスのアクションは同じカードで変更できます。monitor mode に戻すのも同じくすぐにできます。

各アクションに対してコードがすべきこと

  • allow:Bot Protection がない場合と同じように処理を続けます。
  • challenge:続ける前に追加の確認を求めます。CAPTCHA、メールや電話による確認、時間のかかる手順などです。何もなければそのまま続けます。
  • block:操作を拒否します。新規登録が失敗したときと同じメッセージを返し、bot に何も悟らせないようにします。

block mode がページの読み込みを止めることはありません。Bot Protection が判定するのは、お客様のサーバーが問い合わせる操作(新規登録、ログイン、checkout)だけです。block された bot にもサイトは見えますが、その操作を完了することはできません。

チャレンジページ

独自の確認手段がなければ、challenge となった訪問者を Korzen のチャレンジページに送ってください。block mode では、action が challenge の回答に challenge.url が含まれます。&r= と戻り先のアドレス(お客様のドメインのいずれか)を付けて、ブラウザをそこへリダイレクトしてください。ページはブラウザに小さな proof of work を解かせ(長くても数秒)、kz_token を付けてそのアドレスへ戻します。middleware はその token を _kz cookie に保存し、以後 30 分間、そのセッションの challenge は allow になり、challenge.passed は true になります。

SDK がこれを代わりに行います。onChallenge を指定しないページ読み込み(GET)では、protect、withKorzen、Go の Protect が訪問者をそこへ送り、戻ってきたときに kz_token を保存して、それを外した同じアドレスへ送ります。token を受け取るのは自分がページへ送ったブラウザからだけなので、他人の token を含むリンクでは何も仕込めません。challenge となったフォームの送信や API の呼び出しは 403 で拒否されます。フォームを表示するページで challenge すれば、その通過によって送信が通ります。独自の hook からは challengeRedirect(d, returnTo)(Go では korzen.SendToChallenge)で訪問者を送ってください。同じようにブラウザに印を付けます。戻り先のアドレスは訪問者が開いたアドレスで、プロキシが X-Forwarded-Host と X-Forwarded-Proto を付けていればそのホストとスキームを、付けていなければ Host のものを使います。nginx の既定のように Host: localhost を転送し、どちらも付けないプロキシの後ろでは、publicURL(Go では PublicURL)にサイトのオリジン(https://shop.example など)を指定してください。ページが訪問者を localhost へ戻すのは、タグも訪問者のページを localhost 上で見ていて、判定の IP が loopback かプライベートアドレス(自分のマシンの Docker で動くアプリにはブリッジのアドレス、たとえば 172.17.0.1 が見えます)だったときだけです。プロキシの背後では訪問者のページはあなたのドメイン上にあるので、ページが訪問者を localhost へ送ることはありません。

JavaScript のないブラウザは、代わりに待ちます。数秒(難しいパズルほど長く)待つと、ページは自動で進み、同じ通過を与えます。ページを飛ばして戻る方法はありません。proof of work や待ち時間は自動化されたセッションのそれぞれに登録の代価を払わせますが、それだけでは本気のボットは止まりません。

タグを必要とするアクション

ブラウザを真似て、リクエストごとに新しいアドレスから送るスクリプトは、あなたのページを一度も実行しません。そのため、広告ブロッカーがタグを止めている人と同じく bot ではなく unknown になります。キューへの参加、登録、checkout など、それでは足りないアクションでは、判定に "require_token": true を付けて送ってください(SDK の requireToken オプション、Go では RequireToken)。タグの有効な token がなければ、クラスにかかわらず答えは challenge で、token_required が true になります。クラス自体は変わらず、monitor mode では intended_action になります。token がそのアクションを通せるのは、セッションごとに 1 時間に 1 回です。token を使うのはフォームの送信で、フォームを表示するページの読み込みでは使われません。2 分以内の 3 回までの試行(カードの拒否、入力ミス)は同じ試行として扱われ、それより後の利用は token がないものとして答えられます。つまり、1 つのブラウザがキューの 1 つの場所です。SDK のオプションは送信のときだけそれを送ります。

このようなアクションからチャレンジページに送られた訪問者には、JavaScript なしの待機はありません。ページは proof of work と、そのページで私たちのタグが動くことを求め、それがアクション用の新しい token を与えます。私たちのタグを実行せずに proof of work だけを解くスクリプトは通れません。JavaScript を切っている人は通れないので、require_token は必要なアクションにだけ送ってください。challenge のフォーム送信は SDK の 403 を受けます。代わりに訪問者をページへ送るには、onChallenge から challengeRedirect(d, returnTo) でフォームのページに向けて送ってください(Go では korzen.SendToChallenge)。Bot Protection が止まっているか遅いときも、あなたのサーバーは訪問者を通します。

require_token は、本当の訪問なしにアクションを取るコストを上げます。訪問者のブラウザーはあなたのページ(またはチャレンジページ)で私たちのタグを実行し、そのブラウザーとネットワークに結び付いた、一度だけ使える token を得る必要があります。これは CAPTCHA でも人間である証明でもありません。ブラウザーをまねる資金力のあるボットは、時間とコストをかければ token を得られます。そうしたセッションも、私たちの分類とファーム検出がほかのセッションと同じように判断します。

一時停止

セットアップページの保護スイッチを使えば、deploy せずにすべてを一時停止できます。応答はすべて allow になり、何も記録・課金されません。