0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Expressのボット対策をローカルで検証する:monitorの404とenforceの403

0
Posted at

HTTP 404が返っても、ボット対策のミドルウェアがリクエストを止めたとは限りません。監視モードでは、拒否すべきという判定が付いていても、その後のルートが実行されます。

この記事では、通常のパスと自分で用意したデコイ用パスを比較し、判定結果・HTTPステータス・ルートの実行を分けて確認します。WebDecoyの開発元による技術解説です。文章と翻訳にAIを使用しています。以下のコードとHTTP応答は、公開済みnpmパッケージでローカル検証しました。

通常のリクエストと、monitor・enforceそれぞれのデコイ判定

検証する範囲

  • @webdecoy/express 0.21.0
  • @webdecoy/node 0.21.0
  • ローカル検証時のExpressは4.22.3、Node.jsは26.5.0
  • APIキーを指定せず、ローカルのtripwireルールのみ使用
  • 待ち受けは 127.0.0.1:3000

これは任意のAIボットを識別できるかどうかの精度評価ではありません。自分で送るリクエストによって、指定したパスにルールが一致することと、監視・ブロックの違いを確認する実験です。

1. 公開済みパッケージをインストールする

Node.js 20以降の環境で、空の作業ディレクトリから始めます。

npm init -y
npm install express@4 @webdecoy/express@0.21.0 @webdecoy/node@0.21.0

2. 判定を確認できる小さなアプリを用意する

次を demo.cjs として保存します。

const express = require('express');
const { webdecoy } = require('@webdecoy/express');
const { tripwire } = require('@webdecoy/node');

function createApp(mode = 'monitor') {
  const app = express();
  app.use(webdecoy({
    mode,
    rules: [tripwire({ paths: ['/demo-decoy'], includeDefaults: false })],
  }));
  const decision = (req) => ({
    conclusion: req.webdecoyDecision?.conclusion,
    tripwire: req.webdecoyDecision?.deniedBy('tripwire') ?? false,
  });
  app.get('/', (req, res) => {
    res.json({ message: 'Ordinary route', decision: decision(req) });
  });
  app.get('/demo-decoy', (req, res) => {
    res.status(404).json({
      message: 'Controlled decoy route', decision: decision(req),
    });
  });
  return app;
}

if (require.main === module) {
  const mode = process.env.WEBDECOY_MODE === 'enforce' ? 'enforce' : 'monitor';
  createApp(mode).listen(3000, '127.0.0.1', () => {
    console.log(`Local demo: http://127.0.0.1:3000 (${mode})`);
  });
}
module.exports = { createApp };

起動します。

node demo.cjs

/demo-decoy には実際のファイルや秘密情報を置いていません。このサンプルでは判定を見えるようにするため、レスポンスに判定の要約を含めています。本番では同じ情報をサーバー側のログで扱ってください。

3. monitorで通常パスとデコイを比較する

別のターミナルから実行します。

curl -i http://127.0.0.1:3000/
curl -i http://127.0.0.1:3000/demo-decoy

通常のパスはHTTP 200で、次のJSONを返します。

{"message":"Ordinary route","decision":{"conclusion":"ALLOW","tripwire":false}}

デコイ用パスはHTTP 404で、次のJSONを返します。

{"message":"Controlled decoy route","decision":{"conclusion":"DENY","tripwire":true}}

後者の 404 は、デコイ用ルート自身が返しています。monitor ではミドルウェアが後続処理を止めないため、ルートが実行されます。

ルールに一致した根拠は、HTTPステータスではなく req.webdecoyDecision から取り出した conclusion と deniedBy('tripwire') です。

4. ローカルでenforceを明示的に有効にする

Ctrl+Cでサーバーを停止し、次のように再起動します。

WEBDECOY_MODE=enforce node demo.cjs

同じ2つのリクエストを送ると、結果は次のようになります。

パス monitor enforce
/ HTTP 200、ALLOW HTTP 200、ALLOW
/demo-decoy ルートが実行され、HTTP 404、DENY ルートの実行前にHTTP 403で拒否

環境変数を付けずに再起動すると monitor に戻ります。実際のアプリへの初回導入では、まず監視モードで通常の利用フローを確認してください。

実運用で確認したいこと

  • デコイ用パスを、正当なユーザーが使うパスや実ファイルのパスと重ねない。
  • プレビュー、先読み、監視ツール、許可したスキャナーなどからのアクセスも確認する。
  • User-Agentの変更だけを、悪意の有無や人間であることの証拠にしない。
  • リバースプロキシの手前と奥で観測範囲が異なることを考慮し、trustProxy は実際の構成に合わせる。
  • この構成のローカル判定は、クラウドのダッシュボードへは送信しない。

今回の比較では、両モードの通常リクエストとデコイ用リクエストの計4通りを確認しました。サイト全体の誤検知率、実際の攻撃のブロック率、AIクローラーの網羅性を測定したものではありません。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?