Bromureは、ページが目にする前に広告を遮断します
ほとんどの広告ブロッカーはブラウザ拡張機能であり、そしてほとんどのブラウザ拡張機能は、守ろうとしているページと同じプロセスの中で動いています。Bromureはそれを違うやり方でこなします。その方法と、なぜそれが重要なのかをお話しします。
ブラウザの内側に住む広告ブロッカーは、リングの中から試合を裁こうとする審判のようなものです。Bromureはその審判を、ページが届かず、スクリプトが触れられず、「アンチ広告ブロック」のバナーが言い返すこともできない場所 — ネットワークそのもの — に移しました。
広告ブロックは、ブラウザに標準搭載されていないブラウザ機能のなかで、もっとも広く使われている機能です。現代のウェブは、何らかの広告ブロッカーなしではまともに使えません。だからこそ何億人もの人が、初日にサードパーティの拡張機能をインストールしてしまうのです。それ自体が、設計のおかしさを示すサインです。しかし、ほぼすべての広告ブロッカーが取っている仕組みには注目する価値があります。そのアーキテクチャが、動作の良し悪しにも、ページ側が積極的に対抗してきたときの結末にも、実は大きく関わってくるからです。
本記事では、広告ブロッカーがふつうどのように動作するのか、なぜその形には実質的な限界があるのか、そしてBromureがどのように異なるアプローチを取っているのか — その核となる発想を、誰かの地下室のRaspberry Piで動いているあのツールから借りてきた経緯も含めて — をたどっていきます。
広告は単にうっとうしいだけではありません。読み込みの問題であり、プライバシーの問題であり、攻撃経路でもあります。
何年も広告ブロックに慣れきってしまうと、フィルタリングなしの素のウェブが実際どんな姿をしているか、忘れてしまいがちです。人気ニュース記事を何もフィルタリングせずに読み込むと、たいてい30から80ものサードパーティドメインからリソースが取得されます。その大半は、解析ツール、トラッキングピクセル、そしてリアルタイム入札のエンドポイントです。これらはページを重くし、レイテンシを増やし、あなたが名前も聞いたことのない企業のクッキーを勝手に置いていき、そして — 今月初めのランサムウェアの記事で触れたとおり — マルウェアの静かな配送経路のひとつになっています。広告ネットワークが、正規サイト上で悪意あるクリエイティブを配信させられてしまうことが、ときおり起きるからです。
したがって、これらのリクエストを止めることは、単なる見た目の問題ではありません。パフォーマンス上のメリットであり、プライバシー上のメリットであり、そして — 広告ネットワークがマルウェア配布の常連のチャネルである以上 — 実際にセキュリティ上のメリットでもあります。問題はただ一つ、どうやって止めるか、です。
典型的なブラウザ拡張機能は、どのように広告を止めているのか。
主流の広告ブロッカーは、あなたがたぶんインストールしている有名どころも含めて、ほぼすべてがブラウザ拡張機能です。つまり、アーキテクチャとしてはブラウザの内側に住んでいる、ということです。ブラウザプロセスの中でJavaScriptを走らせ、ブラウザのネットワーク関連API(webRequest、declarativeNetRequest)にコールバックを登録し、ブラウザがいまから出そうとしている一つひとつのリクエストを検査します。
この形はちゃんと機能します — 何しろ、多くの人が毎日頼りにしている形なのですから — が、構造的な限界があります。
ページ側から気づかれる
拡張機能はページと同じプロセスに住んでいるので、ページ自身のJavaScriptから存在を探ることができます。「自分が出したリクエストは本当に外に出ていったか? この変数はきちんと定義されたか?」と。サイト全体(そしてペイウォール付きニュースサイトの多く)は、リクエストが消えていることを検知し、ユーザーに「広告ブロッカーを無効化してください」と迫って記事を読ませないようにしています。
ページと同じ信頼境界にいる
拡張機能と、それがフィルタリングしようとしている敵対的なページは、ブラウザプロセスを共有し、レンダラーを共有し、場合によっては権限セットまで共有しています。ページ側に十分に悪質なブラウザ脆弱性が使われれば、拡張機能もほかのすべてと一緒に無力化されます。拡張機能はコードであり、つまり攻撃面でもあるのです。
リクエストはすでに生まれてしまっている
拡張機能がリクエストを見る時点では、ブラウザはすでにそれを送ると決断し、URLを解析し、(APIによっては)DNSルックアップまで済ませています。その段階での遮断は、予防ではなくフィルタリングでしかありません。
フィルタリングAPIはどんどん弱くなっている
ChromeのManifest v3への書き換えは、フィルタリング系拡張機能にできることを縛り、ルール件数に上限を設け、動的なwebRequestをdeclarativeNetRequestに置き換える形になりました。拡張機能APIのアーキテクチャを決めるのはブラウザベンダーであって、あなたではありません。
Bromureのやり方:壁は拡張機能ではない。
Bromureの広告ブロッカーは拡張機能ではありません。ブラウザそのものには、広告ブロック用のコードが一切入っていません。代わりに、ブラウザが走っている使い捨てLinux VMのネットワークスタックそのものが広告ブロッカーになっています。そしてブラウザの視点からは、広告ドメインはそもそも名前解決されません。
仕組みとしては、二つの小さく地味なソフトウェアが仕事をこなしています。
ローカルHTTPプロキシ(Squid)
ブラウザからの外向きリクエストはすべて、VM内のlocalhost:3128で動いているSquidプロキシへ透過的に流し込まれます。Squidは配管にすぎません。何が広告かを判定するのではなく、ブラウザに代わってDNS名前解決と転送を行うだけです。
ローカルDNSリゾルバー(dnsmasq)
Squidは、どんなドメインでも127.0.0.1で動くローカルのdnsmasqインスタンスを通して名前解決するように設定されています。dnsmasqの設定には、およそ10万件のドメイン — 広告ネットワーク、トラッカー、解析、既知の悪質ホスト — からなるブロックリストが含まれています。そこに載っているものは0.0.0.0に解決され、どこにも行きません。
結果として、ブラウザから見れば、ネットワークはインターネットそのものの形をしているのに、広告やトラッキングのドメインだけはDNSレコードが一切存在しない、という世界になります。ブラウザがdoubleclick.netを問い合わせれば「経路なし」が返り、そのまま通り過ぎる。接続は一切開かれません。TLSハンドシェイクも試みられません。クッキーはどこにも送られません。なぜなら、送る先の「どこか」が存在しないからです。
何年も地下室で動いてきたのと同じ発想。
家庭内ネットワーク全体から広告を追い出すために、Raspberry Piの上でpi-holeという小箱DNSシンクホールを仕立てたことがある方なら、Bromureのアーキテクチャはとても親しく感じられるはずです。下敷きになっているブロックリストは、Steven Blackが整備している統合hostsファイルで、それらの家庭導入で何年も前から使われてきたのと同じものです。発想の核は同じです。ページから広告を取り除こうとするのではなく、広告サーバーの所在をブラウザに教えること自体を拒む、ということです。
重要な違いは、シンクホールがどこに置かれているかです。家庭全体のシンクホールは、家のネットワーク上のすべての端末を守ります。Bromureのシンクホールはブラウザプロファイル一つだけを守ります。ニュースを読むためのプロファイルではオンにして、銀行のように「変な中継は挟まれたくない」プロファイルではオフのままにしておく、といった使い分けができるわけです。
これが実際に何を手に入れさせてくれるのか。
実用上のメリットはこう積み上がります。
侵害されたページに無効化されない
ブロックリストは、ブラウザに読み込まれているコードではなく、ブラウザのネットワークそのものです。レンダラーの脆弱性も、敵対的なスクリプトも、行儀の悪いサードパーティライブラリも — どれ一つとして、ブラウザプロセスの外に出てVMのネットワークスタックに手を伸ばせない以上、dnsmasqの設定には届きません。
ページ側から回り込めない
ページのJavaScriptはいくらでもnavigatorのプロパティを調べられますが、自分が乗っているネットワークのDNS設定を見ることはできません。それはJavaScriptが知ってよいこととされていないからです。ページにしてみれば、遮断された広告は、広告ドメインが1分ほどダウンしているのとまったく同じに見えます。
拡張機能の攻撃面がない
広告ブロッカー拡張機能は、これまでに何度か侵害されてきました — ストア経由だったり、買収経由だったり、悪意あるアップデート経由だったり。Bromureにはそもそも拡張機能がないので、侵害しようにも侵害できる拡張機能が存在しません。
プロファイル単位で、他の機能と同じように切り替え可能
広告ブロックはプロファイルごとの設定(「プライバシーとセーフティ」内の「広告をブロック」)で、既定はオフ、オンにしたいプロファイルだけでオンにできます。銀行用プロファイルはフィルタリングなしのまま、日常の記事閲覧用プロファイルはすっきり、という具合に。
正直に言う限界。
この領域に無料で手に入るものはありません。ネットワーク層のアプローチが意図的にやらないことがいくつかあります。先にはっきりさせておくべきでしょう。
コスメティックフィルタリングはしない
古典的な拡張機能なら、かつてバナーがあった空き箱を非表示にできます。Bromureはページを書き換えないので、もし掲載元が728×90の枠を確保していれば、その枠は空のまま残ります。一部のサイトでちょっと見た目が気になる、程度の小さな不都合です。代わりに、スクリプトが気づける手がかりがページ上に何も残りません。
ファーストパーティ広告は残る
サイトが自前のドメインから自前の広告を配信している場合(一部の大手プラットフォームはいま実際にそうしています)、ドメイン単位のブロックでは「記事」と「広告」を区別できません。どちらも同じホスト名の上にあるからです。これは本当に穴であり、ここが問題になる場面の答えは、その上にコンテンツスクリプトの層を足すことであって、そちらは現在検討中です。
アンチ広告ブロックの壁は「不在」を検知する
なかには、広告ブロッカーを見つけようとすらしないサイトもあります。特定のスクリプトが読み込まれたかだけをチェックし、読み込まれていなければ記事を表示しない、というやり方です。そうしたサイトでは、拡張機能型であれネットワーク型であれ、どのブロッカーもつかまります。それは掲載元との方針上の議論であって、ブロッカーとの技術的な議論ではありません。
ブロックリストはBromureと一緒に配布される
gravity.listはイメージビルド時に焼き込まれ、Bromureをアップデートするタイミングで更新されます。常時稼働の専用家庭用シンクホールのように、毎時最新ルールを取りにいく仕組みではありません。ホスト名ベースのリストであれば、これはだいたい問題になりません — 広告ドメインは、たとえばマルウェアドメインほどには頻繁に入れ替わらないからです — が、知っておく価値はあります。
ものごとの形。
もっと広い論点は、Bromureの広告ブロッカーがuBlock Originよりも魔法のようにうまくルールをマッチングできる、という話ではありません。uBlockのルールエンジンのほうが、実のところ洗練されています。論点は「どこで遮断が起きるか」です。拡張機能は、ブラウザに「どうかこれは読み込まないでください」とお願いする礼儀正しい審判です。Bromureは、そのリクエストが通るはずだった道路そのものを、ドライバーがまだ車にも乗らないうちに、高速の入口で静かに封鎖してしまうのです。
密閉VMのなかで広告をブロックする、これはBromureに新しく加わった機能ではありません。初日からそこにあったアーキテクチャの帰結です。各プロファイルのネットワーク層は、それ自体が独立した小さな世界なのです。その世界にWARPを入れることもできます。有料VPNを入れることもできます。Torのトランスポートを入れることもできます。そして、何年ものあいだ人々の地下室で静かに広告を濾し続けてきたのと同じDNSシンクホールを、無料で、あらかじめインストールされ、設定済みで、あなたが指定したまさにそのブラウザセッションにだけ適用される形で入れることもできます。
長いほうが知りたい方へ。このブロックリストはVMイメージの中にプレーンテキストで同梱されており、次のリリースでそのまま開いて、あなたのブラウザにとって静かに存在しなくなる十万件のドメインを、一つずつすべて確かめることができます。短いほうでいい、という方へ。どのBromureプロファイルでも「プライバシーとセーフティ」を開き、「広告をブロック」をオンにしてください。道路はすでに封鎖されています。あとは、あなたが運転するだけです。