返回所有文章
發佈於 · 作者 Renaud Deraison

Bromure 如何在頁面看見之前就攔下廣告

多數廣告攔截器都是瀏覽器擴充功能,而多數擴充功能都和它想保護你的那個頁面跑在同一個行程裡。Bromure 的做法不一樣。以下是怎麼做到的,以及為什麼這件事重要。

住在瀏覽器裡的廣告攔截器,就像想從擂台內部當裁判。Bromure 把裁判搬到網路本身——一個頁面碰不到、指令碼觸不到、也沒有「反廣告攔截」橫幅能跟它吵嘴的位置。

廣告攔截是最受歡迎、卻沒有內建於瀏覽器的瀏覽器功能。數以億計的人一拿到新電腦就裝上第三方擴充功能,因為現代網路若沒有它,根本無法使用。這件事本身,就是一個設計上的異味。但幾乎每一款廣告攔截器的運作方式,都值得我們好好端詳一番,因為架構這件事其實影響深遠——既影響它實際能發揮多少效果,也影響當頁面主動反擊時會發生什麼事。

這篇文章會走過一般廣告攔截器是怎麼運作的、這種形態為什麼有實實在在的極限,以及 Bromure 如何採取另一種做法——這個做法的核心,其實借自一個你或許在某人地下室的 Raspberry Pi 上聽過的小工具。

廣告不只是惱人。它們是載入問題、隱私問題,也是一種攻擊途徑。

用了幾年廣告攔截之後,人很容易忘記原始、未經過濾的網路長什麼樣子。一篇熱門新聞文章,若不加任何過濾地載入,通常會從 30 到 80 個第三方網域抓資源。其中大多是分析服務、追蹤像素,以及即時競價端點。它們讓頁面變重、延遲變高,替一堆你連名字都沒聽過的公司種下 cookie,而且——正如本月稍早那篇關於勒索軟體的文章所提——它們是惡意程式其中一條低調的遞送管道,因為廣告聯播網偶爾會被騙,在正當網站上投放含有惡意內容的素材。

news.example.com一篇文章doubleclick.netgoogletagmanager.comfacebook.netadnxs.comscorecardresearch.comcriteo.nethotjar.comsegment.comchartbeat.compubmatic.comrubiconproject.comliveramp.comtaboola.comoutbrain.comnewrelic.comamplitude.commixpanel.com……還有 40 個每一個標誌都是一個新網域、一次新的 DNS、一次新的 TLS,以及一組新的 cookie。沒一個是你要求的。
2026 年,在完全不加過濾的情況下,一次造訪單一頁面實際會拉進哪些東西。你正在讀的那篇文章,通常是整個頁面裡最小的請求。其餘的一切,都是包在文章外面的那套機器。

因此,攔下這些請求並不是美觀層面的問題。它能讓效能提升、讓隱私提升,而且——因為廣告聯播網是惡意程式的常見散布管道——它也實實在在讓資安提升。唯一的問題是:你要怎麼攔。

典型的瀏覽器擴充功能是怎麼攔廣告的。

幾乎每一款主流廣告攔截器,包括你大概裝過的那些熱門款,都是瀏覽器擴充功能。這意味著在架構上,它住在瀏覽器裡面——它在瀏覽器行程內執行 JavaScript,針對瀏覽器的網路 API(webRequestdeclarativeNetRequest)註冊回呼,並檢查瀏覽器即將發出的每一個請求。

瀏覽器行程頁面載入、執行指令碼、請求資源廣告攔截器擴充功能檢查每個請求,回傳放行或封鎖網路TCP / TLS通往網站(已封鎖)擴充功能是瀏覽器載入的程式碼。被攻陷的轉譯程序或被撤銷的權限,都能讓它失效。惡意頁面能看出它是否已安裝,並拒絕載入。網際網路廣告伺服器.追蹤器.分析服務
以擴充功能為基礎的廣告攔截器通常是這樣運作的。擴充功能住在瀏覽器裡。每一個外送的請求都會交給它審核;它會把網址符合規則的那些攔下來。頁面與擴充功能共用同一個行程,大多數情況下也共用同一組權限。

這個形態能用——畢竟多數人每天都仰賴它——但它有實實在在的結構性限制:

頁面看得出來

既然擴充功能和頁面跑在同一個行程裡,頁面自己的 JavaScript 就能探測:「我的請求真的送出去了嗎?這個變數最後有被定義嗎?」整票網站(以及多數有付費牆的新聞媒體)會偵測到缺少的請求,然後拒絕載入,要求使用者「停用你的廣告攔截器」。

頁面和它在同一個信任區裡

擴充功能與它試圖過濾的那個惡意頁面,共用一個瀏覽器行程、一個轉譯程序,有時還共用一組權限。若頁面上出現夠糟糕的瀏覽器漏洞利用,擴充功能會跟著其他東西一起陣亡。擴充功能是程式碼;它們同時也是攻擊面。

請求早就已經誕生

等擴充功能看到某個請求時,瀏覽器其實已經決定要發這個請求、已經解析完網址,並且(視使用的 API 而定)做完 DNS 查詢。在那個階段才攔,是在過濾,不是在預防。

過濾 API 愈來愈弱

Chrome 在 Manifest v3 改寫之後,限縮了過濾類擴充功能能做的事,主要是限制規則數量,並以 declarativeNetRequest 取代動態的 webRequest。擴充功能 API 的架構是由瀏覽器廠商決定的,不是你能決定的。

Bromure 的做法:那道牆不是擴充功能。

Bromure 的廣告攔截器不是擴充功能。瀏覽器本身裡面完全沒有任何廣告攔截相關的程式碼。取而代之的是:瀏覽器執行所在的那台用完即丟 Linux VM 的網路堆疊才是那個廣告攔截器——從瀏覽器的角度來看,廣告網域根本就無法解析。

客體 VM.設定檔網路瀏覽器沒有安裝任何廣告攔截擴充功能Squid 代理伺服器:3128.HTTP/HTTPS透過本地 DNS 解析dnsmasq本地 DNS 解析器把命中清單者送進黑洞封鎖清單gravity.list十萬以上個網域全部送去 0.0.0.0網際網路news.example.comdoubleclick.netadnxs.com已封鎖頁面和它的指令碼都看不到代理伺服器後面的世界。從瀏覽器內部看,廣告網域根本就不存在。
在 Bromure 設定檔的 VM 內,瀏覽器每一個外送連線都會被導到一個本地的 HTTP 代理伺服器。那個代理伺服器會透過一個本地 DNS 伺服器解析每一個網域,而那個 DNS 伺服器的「拒絕清單」就是一份封鎖清單。如果網域在清單上,瀏覽器拿到的就是一個不可達的位址,也就永遠不會建立連線——頁面自己的指令碼也一樣。

在機制上,有兩個不起眼的小軟體在幹活:

一個本地 HTTP 代理伺服器(Squid)

瀏覽器送出的每一個請求,都會被透明地導向 VM 內跑在 localhost:3128 上的 Squid 代理伺服器。Squid 扮演的是管線的角色:它不決定什麼算廣告,只為瀏覽器做 DNS 解析與轉送而已。

一個本地 DNS 解析器(dnsmasq)

我們指示 Squid 透過跑在 127.0.0.1 的本地 dnsmasq 來解析每一個網域。dnsmasq 的設定裡包含一份大約十萬個網域的封鎖清單——廣告聯播網、追蹤器、分析服務,以及已知的惡意主機。清單上的一切,都會被解析到 0.0.0.0,而那哪裡都去不了。

結果就是:從瀏覽器的角度看,這是一個長得像網際網路的網路,只是廣告與追蹤網域完全沒有 DNS 記錄而已。瀏覽器問 doubleclick.net,拿到「沒有路由」,然後就過了。沒有連線被開啟。沒有 TLS 交握被嘗試。沒有任何 cookie 被送出去,因為根本沒有「去」可送。

這個點子,在地下室裡已經跑了好多年。

如果你曾經架設過 pi-hole——那個很多人放在 Raspberry Pi 上、負責把整個家用網路裡的廣告過濾掉的小盒子 DNS 黑洞——那你會覺得 Bromure 的架構非常眼熟。底層那份封鎖清單就是 Steven Black 的統一 hosts 檔案,也就是那些家用安裝已經跑了好幾年的同一份。概念上的轉變完全一樣:別想著把廣告從頁面裡移除,直接拒絕告訴瀏覽器廣告的伺服器在哪裡,就好了。

重要的差異在於:這個 DNS 黑洞住在哪裡。家戶級的 DNS 黑洞保護的是家用網路上的每一台裝置;Bromure 的 DNS 黑洞只保護某一個特定的瀏覽器設定檔。你可以在用來讀新聞的那個設定檔打開它;在你銀行大概不太希望你經過任何奇怪中介層的那個設定檔關掉它。

這樣做實際換到的是什麼。

擴充功能把它攔下瀏覽器解析廣告網址。對廣告網域進行 DNS 查詢。連線嘗試可能已經開始。擴充功能在最後一刻否決。頁面能察覺到少了那個請求。廣告伺服器學到「有人從 IP X 嘗試連過來,然後放棄了。」Bromure 根本不問瀏覽器向本地 DNS 詢問那個網域。dnsmasq 回答 0.0.0.0沒有任何網路連線被開啟。沒有 TLS、沒有 SNI、沒有 HTTP 請求。頁面無法分辨這與 DNS 失敗有何差別。廣告伺服器學到什麼都沒有。根本沒有任何連線可以被觀察到。
同樣是造訪一個頁面,架構不同。擴充功能放任請求開始,在最後一刻才過濾掉它。Bromure 在問題被問出口之前就拒絕。廣告伺服器對 Bromure 使用者什麼都不知道——連對方嘗試過都不知道。

實務上能拿到的好處一層又一層:

不會被被攻陷的頁面停用

封鎖清單不是瀏覽器載入的程式碼,而是瀏覽器的網路本身。轉譯程序漏洞、惡意指令碼、行為異常的第三方函式庫——沒有一個能碰到 dnsmasq 的設定,因為沒有一個能跨出瀏覽器行程、觸及 VM 的網路堆疊。

頁面繞不過它

頁面的 JavaScript 可以一整天都在檢查 navigator 屬性;但它看不到所在網路的 DNS 設定,因為那不是 JavaScript 被允許知道的東西。對頁面而言,被封鎖的廣告看起來,就跟某個廣告網域剛好掛掉一分鐘一模一樣。

沒有擴充功能的攻擊面

廣告攔截器擴充功能曾不止一次被攻陷——透過擴充功能商店、透過併購易主,或透過惡意更新。Bromure 裡沒有這樣的擴充功能可以被攻陷,因為它根本就沒有擴充功能。

以設定檔為單位,像其他任何能力一樣可切換

廣告攔截是以設定檔為單位的設定(「隱私與安全」裡的「封鎖廣告」),預設關閉,你可以選擇在哪些設定檔打開它。你的銀行設定檔不做過濾;你的日常閱讀設定檔則乾乾淨淨。

誠實面對它的極限。

這個領域裡沒有什麼是免費的。以下是網路層做法刻意不做的幾件事,先跟你說清楚:

沒有外觀過濾

傳統擴充功能能把橫幅原本所在的那個空盒子藏掉。Bromure 不會改寫頁面,所以如果出版者預留了一塊 728×90 的區域,那塊空間還是會留在那裡,空著。在少數網站上這會造成一點小小的視覺困擾,而換來的是:頁面裡沒有任何東西能讓指令碼察覺異樣。

第一方廣告仍會通過

如果某個網站是從自己的網域投放自家廣告(現在有些大型科技平台就是這樣做),以網域為單位的封鎖無法區分「文章」與「廣告」——它們都掛在同一個主機名底下。這是一個真實存在的缺口;在有需要的情境下,解法是在上面疊一層 content-script,這是我們正在研究的工作。

反廣告攔截牆仍會偵測到「不在」

有些網站不需要真的找到廣告攔截器。它們只要檢查某個特定指令碼有沒有載入,如果沒有,就拒絕顯示文章。對於這些網站,任何攔截器——不管是擴充功能還是網路層——都會被抓到。這是你和出版者之間的政策之爭,而不是你和攔截器之間的技術之爭。

封鎖清單隨 Bromure 一起出貨

gravity.list 會在映像檔建置時被打包進去,而且會在你更新 Bromure 時一起更新。它不會像一個專門、隨時運行的家用 DNS 黑洞那樣,每小時拉取最新規則。對於一份以主機名為基礎的清單來說,這通常沒什麼問題——廣告網域汰換的速度不像、比方說、惡意程式網域那麼快——但還是值得你知道一下。

整件事的輪廓。

更大的重點,不是說 Bromure 的廣告攔截器在規則比對上神奇地比 uBlock Origin 強。事實上,uBlock 的規則引擎更為精巧。重點在於封鎖發生在哪裡。擴充功能是一位客氣的裁判,拜託瀏覽器請不要載入這個東西。Bromure 則是那條路——那條請求原本會經過的路——在交流道入口就被靜靜封了起來,連駕駛還沒上車就封了。

在密封 VM 裡做廣告攔截,並不是 Bromure 的什麼新功能;它是這套架構從第一天起就存在的結果。每一個設定檔的網路層都是它自己的小小世界。那個世界裡可以有 WARP,可以有付費 VPN,可以有 Tor 傳輸層。而它也可以免費擁有——那個在別人地下室裡靜靜過濾了好幾年廣告的同一套 DNS 黑洞——只不過這回它裝好、設定好,而且只限定在你想要它存在的那個瀏覽器工作階段裡。

如果你想要長版的說明:封鎖清單是一個純文字檔案,打包在 VM 映像檔裡——你可以在下一次發行版中直接檢視它,讀遍那十萬個將會悄悄從你瀏覽器的世界裡消失的網域。如果你只想要短版:在任一個 Bromure 設定檔裡打開「隱私與安全」,把「封鎖廣告」切到開啟。那條路已經被封了。你只需要上路,開車。