unmask

docs

JA4 の取得方法、LB / CDN 設定、対応 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 から来るのでこれまでどおり素通りし、何も解かされ ないので検索順位には影響しません

これは 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 フィルタのタブを一度でも保存したことがあるなら、その瞬間に画面に出ていた状態が 設定へ明示的に書き込まれています。そうして固定されたパターンは、以後ホワイトリスト IP タブに 追随しません。両方のタブを開いて意図どおりか確かめてください — UA フィルタのタブでは、 公開 range が現在効いている行が分かるようになっています。

この 2 軸は nginx module でも forward-auth でも同じ配線なので、 導入形態によって結論が変わることはありません。

自分の環境で確かめる

偽の 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 内からリクエストを出すことこそ、 詐称する側にできないことだからです。代わりに確認できるのは 本物のクローラーがちゃんと来ているかで、管理画面の クローラーでクローラー別の内訳が見られます。Search Console の URL 検査で 「公開 URL をテスト」すれば、本物の range から本物の Googlebot が取りに来ます。

nginx module でどちらかの設定を変えたときは、判定が生成済みの nginx 設定に 載っているため、render-nginx と reload をしないと反映されません。 ディスク上の内容が設定より古い場合は unmask doctor が指摘します。