Web Bot Auth は、HTTP メッセージの暗号署名で、リクエストが自動ボットからのものであることを確認する認証方式です。Web Bot Auth は 検証済みボットとエージェント の検証方法として使われます。
IETF のドラフトに依拠します。クローラーが公開鍵を共有するための ディレクトリドラフト ↗ と、これらの鍵でクローラーの身元を HTTP リクエストに付ける方法を定める プロトコルドラフト ↗ です。
このドキュメントでは、Cloudflare での具体的な連携を説明します。
ボットのリクエストを認証するために使う署名鍵を生成します。
-
リクエストの署名に使う、一意な Ed25519 ↗ 秘密鍵を生成します。この例では OpenSSL ↗ の
genpkeyコマンドを使います。openssl genpkey -algorithm ed25519 -out private-key.pem -
公開鍵を取り出します。
openssl pkey -in private-key.pem -pubout -out public-key.pem -
任意のツールで、公開鍵を JSON Web Key(JWK)に変換します。この例では
jwker↗ コマンドラインアプリケーションを使います。go install github.com/jphastings/jwker/cmd/jwker@latest jwker public-key.pem public-key.jwk
この手順で、秘密鍵と公開鍵を生成し、公開鍵を JWK に変換しています。
ボットが Cloudflare へのリクエストを認証できるよう、鍵ディレクトリをホストします。 このディレクトリは draft-meunier-http-message-signatures-directory-03 ↗ の定義に従ってください。
-
/.well-known/http-message-signatures-directoryで鍵ディレクトリをホストします(これは必須です)。この鍵ディレクトリは、署名鍵から導出した公開鍵を含む JSON Web Key Set(JWKS)を返す必要があります。 -
Web ページは HTTP ではなく HTTPS で配信します。
-
Ed25519 公開鍵に対応する base64 URL エンコードの JWK サムプリントを計算 ↗ します。
-
HTTP メッセージ署名の仕様に従い、鍵ディレクトリ内の鍵ごとに 1 つの署名を付けて HTTP レスポンスに署名します。これにより、ほかの者がディレクトリを複製して代わりに登録することを防げます。レスポンスには次のヘッダーが必要です。
Content-Type: このヘッダーの値はapplication/http-message-signatures-directory+jsonにしてください。Signature: 選んだコンポーネントに対してSignatureヘッダー ↗ を構築します。Signature-Input: 選んだコンポーネントに対してSignature-Inputヘッダー ↗ を構築します。ヘッダーは次の要件を満たす必要があります。必須コンポーネント / パラメーター 要件 taghttp-message-signatures-directoryと等しくしてください。keyidディレクトリ内の対応する鍵の JWK サムプリントです。 createdアプリケーションがメッセージを送った時点の Unixタイムスタンプと等しくしてください。expiresCloudflare がメッセージの検証をやめる時点の Unixタイムスタンプと等しくしてください。@authorityリクエストが送った Host ヘッダーの値と等しくしてください。 reqコンポーネントパラメーター ↗ を設定します。
次の例は、
https://example.comに対する、必須ヘッダー付きの注釈付きリクエストとレスポンスです。ここでのSignatureの値は説明用であり、実際に生成された署名ではありません。GET /.well-known/http-message-signatures-directory HTTP/1.1 Host: example.com Accept: application/http-message-signatures-directory+json HTTP/1.1 200 OK Content-Type: application/http-message-signatures-directory+json Signature: sig1=:TD5arhV1ved6xtx63cUIFCMONT248cpDeVUAljLgkdozbjMNpJGr/WAx4PzHj+WeG0xMHQF1BOdFLDsfjdjvBA==: Signature-Input: sig1=("@authority";req);alg="ed25519";keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U";nonce="ZO3/XMEZjrvSnLtAP9M7jK0WGQf3J+pbmQRUpKDhF9/jsNCWqUh2sq+TH4WTX3/GpNoSZUa8eNWMKqxWp2/c2g==";tag="http-message-signatures-directory";created=1750105829;expires=1750105839 Cache-Control: max-age=86400 { "keys": [{ "kty": "OKP", "crv": "Ed25519", "x": "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs", // Base64 URL-encoded public key, with no padding }] }
ディレクトリの検証には、Cloudflare が開発した http-signature-directory CLI ツール ↗ を使えます。
検証済みボットの一覧にボットを追加するには、ボットと鍵ディレクトリを登録します。
- Cloudflare ダッシュボード ↗ にログインし、アカウントとドメインを選びます。
- Manage Account > Configurations を開きます。
- Bot Submission Form タブを開きます。
- Verification Method で Request Signature を選びます。
- Validation Instructions に、鍵ディレクトリの URL を入力します。ボットが送る User-Agent の値(と一致パターン)も追加で指定できます。
- Submit を選びます。
Cloudflare は、鍵ディレクトリ内の有効な Ed25519 鍵をすべて受け入れます。鍵がすでに Cloudflare の登録データベースにある場合は、新しい鍵の提供、または既存鍵のローテーションについて調整します。
検証が成功すると、検証済みリクエストを送れるようになります。
ボットの検証が成功したら、リクエストに署名できます。署名プロトコルは draft-meunier-web-bot-auth-architecture-02 ↗ で定義されています。
署名するコンポーネントの集合を選びます。
コンポーネントは HTTP ヘッダー、または HTTP Message Signatures 仕様の 派生コンポーネント ↗ のいずれかです。Cloudflare は次を推奨します。
- 少なくとも
@authority派生コンポーネントを選んでください。リクエスト先のドメインを表します。たとえばhttps://example.comへのリクエストでは、@authorityはexample.comと解釈されます。 - ASCII 値だけを含むコンポーネントを使ってください。HTTP Message Signatures 仕様は非 ASCII 文字を認めておらず、ボットのリクエスト検証が失敗します。
Cloudflare に登録した公開鍵から、base64 URL エンコードの JWK サムプリントを計算 ↗ します。
Web Bot Auth に必要な 3 つのヘッダーを構築します。
選んだコンポーネントに対して Signature-Input ヘッダー ↗ を構築します。ヘッダーは次の要件を満たす必要があります。
| 必須コンポーネントパラメーター | 要件 |
|---|---|
tag |
web-bot-auth と等しくしてください。 |
keyid |
手順 2 で計算したサムプリントと等しくしてください。 |
created |
アプリケーションがメッセージを送った時点の Unix タイムスタンプと等しくしてください。 |
expires |
Cloudflare がメッセージの検証をやめる時点の Unix タイムスタンプと等しくしてください。短い expires はリプレイ攻撃の可能性を下げます。適切な短寿命の間隔を選ぶことを Cloudflare は推奨します。 |
選んだコンポーネントに対して Signature ヘッダー ↗ を構築します。
鍵ディレクトリを指す Signature-Agent ヘッダー ↗ を構築します。Cloudflare は draft-meunier-http-message-signatures-directory-03 の Signature-Agent 形式を実装しており、ヘッダー値は "https://signature-agent.test" のような構造化文字列です。
次の場合、Cloudflare はメッセージの検証に失敗します。
- メッセージに
https://ではないSignature-Agentヘッダーがある。 - メッセージに有効な URI があるが、二重引用符で囲まれていない。Signature-Agent は構造化フィールドのためです。
- メッセージが後続ドラフトの辞書形式(
sig2="https://signature-agent.test"など)を使っている。 - メッセージに有効な
Signature-Agentヘッダーがあるが、Signature-Inputのコンポーネント一覧に含まれていない。
この 3 つのヘッダーをボットのリクエストに付けます。
リクエストの例は次のとおりです。
Signature-Agent: "https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent")
;created=1735689600
;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"
;alg="ed25519"
;expires=1735693200
;nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg=="
;tag="web-bot-auth"
Signature: sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:サイトに到達するエージェントは、それを作った企業自身が運用していないことが多いです。1 つのプラットフォームが多数のエンドユーザーに代わって自動化を実行できるため、運用者とエンドユーザーは同一ではありません。Cloudflare はこの連鎖(サイト所有者 → ボット運用者 → エンドユーザー)を 推移的信頼(transitive trust) と呼びます。
この連鎖を通じて運用者の身元を運ぶため、Cloudflare は RFC 7239 ↗ で定義された Forwarded ヘッダーを試験しています。IP アドレスに対する X-Forwarded-For と同様です。運用者を許可する設定は、その運用者が直接到達する場合でも、Cloudflare が信頼する中継を経由する場合でも有効です。
運用者は for パラメーターで識別します。
Forwarded: for="openai"ヘッダーには、運用者がアクセスするコンテンツに対して約束する content-use の値も載せられます。
Forwarded: for="openai";use="reference"Cloudflare の Web Bot Auth 実装は、IETF RFC 9421 で定義されたすべてのコンポーネントとパラメーターには対応していません。リクエストの Signature-Input ヘッダーに次のいずれかを含めると、検証は失敗します。
@query-params: 個別パラメーターに署名する代わりに、@queryコンポーネントでクエリ全体に署名することを推奨します。@status: リクエストパスに含めることはできません。
IETF RFC 9421 で定義された次のコンポーネントパラメーターには対応しておらず、含めると Cloudflare はメッセージの検証に失敗します。
sf(HTTP ヘッダーフィールド向け)bs(HTTP ヘッダーフィールド向け)key(HTTP ヘッダーフィールド向け)req(HTTP ヘッダーフィールドまたは派生コンポーネント向け)name(@query-param向け。これには@query-paramの対応が必要です)
メッセージの検証に失敗する場合、原因には次があります。
Signature-Agentヘッダー があり、値が二重引用符で囲まれていることを確認します。Signature-Agentヘッダー が辞書ではなく構造化文字列であることを確認します。Signature-Inputヘッダー のコンポーネント一覧にsignature-agentを含めていることを確認します。expiresタイムスタンプが短すぎて、Cloudflare のサーバーに届くまでに期限切れになっていないことを確認します。1 分で十分なことが多いです。- 非 ASCII 値を含むコンポーネントや、非対応の一覧にあるコンポーネントに署名していないことを確認します。
自分のオリジン処理のために HTTP Message Signatures(Web Bot Auth)を使い、Cloudflare の検証が介入したり cf.bot_management.verified_bot フィールドを設定したりしてほしくない場合は、そのゾーンで Cloudflare の検証機能を無効にできます。
Web Bot Auth の検証を無効にするには、Cloudflare サポート に連絡してください。
この機能を無効にすると、Cloudflare は受信署名を検証しません。検証済みボットは、トラフィックが正当かどうかを判断するため、逆引き DNS 検証などほかの方法にフォールバックします。
次のリソースも参照できます。
- Cloudflare ブログ: Message Signatures are now part of our Verified Bots Program ↗。
- Cloudflare ブログ: Forget IPs: using cryptography to verify bot and agent traffic ↗。
- Cloudflare の Rust 向け
web-bot-authライブラリ ↗。 - Cloudflare の TypeScript 向け
web-bot-authnpm パッケージ ↗。