Korzen

ブログ

fail-open:bot チェックでサイトを止めてはいけない理由

bot チェックは最も価値のあるページの手前に置かれます。fail-closed にすると、その障害がそのままあなたの障害になります。状況を良くすることしかできないように呼び出す方法を解説します。

bot チェックは、ログイン、サインアップ、チェックアウトといった最も重要なページに置かれます。だからこそ役に立ち、同時に危険でもあります。すべてのチェックアウトがその応答を待つなら、チェックが遅い日はチェックアウトも遅くなり、チェックが止まった日はあなたのサイトも止まります。

fail-open と fail-closed

チェックが応答できないとき、選択肢は 2 つです。fail-closed は訪問者をブロックします。bot に対しては安全ですが、本当の顧客も全員ブロックされるため、ビジネスにとっては致命的です。fail-open は訪問者を通します。障害の間、bot はチェックを導入する前と同じように入ってきますが、それ以外の誰も気付きません。

ほぼすべてのサイトにとって、fail-open が正解です。bot 対策のない数分間の損失はわずかですが、チェックアウトのない数分間は大きな損失となり、それを目にした人々の信頼も失います。

bot チェックを呼び出すための 4 つのルール

  1. 短い timeout。ページに追加してよい最大の時間、つまり 100〜200 ms を決め、自分のコードで強制してください。プロバイダー側が速いことを当てにしてはいけません。
  2. どんなエラーでも訪問者を通す。timeout、接続エラー、5xx、プランを使い切ったときの 402、解析できないレスポンス。どれも「応答なし」を意味し、応答がなければそのまま進めます。
  3. 確かな応答にだけ対応する。ブロックするのは最も高い bot クラスのときだけです。証拠が弱い場合は、壁ではなく、メールで送るコードのような手間を加えます。
  4. 取りこぼしを記録する。timeout とエラーを数えておけば、障害は謎ではなくグラフになります。

コードではこうなります

const d = await fetch(API + "/v1/decide", {
  method: "POST",
  headers: { Authorization: `Bearer ${KEY}` },
  body: JSON.stringify({ ip, user_agent, token, path }),
  signal: AbortSignal.timeout(150),
}).then((r) => r.json()).catch(() => null);

if (d?.class === "bot_high") return res.status(403).end();
// anything else, including no answer: carry on

ポリシーのすべては catch にあります。何がうまくいかなくても結果は null になり、null が bot と見なされることはありません。

ブラウザ側も fail-open

ページ上のスクリプトも、ページの表示を妨げてはいけません。サービスに到達できない場合でも、ページはスクリプトがないときとまったく同じように動作します。そのときのサーバーの判定は、単に証拠が少なくなるだけです。

Bot Protection の設計

Bot Protection はサイトの手前に置くプロキシではなく、サーバーからの呼び出しです。そのため、あなたがチェックすると決めていないリクエストの経路に入ることはありません。タグは決められた時間だけ待ち、黙って諦めます。利用上限に達すると 402 を返し、コードはそれを他のエラーと同じように扱います。訪問者は流れ続け、その前にあなたにはメールが届きます。