Canvas ブリッジ
canvas と WebGL をリモートの実 GPU で描画し、ページが読み出すピクセルを、レンダーホストが実際に搭載している GPU と整合させます。プロファイルの GPU 文字列もその GPU に合わせてください。実験的な機能で、オプトイン方式です。--canvas-bridge-url を指定しなければ、Clearcote はこれまでどおり完全にローカルで描画します。
この機能がある理由
Clearcote は、ホストマシンが実際に搭載している GPU で canvas/WebGL を描画します。プロファイルがホストとは異なる GPU を名乗っていると、描画されたピクセルを名乗っているハードウェアと照合する厳格なアンチディテクト / ブラウザ改ざんチェックに、その不一致を気づかれる可能性があります。ある GPU に、別の GPU とまったく同じピクセルをソフトウェアで出力させることはできないからです。Canvas ブリッジはこの不一致をなくします。ローカルで描画して GPU の文字列だけを偽装するのではなく、canvas/WebGL の操作を、提示したい GPU を搭載したリモートホストに転送し、そのホストの実際のピクセルを返します。転送するのは操作(事前に記録した画像の固定ライブラリではありません)なので、既知のプローブに限らず、生成されるほとんどの canvas に対応できます。
仕組み
読み出し系の API(getImageData、toDataURL、readPixels、measureText)は、ブリッジホストの本物のピクセルを返します。ブリッジ経由の場合、ローカルのファーブリングによるノイズは適用されません(ブリッジのピクセルが正解値だからです)。通信には、コンパクトなバイナリメッセージのストリームを運ぶ WebSocket を使います。ピクセルは、レンダーブラウザが搭載している GPU から得られます。
clearcote (your automation host) bridge host (real GPU)
+-----------------------------+ +-------------------------+
| page: getImageData / | ops --> | render browser |
| toDataURL / readPixels | | renders on the real GPU,|
| CanvasBridgeClient <-- pixels ---------| reads back the pixels |
+-----------------------------+ +-------------------------+必要なもの
- レンダーホスト:提示したい GPU を搭載した任意のマシン(Windows ペルソナなら Windows の GPU)。その GPU が、プロファイルが提示する canvas のアイデンティティになります。見せたいペルソナに合ったハードウェアを選んでください(NVIDIA として見せるなら NVIDIA のマシン、など)。サーバーの
--backend cdpをそのマシンで動かす通常の Chrome に向けるか(推奨)、Clearcote のバイナリで--backend localを使います。 - 自動化ホストとブリッジホストの間のプライベートなネットワーク経路。ブリッジは平文の WebSocket(
ws://)で通信するため、必ずプライベートネットワークか暗号化トンネル(Tailscale、WireGuard、または SSH ポートフォワーディング)上で運用してください。ブリッジのポートは決してパブリックなインターネットに公開しないでください。
セットアップ
1. レンダーサーバーを起動します(実 GPU ホスト上)。これはヘッドレスブラウザを操作する小さな Python のコーディネーターで、転送された操作を実際の canvas 上で再生します。そのため、返すピクセルはその GPU が生成するものとまったく同じです。レンダーホストの実 GPU が canvas/WebGL のアイデンティティになります。--backend cdp の場合は、起動時にレンダー GPU の renderer 文字列を出力します(render GPU='ANGLE (…)')。手順 3 で使うので控えておいてください。--backend local の場合は、代わりに同じマシン上の通常の Chrome から文字列を読み取ってください。
pip install playwright # one-time (no browser download needed for CDP)
# a regular Chrome on the GPU host, started with --remote-debugging-port=9222
# --user-data-dir=<a separate folder> (Chrome ignores the port on its default profile);
# its CDP URL is webSocketDebuggerUrl from http://127.0.0.1:9222/json/version
python tools/canvas-bridge-server/server.py \
--backend cdp \
--cdp-url ws://127.0.0.1:9222/devtools/browser/... \
--port 8443
# Or let the server launch a Clearcote binary itself:
# python tools/canvas-bridge-server/server.py \
# --backend local \
# --chrome /path/to/clearcote/chrome.exe \
# --port 84432. トンネルを張ります。ws:// は暗号化されていないため、両方のホストを同じ Tailscale/WireGuard ネットワークに参加させるか、SSH でポートをフォワードしてください。サーバーはデフォルトで localhost にバインドするので、Tailscale/WireGuard の場合は --host <that interface's IP> を付けて起動します。以下の SSH の方法なら、そのまま使えます:
ssh -N -L 8443:localhost:8443 user@bridge-host
# the bridge is now reachable at ws://127.0.0.1:84433. クライアントを起動します(自動化に使う Clearcote)。ブリッジを指定し、レンダー GPU の文字列も渡します。renderer はサーバーが出力したとおりに、vendor は Google Inc. (<first name in the renderer>) の形式(例:Google Inc. (Intel))で指定します。ブリッジはピクセルをレンダー GPU と一致させ、これらの値は報告される文字列も一致させます。これらがないと、ペルソナの GPU 名とブリッジ経由のピクセルが食い違います:
--canvas-bridge-url=ws://127.0.0.1:8443 \
--no-sandbox \
--fingerprint=<seed> \
--fingerprint-gpu-vendor='Google Inc. (Intel)' \
--fingerprint-gpu-renderer='ANGLE (Intel, Intel(R) UHD Graphics ... D3D11)'| フラグ | 意味 |
|---|---|
| --canvas-bridge-url | ブリッジのエンドポイント ws://host:port。ブリッジを有効にするには必須です。 |
| --canvas-bridge-auth | 任意。サーバーの前段に認証を置く構成向けの、user:secret 形式の HTTP Basic 認証情報です。リファレンスサーバーはこれを検証しないため、アクセス制御はプライベートネットワークやトンネルに任せてください。 |
| --no-sandbox | 必須。クライアントはレンダラープロセスからブリッジのソケットを開きますが、サンドボックスがこれをブロックするためです。 |
| --fingerprint | ペルソナのシード。 |
| --fingerprint-gpu-vendor / --fingerprint-gpu-renderer | レンダー GPU の文字列。renderer はサーバーが出力したとおりに、vendor は Google Inc. (<first name in the renderer>) の形式で指定します。 |
| --canvas-bridge-mode | オリジンごとのポリシー:off、all(デフォルト)、allow、deny のいずれか。 |
| --canvas-bridge-allow / --canvas-bridge-deny | mode=allow または mode=deny で使う、カンマ区切りの eTLD+1 リスト。 |
| --canvas-bridge-fallback | コールドキャッシュミス時の動作:block(デフォルト)はブリッジを待ちます。local は待たずにローカルのピクセルを返します。 |
SDK から使う
SDK(Node、Python、.NET。現行バージョンは 0.31.1)には、専用の canvasBridge / canvas_bridge / CanvasBridge オプションがあります。ブリッジの URL を設定すると、対応するスイッチが出力され、--no-sandbox も自動で追加されます。同じ許可リストのポリシーを使った完全な起動スクリプトは使用例を参照してください。
const browser = await clearcote.launch({
fingerprint: "user-1",
gpuVendor: "Google Inc. (Intel)", // "Google Inc. (<first name in the renderer>)"
gpuRenderer: "ANGLE (Intel, Intel(R) UHD Graphics ... D3D11)", // exactly as the server printed it
canvasBridge: {
url: "ws://127.0.0.1:8443",
auth: "user:secret",
mode: "allow",
allow: ["example.com"],
fallback: "local",
},
});動作を確認する
- 接続に成功すると、クライアントのログに
canvas-bridge: connected to <host>:<port>と出力されます(表示するには--enable-logging=stderr --v=1を付けて実行します)。 - canvas/WebGL のサーフェスをハッシュ化するページを読み込みます。ブリッジが接続されていれば、ハッシュは自動化ホストではなくブリッジホストの GPU と一致します。手早く確認するには、同じ
canvas.toDataURL()をブリッジありとなしで実行します。結果は異なります。 - ブリッジに到達できない場合、Clearcote は警告をログに出力し、ローカル描画にフォールバックします。ブリッジの設定を誤ってもグレースフルに縮退するだけで、ページが壊れることはありません。
注意点と制限
- canvas のアイデンティティ = シードではなくブリッジホスト。1 台のブリッジホストを共有するプロファイルはすべて、そのホストの canvas/WebGL ハッシュを共有するため、canvas ハッシュで紐付けられます。紐付けられないアイデンティティを多数用意するには、アイデンティティのグループごとにブリッジホスト(GPU)を 1 台用意してください。
- レイテンシ。
fallbackがlocalでない限り、ブリッジのキャッシュにないピクセルの読み出しは、ネットワークの往復を待つブロッキング処理になります(タイムアウトは 5 秒で、その後ローカルにフォールバック)。エンジンは描画のたびに先読みするため、変化していない canvas のピクセルを繰り返し読み出す場合は待ちません。ただしmeasureTextは、呼び出しごとに往復が発生します。ブリッジホストは同じ LAN/データセンター内に置き、レイテンシに敏感で canvas を多用するページではブリッジを使わないでください。 - ブリッジされるのはプロシージャルな WebGL テクスチャです。画像、2D canvas、動画、
ImageBitmap、3D のテクスチャソースを使うと、その canvas はローカル描画にフォールバックします。そのため結果は正しいままですが、ブリッジは経由しません。 - クライアントでは
--no-sandboxが必須で、通信は平文です。必ずトンネルを使い、ブリッジのポートは決して公開しないでください。
実験的機能です。オープンビルドには v0.1.0-pre.12 以降、ライセンスビルドにも含まれています。正式なリファレンス(トラブルシューティング表の完全版を含む)は GitHub の canvas-bridge ガイドを参照してください。ほとんどの構成ではブリッジは不要です。標準のエンジンレベルの制御についてはフィンガープリントフラグを参照してください。