ボット検知の仕組みと、Clearcote がエンジンにパッチを当てる理由
一般的な手法では、navigator.webdriver へのパッチ、WebGL ベンダーの偽装、navigator.plugins の上書きをスクリプトから行います。それでも検知ツールには見抜かれます。その理由は、偽装し損ねたプロパティがまだ 1 つ残っているからではなく、構造的なものです。
JavaScript による偽装は自ら正体を明かす
JS による偽装とは、本来ネイティブ関数があるべき場所に置かれた関数です。検知側は、返された値はいったん脇に置き、その値を返しているものがネイティブかどうかを調べます:
| 手がかり | JS による偽装を見抜ける理由 |
|---|---|
toString による自己露呈 | ネイティブメソッドを文字列化すると function get vendor() { [native code] } になりますが、上書きした関数は自身のソースコードになります。.toString() を 1 回呼ぶだけで見抜けます。 |
ディスクリプタ / hasOwnProperty | getOwnPropertyDescriptor は再定義されたプロパティを露呈させます。また hasOwnProperty('toString') は、ネイティブ関数なら false を返すところ、改ざんされた関数では true を返します。 |
誤った this での TypeError | ネイティブの getter は、誤ったレシーバーで呼ばれると特定の TypeError をスローします。素朴な shim は黙ったままで、その沈黙こそがシグナルになります。 |
| Realm の再取得 | 検知側は、新しい iframe や Web Worker から手付かずの Function.prototype.toString を取得し、それをあなたの getter に適用します。メインワールドのパッチとは別の realm です。返ってくるのはあなたのソースコード。これで見破られます。 |
Clearcote にはそのようなレイヤーがありません。navigator.userAgent の getter は C++ の getter そのものです。[native code] と報告するのは、それが実際にネイティブコードだからであり、メインフレーム、iframe、ワーカーのどの realm でも同一です。検知される JavaScript の乗っ取り自体が存在しません。
ボット検知の 3 つのレイヤー
現代のアンチボットシステムは、構造的に異なる 3 つのサーフェスを、それぞれ別の場所で読み取ります。1 つのツールで 3 つすべてに対処できることはまれです:
| レイヤー | 手がかり | 対処する場所 | Clearcote |
|---|---|---|---|
| A · ドライバ / バイナリ | ChromeDriver の cdc_ 変数、WebDriver プロトコルのサーフェス | CDP を直接使い、chromedriver を使わない | ✅ 素の Chromium バイナリで、ドライバの痕跡なし |
| B · CDP の副作用 | Runtime.enable によるリーク、注入された init スクリプト、メインワールドでの実行、自動化ツール既定のビューポート | 制御 / CDP クライアントのレイヤー | ✅ エンジンが Runtime.enable のリークを無効化し、SDK はデフォルトでスクリプトを注入せず、起動時のデフォルト設定は自動化ツール既定のビューポートを使いません(クライアントが独自のスクリプトをどこで実行するかはクライアント次第です) |
| C · フィンガープリントのサーフェス | canvas、WebGL、オーディオ、フォント、navigator、TLS(メインフレーム、iframe、ワーカーのすべてで) | エンジン(C++)。JS による上書きは自ら正体を明かすため | ✅ これが Clearcote です |
最も重要なこと:偽装と実体の継ぎ目がない
制御がエンジン内にあるため、ページから見える JavaScript も、その下のネットワークハンドシェイクも、1 つの本物の Chromium から来ています。クロスチェックで捕捉されるような「偽装した JS と本物の TLS」の継ぎ目はありません。これはまさに、インジェクション型のツールが見破られる原因となる失敗パターンです。1 つの --fingerprint シードから、canvas、WebGL、オーディオ、フォント、ハードウェアにわたって内部で一貫した 1 台のマシンが生成されます。その下の TLS と HTTP/2 のハンドシェイクはエンジン自身のもので、ペルソナがエンジンの実際のバージョンを報告するため、両者は一致します。この状態を保つには、brandVersion を未設定のままにしてください。
ノイズそのものが手がかりになる場合は、ノイズをオフにします。アイデンティティの偽装は有効なまま、canvas と WebGL は本来の値を返します(レンダリングされたオーディオとクライアント矩形にはどちらの場合もノイズが加わらず、AudioContext のサンプルレート/レイテンシのスカラー値は引き続きペルソナに従います。その理由はこちら):
await launch({ fingerprint: "u1", fingerprintNoise: false }); // identity on, per-site farbling offノイズをオフにすると、同じマシン上のアイデンティティは 1 つの canvas ハッシュを共有します。canvasNoise: false は canvas 2D のノイズだけをオフにし、WebGL のノイズは維持します(ライセンスビルド、150 r12 以降)。
ネットワークとロケールの整合性
ペルソナは全体の半分にすぎません。タイムゾーン、言語、WebRTC のアドレスも、トラフィックの発信元と一致している必要があります。プロキシを使う場合は geoip を指定して起動してください。SDK がプロキシの出口 IP を調べ、その地域に合わせてタイムゾーン、言語リスト、位置情報、WebRTC アドレスを設定します。地域を特定できなければ起動を中止します。指定しない場合、プロキシがどの国にあっても、タイムゾーンは言語に従います(en-US ならニューヨーク)。オプションについては Playwright & Puppeteer を参照してください。
Clearcote が JavaScript を注入するのではなく、C++ エンジンにパッチを当てているのはこのためです。制御できる項目はフィンガープリントフラグを、エンジンがすべてのシグナルの整合性をどう保っているかはアーキテクチャを参照してください。
関連記事