Overview
JA4 と LB / CDN
クローラー偽装対策
advisor
対応 distro
バックアップ・復旧
FAQ
UA は名札であって、身分証ではない
bot 対策を入れると、必ず検索エンジンの例外が要ります。Googlebot を止めたい人はいません。そして例外の
書き方として真っ先に思いつくのが UA 文字列での判定ですが、これは筋が悪い。
UA は名乗る側が自由に決められる からです。攻撃はこれだけで済みます。
curl -A 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' https://example.com/
UA のホワイトリストは、合言葉が表に書いてあるドアです。しかも
信頼されているクローラーほど、名前を借りる価値が高い 。
通したい相手ほど詐称の圧力が強いという、逆向きの構造になっています。
救いは、その圧力が解決策を生んだことです。詐称する価値のあるクローラーを持つベンダー
— Google、Microsoft、OpenAI、Apple など — は
クローラーが実際にどの IP range から来るかを公開しています 。機械可読な JSON で、
更新も続いています。これで身元は、名乗る側が選べないものになります。
unmask の判定
unmask は公開された range を preset として同梱し、名前ではなくアドレスで照合します 。
関係する設定は 2 つで、それぞれが別々の救済経路を持っている と捉えると分かりやすい。
設定
場所
働き
公式 IP range の preset
設定 → ホワイトリスト IP
公開されているリスト 1 本につき preset 1 つ。既定で全部 ON なので、入れた直後から本物のクローラーをアドレスで見分けます。
IP range で検証できる bot は UA を見ず IP だけで判定する
設定 → UA フィルタ
全体方針にあたるスイッチ。公開 range のあるパターンについては UA 文字列が通行証として一切効かなくなり、range 内のアドレスだけが通ります。既定 ON。
どちらも出荷時のままなら、レンタル VPS から来る Googlebot/2.1 は
検索エンジンではありません 。ただの正体不明のクライアントとして、通常の challenge に
当たります。本物の Googlebot は Google の公開 range から来るのでこれまでどおり素通りし、何も解かされ
ないので検索順位には影響しません 。
公開 range の無い クローラーは、UA 文字列の名乗りだけで通ります。その名乗りは誰でも書けるので、
名乗りで得られるものはあえて小さくしてあります。免除されるのはブラウザが受ける challenge だけで、それ以外は
誰とも同じ扱いです。踏んだ honeypot、コミュニティの BAN 一覧、国・ネットワーク・カスタムルール、保護パス、deny、
そしてレート制限はすべて効きます。名乗りが効くのは GET と HEAD だけで、IP ごとの上限 (設定 →
UA フィルタ 、既定 30 件/分) を超えると CAPTCHA になります。各クローラーの「詳細」には直近
24 時間に名乗りだけで通した件数と送信元 IP 数が出るので、悪用されている名前は「通常判定」か「止める」に
切り替えられます。
SNS のリンクプレビューの取得も名乗りクローラーで、しかも海外から来ます。そのため、世界中のスクレイパー向けに
書いた国ルールは、プレビューの取得も一緒に止めてしまいます (気付くのは画像の出ない投稿が 1 日分たまってから)。
そこで X・Facebook・LINE の取得は、名乗りと送信元のネットワーク (AS13414・AS32934・AS38631。各社自身の AS で、
他者は送信元にできない) の組でも確かめます。両方が合った取得は国・ASN のルールだけ免除され、カスタムルール・
保護パス・honeypot・レート制限は効いたままです。ASN の mmdb (設定 → ネットワーク ) が
要ります。mmdb が無い場合や、クラウドから来る取得 (Slack・Discord など) については、国タブがルールの編集中に
「直近 1 日の通信からみて止まる取得」を示し、止まり始めると通知一覧に出ます。
これは rDNS 方式ではありません。 Googlebot の検証方法として古くから知られているのは
逆引き DNS と正引きの突き合わせです。有効な手ですが、リクエスト経路に DNS の往復が挟まります。
メモリ上の prefix リストとの照合ならリクエストあたりのコストはゼロなので、unmask はリストを同梱する
側を採っています。
この方式で検証できるクローラー
以下のベンダーは機械可読な range を公開しているため、アドレスで身元を判定できます。
ベンダー
対象
Google
Googlebot と Google 名義の fetcher 全般 — Image / News / Video、AdsBot、Mediapartners、Inspection Tool、Google-Extended、Read-Aloud、Site-Verification。公開リストは 3 本に分かれていますが、Google が製品をファイル間で移すため unmask は 3 本の和集合で照合します。
Microsoft
bingbot、BingPreview
OpenAI
GPTBot、OAI-SearchBot、ChatGPT-User — 製品ごとに別リスト
Anthropic (v0.1.30+)
ClaudeBot、Claude-User、Claude-SearchBot — 全 crawler 共通の 1 リストです。Anthropic は長らく range を公開していませんでしたが、公開が始まったため対応しました。旧名の Claude-Web / anthropic-ai も意図的に対象です。
Perplexity
PerplexityBot、Perplexity-User
DuckDuckGo
DuckDuckBot、DuckAssistBot
Apple
Applebot、Applebot-Extended
Amazon
Amazonbot
終了した製品の名前も、あえて対象に含めています。 Google Web Preview のような
すでに実トラフィックのない名前を UA 判定のまま残すと、通るのは詐称だけになります。
「Googlebot は検証しているのに Google Favicon は素通り」では防御になりません。ベンダー名義の
パターンが 1 つ開いていれば、そこが穴です。
range を公開していないクローラー — 中小の検索エンジン、フィードリーダー、
リンクプレビュー、自社の監視 bot など — は UA 文字列でしか見分けられないので、そちらが救済
経路として残ります。これは回避のしようがありません。どこから来るかを公開していない相手は、
本物と偽物を区別できないからです。通す価値があるかどうかで判断し、不要なものは 設定 →
UA フィルタ の各グループの「詳細」で「通常判定」か「止める」にしてください。
1 つだけ確認しておくとよいこと
2 つの設定は噛み合っている必要があります。そして両者の間には意図的な非対称があるので、
どちらかを変える前に知っておく価値があります。
range の preset を OFF にすると、そのベンダーについては UA 判定が復活します。
これは手落ちではなく安全側の設計です。preset を切ったときに UA 救済も落としてしまうと、
本物のクローラーに通る道が 1 本も残らず、Googlebot を止めることになります。だから unmask は
「UA も拒否、range も OFF」という状態には決して落ちません。裏を返すと、
preset を 1 つ切ると、この方針が消したはずの詐称可能な状態が黙って戻ります 。
UA フィルタのタブで「通す」にしたクローラーが例外を作ることはありません。 スイッチが ON の間は、
range preset が有効なパターンは「通す」にしていてもアドレスで判定されます。
UA 文字列でも通るようになるのは、スイッチを OFF にしたときだけです。確認すべきなのは preset の側です。
UA フィルタのタブでは range を持つ各行に 🛡 バッジが付き、公開 range がいまホワイトリスト IP タブで
有効なら緑になります。緑でない行は、UA 文字列で通る状態に戻っているベンダーです。
この 2 軸は、ホストの nginx module でも gateway コンテナでも同じように働くので、
導入形態によって結論が変わることはありません。
自分の環境で確かめる
偽の Googlebot を自分で送ってみるのが早いです。ベンダーの range 外にあるマシンなら何でも構いません
— 手元のノート PC でも VPS でも。unmask が保護しているパスを叩きます。
curl -sS -o /dev/null -w '%{http_code}\n' \
-A 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' \
https://your-site/<保護しているパス>
challenge ページを伴う 403 が正解です。名前は無視され、アドレスで判定された、ということです。200 が返る場合はそのパターンがまだ UA 文字列で救済されているので、
上の 2 つの設定を確認してください。
逆方向は外からは試せません。そこが肝で、Google の公開 range 内からリクエストを出すことこそ、
詐称する側にできないことだからです。代わりに確認できるのは
本物のクローラーがちゃんと来ているか です。管理画面の
AI / crawler traffic カード (ダッシュボードと統計ページ) でクローラーの分類別の内訳が見られ、
分類を開くと個々のクローラーが並び、アドレスで検証済みのものには 🛡 が付きます。Search Console の URL 検査で
「公開 URL をテスト」すれば、本物の range から本物の Googlebot が取りに来ます。
nginx module でどちらかの設定を変えたときは、 判定が生成済みの nginx 設定に
載っていることに注意してください。タブを保存するとその場で render し直されますが、動いている nginx は
reload するまで前の render のままです (nginx -t の後に reload。gateway コンテナは自動で reload します)。
nginx が古い render のまま動いているときと、render 済みのファイルが config.yml と食い違っているとき
(手で編集した後は unmask render-nginx を実行) は、unmask doctor が警告します。