uBlock Origin、`ipaddress=` オプションを反映して CNAME uncloaking コードを修正
(github.com/gorhill)- uBlock Origin のコミットでは、Firefox のネットワーク処理における CNAME uncloaking のフローを書き直し、DNS 参照で得た IP を
details.ipに反映するように変更 - 既存の
cnamesMap キャッシュはなくなり、dnsList、dnsDict、dnsWritePtrベースの 256 件リングバッファ と60000msTTL キャッシュに置き換え - DNS 参照には
browser.dns.resolve(hn, [ 'canonical_name' ])を使用し、結果のcanonicalNameとaddresses[0]をそれぞれ CNAME と IP として利用 - CNAME 例外処理は 1st-party、ignore list、root document 条件を維持し、IPv4 アドレスや
[で始まるホスト名は 再参照の対象外 とする - Chromium の最小バージョンは
80.0、Opera の最小バージョンは67.0に引き上げられ、隠し設定のcnameMaxTTLデフォルト値は削除
Firefox DNS キャッシュ構造の再設計
platform/firefox/vapi-background-ext.jsの CNAME uncloaking 関連コードが、グローバル Map 中心の構造からクラス内部の DNS キャッシュ 構造に変更- 既存の
cnameUncloakEnabledグローバル状態とcnamesMap の代わりに、次のフィールドでキャッシュを管理dnsList: リングバッファdnsWritePtr: 次の書き込み位置dnsMaxCount: 最大256dnsDict: ホスト名からリングバッファインデックスへのマッピングdnsEntryTTL:60000ms
- コンストラクタでは
canUncloakCnamesとcnameUncloakEnabledがtrueで初期化
リクエスト処理フロー
onBeforeSuspendableRequest(details)はリクエスト URL からホスト名を取り出した後、まずdnsFromCache(hn)でキャッシュを確認- キャッシュされた DNS 項目に
ipがあれば、details.ipに設定 - 基本の
super.onBeforeSuspendableRequest(details)呼び出し結果がキャンセルやリダイレクトなどで終了した場合、その結果をそのまま返却 - キャッシュされた DNS 項目が
Promiseでなければ、onAfterDNSResolution(hn, details, dnsEntry)で後続処理を継続 - DNS 再参照条件を満たさない、または
details.proxyInfo?.proxyDNSがある場合は、追加の DNS 処理を行わない
DNS 参照と保存方式
dnsShouldResolve(hn)は、空のホスト名、[で始まるホスト名、IPv4 アドレス形式を DNS 参照対象から除外dnsResolve(hn, details)はリングバッファの現在位置にホスト名を登録し、dnsAPI.resolve(hn, [ 'canonical_name' ])を呼び出す- 参照成功時は
dnsToCache(hn, rec, details)が実行され、失敗時はdnsToCache(hn)で空の項目をキャッシュに残す dnsToCacheは新しいキャッシュ項目にhnと有効期限時刻を保存cnameFromRecordが値を返せばdnsEntry.cnameに保存ipFromRecordが値を返せばdnsEntry.ipに保存
dnsFromCacheはキャッシュ項目がPromiseならそのまま返し、期限切れ項目はdnsListとdnsDictから削除
CNAME と IP の反映条件
cnameFromRecord(hn, record, details)はrecord.canonicalNameがない、または元のホスト名と同じ場合は CNAME を返さないcnameIgnore1stPartyが有効なら、CNAME と元のホスト名のドメインが同じ場合は除外cnameIgnoreListがある場合、その正規表現にマッチしない CNAME は除外cnameIgnoreRootDocumentが有効なら、リクエストホスト名がdetails.documentUrl || details.urlのホスト名と同じ場合は除外ipFromRecord(record)はrecord.addressesが配列で空でない場合、最初のアドレスaddresses[0]を返す
URL の書き換えと後続フィルタリング
onAfterDNSResolutionは DNS 項目に CNAME があり、cnameUncloakEnabledが有効ならuncloakURLで URL を書き換える- URL を変更する際、既存の URL は
details.aliasURLに保存し、新しい URL はdetails.urlに反映 - DNS 項目に IP があり、現在の
details.ipと異なる場合はdetails.ipを更新 - CNAME 書き換え または IP 変更が発生した場合にのみ、ベースクラスの
onBeforeSuspendableRequest(details)を再度呼び出す uncloakURLは URL 内のホスト名位置を見つけて CNAME に置き換え、cnameReplayFullURLの値に応じて URL 全体を連結するか、パス手前までを維持する
設定と manifest の変更
setOptionsからcnameMaxTTLの処理を削除- オプション変更時は既存の
cnamesMap 初期化の代わりにdnsList.fill(null)とdnsDict.clear()で DNS キャッシュを空にする src/js/background.jsの隠し設定デフォルト値からcnameMaxTTL: 120を削除platform/chromium/manifest.jsonのminimum_chrome_versionは73.0から80.0に変更platform/opera/manifest.jsonのminimum_opera_versionは60.0から67.0に変更
1件のコメント
Hacker Newsのコメント
タイトルが間違っているように思える。uBlock Origin はすでに何年も前からこの機能をサポートしていて、ただし Firefoxでのみ 可能だった
今回の件はまったく新しい機能というより、そのコードのリファクタリングに見える
ただし、1つのドメインに複数のIPがある場合、ブラウザがどのIPを選ぶかは分からないので、完璧ではない
もっと正確で中立的なタイトルを提案してくれるなら、また変更できる。ただ、追加の文脈がない GitHub コミットは通常 HN スレッド向きではあまりない
まだ直接の被害は受けていないが、Chrome が本当に uBOを排除したら 乗り換えられるように、すでに拡張機能を Firefox 向けに手直ししている
あと数回のリリースで到達するだろうから、準備しておくべきだ
せいぜい
background.service_workerをbackground.scriptsに変える程度で、文字どおりキー名を変えるだけで済むuBlock Origin は Firefox をより優れたものにしている要素であり、Chrome などではなく Firefox を使う大きな理由の1つだ
インターネットを実際に閲覧可能な状態にしてくれる
10年以上、いくつかのサイトで表示の問題はあったが、そうしたサイトは Chrome でも問題があった
個人的には広告は現代社会のがんのような存在だと思っている。罪のない嘘とそうでない嘘、操作が入り混じっていて、そこに莫大な金が流れているという点で、むしろまったく尊重に値しない
Brave も品質の高いプロジェクトなのでバックアップとして使っており、ときどきウィンドウ分割とずっと優れたタブ管理のために Vivaldi も併用している
CNAME クローキング とは、広告サイトがワイルドカードレコードを指すランダム生成のサブドメインを使うことを意味するのか?
通常、contentsite.com を訪れると広告は adsite.com から配信される。広告ブロックのルールで adsite.com を止めれば、広告は表示されない
CNAME クローキングは、メインサイトが adsite.contentsite.com のようなサブドメインを adsite.com に向ける方式だ。すると広告ブロッカーは、正規サイトに属しているように見える何百万ものサブドメインをブロックしなければならないという、ほぼ不可能な仕事を負わされる
正規サイトはサブドメインを変え続けることができ、広告ブロッカーにはどのサブドメインが正規コンテンツでどれが広告なのか知る方法がない。しかも、同じドメインからコンテンツが配信されるため、一部の Cookie ポリシーを回避してユーザーをより追跡しやすくもなる
今回のアップデートでは、解決されたIPを基準にフィルタリングするルールを設定できるようになる
これは Manifest V3 がなぜいまひとつなのか をよく示す例だ。定義上、この種のことはできず、実行時コードベースのヒューリスティクスも不可能だ
広告主との軍拡競争だが、Google は両陣営に武器を売るディーラーだ。ユーザーが勝つために必要なものは与えないだろう
もちろん、これらすべてはブラウザベンダー、つまり Google がこの API を追加したいかどうかにかかっている。「実行時コード」による命令的な処理が可能なら、ブラウザメーカーが組み込みサポートを入れる前に、ユーザー空間でイノベーションを起こせる
したがって、特定の機能が「定義上」不可能だというのは誤りだ
[1] https://blog.mozilla.org/addons/2022/05/18/manifest-v3-in-fi...
CNAMEクローキング たとえば、SaaSプロバイダーAが企業Qに優れた広告トラッキングソフトウェアを提供しようとしているとする。
従来のやり方であれば、Aは企業Qのウェブサイト
https://q-company.exampleに、たとえば https://A-ads-tracking.example のスクリプトを挿入するよう求めていたはず。すると、uBlock Originが使うブロックリストには「A-ads-tracking.example ドメインへのリクエストを遮断せよ」のようなルールが追加され、広告はブロックされる。
CNAMEクローキングでは、SaaSプロバイダーAは広告トラッキングサービスを A-ads-tracking.example ドメインではなく、たとえば 29.1.2.3 のような特定のIPアドレス上に置く。さらに重要なのは、SaaS Aが企業Qに対して q-company.example のサブドメインを作成し、そのCNAMEレコードが 23.1.2.3 を指すように要求する点である。media.q-company.example のようなもっともらしい名前を付ける。
Q社がそのCNAMEを設定し、ウェブサイトに
media.q-company.exampleのスクリプトタグを追加すると、SaaS Aはそのサイトのすべてのユーザーを追跡できる。この迂回レイヤーのせいで、Q社の運営者と公開ブロックリストの間には、事実上終わりのないいたちごっこが生まれる。この問題を避けるには、uBlock Originのような拡張機能を動かすソフトウェアが、ブラウザのリクエスト先ドメインだけでなく、そのドメインの実際のIPアドレスも見られる必要がある。このコミットは、その動作を可能にすること、あるいは少なくともそのコードがより適切に動作するようにすることに関係しているように見える。
たとえば
media.q-company.exampleがq-company.ads-tracking.exampleを指すCNAMEで、その次にq-company.ads-tracking.exampleがIPを返すAレコードを持つ、といった形になる。ブラウザがその中間DNS名を拡張機能に提供するのかは分からない。だから、uBlockのようなものはIPリストに依存せざるを得ないかもしれないが、piholeのようなDNSベースのフィルタリングなら、
ads-tracking.exampleに対するルールでそのままブロックできる。いずれにせよ、ブラウザベースとDNSベースのマルウェアブロッカーの両方を使うのがよい。
遅くてミスもしやすいが、慣れれば楽になり、この種のくだらない手口には完全に耐性がつく。
ChromeはuBOを止める予定なのか? 最新状況を常に追っているわけではない。
サードパーティCookieは今では許可することになったと理解しているので、ひょっとすると可能性はあるのかもしれない。
uBOが、読み込ませてはいけないものを識別し、その後で実際に読み込まれないようにするために必要な中核APIを取り除いている。
Googleはこれを「性能」や「セキュリティ」のためだと主張している。もちろん、実際に大きく影響を受ける唯一の「性能」や「セキュリティ」とは、有害または広告関連のダウンロードが始まる前に、それを識別し、横取りして、中止する能力のことだ。
https://developer.chrome.com/docs/extensions/develop/migrate...
https://www.bleepingcomputer.com/news/google/google-chrome-w...
Manifest V3のみをサポートするChromiumバージョンを使うと非表示になる。
一部のDNSサーバーには、サーバーが解決したCNAMEのように動作する機能があるのでは? 管理者は別のDNS名を指すレコードを入れるが、クライアント側からは単にAまたはAAAAレコードしか見えない、という方式のこと。
uBOにはこの機能がかなり前からあった。1.34.0 からで、高度な設定では1.25.0からだった。
https://github.com/gorhill/uBlock/wiki/Dashboard:-Settings#u...
だいたい2021年ごろだったと記憶している。
Brave、Edge、Operaでの uBOの状況 はどうなのか?
https://brave.com/blog/brave-shields-manifest-v3/
ただし必須というわけではない。Braveには独自の内蔵広告ブロッカーがかなり強力に組み込まれており、最後に確認した時点ではネイティブコードにコンパイルされていてuBOより性能も高く、同じ広告リストも完全にサポートしていた。