即使開著 VPN,WebRTC 仍可能透過 STUN 請求暴露你的真實 IP 位址。本文說明 WebRTC 洩露的成因、如何自行檢測,以及可靠的防護做法。
WebRTC 洩露指的是:瀏覽器的即時通訊功能會暴露你的真實 IP 位址——包括真實的公網 IP——即使你已經開啟了 VPN。要阻止它,你可以停用 WebRTC、將其限制為只使用 VPN 的網路介面,或者選擇一款明確支援攔截 WebRTC 洩露的 VPN。以下我們將詳細解釋這個洩露是如何發生的、如何自行檢測,以及在不破壞視訊通話的前提下最安全的修復方式。
什麼是 WebRTC,瀏覽器為什麼要內建它
WebRTC(網頁即時通訊)是一項瀏覽器技術,讓網頁能夠在兩台裝置之間直接交換音訊、視訊和任意資料——也就是點對點(P2P)通訊——而無需任何外掛。它支撐著瀏覽器內的視訊會議、語音通話、螢幕分享和檔案傳輸,例如 Google Meet、Discord 以及大量線上客服聊天視窗。
由於 WebRTC 讓兩個對端直接相連,而不是把所有資料都經由中央伺服器轉發,因此每個對端都需要知道對方在網路上的可達位址。這個「探索」過程正是洩露的根源。WebRTC 既不是惡意軟體,也不是漏洞——它只是在做它被設計來做的事。問題在於,這套為視訊通話尋找最佳網路路徑的機制,同樣可以把你的真實 IP 位址交給頁面上的任意指令稿。
ICE 過程:STUN、TURN 與候選位址收集
為了建立直接連線,WebRTC 使用一套名為 ICE(互動式連線建立) 的框架,其規範定義於 RFC 8445。ICE 會收集兩個對端之間所有可能的可達方式,並依照該 RFC 定義的優先順序公式排序——主機候選優先,其次是伺服器反射候選,最後才是中繼候選——因此瀏覽器總會先嘗試最直接(也最容易暴露資訊)的路徑,再退回中繼方案。每一種可達方式都被稱為一個候選位址(candidate)。
候選位址主要有三類:
- 主機候選(Host)——你裝置的區域網路位址(例如
192.168.x.x或10.x.x.x這類 LAN IP,有時還包括 IPv6 位址)。 - 伺服器反射候選(Server-reflexive)——從外部看到的你的公網 IP,透過詢問 STUN 伺服器取得。STUN(NAT 工作階段穿越工具)伺服器只是回覆:「我看到你是從這個公網 IP 和連接埠連過來的。」這正是可能暴露真實 IP 的候選位址。
- 中繼候選(Relay)——當無法建立直接連線時,透過 TURN 伺服器轉發媒體流的備援方案。TURN 伺服器只是中轉流量,不會暴露新的 IP,但會消耗頻寬,因此僅在不得已時使用。
危險之處在於,ICE 會主動且悄無聲息地收集候選位址。一個網頁可以建立連線、根本不去呼叫任何人,卻依然能讀取瀏覽器收集到的候選位址——包括 STUN 探索到的公網 IP。
為什麼 VPN 不一定能救你
以下這一點會讓大多數 VPN 用戶感到意外。當你連接 VPN 後,一般網頁流量會透過 VPN 介面進行隧道傳輸,所以查詢 IP 的網站會顯示 VPN 的位址。但 WebRTC 的 STUN 請求是一條獨立的 UDP 流。根據你作業系統的路由規則、VPN 的分流(split-tunnel)設定,以及瀏覽器繫結網路介面的行為,這個 STUN 請求可能會走你的真實網路介面,而不是隧道。於是 STUN 伺服器回報的就是你的真實公網 IP,頁面隨即讀取到它——完全繞過了 VPN。
換句話說,VPN 保護了你的 HTTP 流量,而 WebRTC 卻悄悄洩露了你本想隱藏的那個 IP。如果你想確認 VPN 是否真正隱藏了你的位址,可以使用 BrowserInsight 的 VPN/代理檢測 和 IP 情報 工具,看看外部世界實際觀察到的是什麼。
mDNS .local 混淆機制及其侷限
現代 Chromium 系瀏覽器(Chrome、Edge)和 Firefox 針對本地 IP 暴露加入了一項緩解措施:它們不再暴露原始的 192.168.x.x 主機候選,而是替換為一個隨機化的 mDNS 主機名稱,形如 a1b2c3d4-....local。這個 .local 位址對遠端指令稿毫無意義,因此你的區域網路拓撲得以保密,而連線在本地網路上仍能正常運作。
這個領域的規範是 RFC 8828(「WebRTC IP Address Handling Requirements」)。它並沒有硬性規定 .local 這種做法,而是定義了四種 IP 處理模式,並規範每種模式最多可以透露多少網路資訊:模式 1 列舉全部位址,模式 2 使用預設路由及其關聯的本地位址,模式 3 只使用預設路由,模式 4 強制走 Proxy。隨機 mDNS 名稱則是各家瀏覽器為了在主機候選上滿足其中最嚴格的一端,而共同選擇的實作方式:瀏覽器在本地連結上公布一個隨機名稱,對外交出的是這個名稱而不是位址,於是區域網路 IP 本身根本不會離開你的機器。
這是一項實實在在的改進,但它有兩個重要侷限:
- 它只隱藏主機(本地)候選。 伺服器反射候選按定義就是一個公網位址——它正是公網上的 STUN 伺服器所看到的、你的封包來自何處,因此根本沒有本地名稱可以拿來替代。你的真實公網 IP 不會被 mDNS 隱藏,而這恰恰是對 VPN 用戶最要命的那種洩露。
- 它依賴瀏覽器和平台的支援。 較舊的瀏覽器、某些嵌入式 webview 以及特定設定,仍可能暴露原始的本地 IP。
所以,mDNS 減少了透過區域網路位址進行的指紋識別,但它並不能防禦公網 IP 洩露。
RFC 8828 真正能幫到 VPN 用戶的地方在於模式 3。「只使用預設路由」意味著 WebRTC 只能使用作業系統本來就用於一般流量的那個介面——而在 VPN 開啟時,這個介面就是隧道。於是 STUN 請求會從隧道送出,伺服器反射候選回報的也就成了 VPN 的位址,而不是你的位址。下一節那些瀏覽器開關,底層做的正是這件事。
洩露在程式碼裡長什麼樣
觸發候選位址收集並不需要什麼特殊工具。任何頁面都能用 W3C WebRTC 規範 中定義的標準介面 RTCPeerConnection,僅憑幾行 JavaScript 就能做到。下面這段程式碼建立一個對等連線,指向一個公共 STUN 伺服器,並印出瀏覽器探索到的每一個候選位址:
// 揭示 WebRTC 收集到的 IP 候選位址
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// 強制瀏覽器開始收集 ICE 候選位址
pc.createDataChannel('leak-test');
pc.onicecandidate = (event) => {
if (!event.candidate) return; // 收集完成
const candidate = event.candidate.candidate;
// ICE 候選字串的第 5 個欄位包含 IP
const ipMatch = candidate.match(
/([0-9]{1,3}(\.[0-9]{1,3}){3})|([a-f0-9]{1,4}(:[a-f0-9]{0,4}){2,7})/i
);
if (ipMatch) {
console.log('候選類型:', event.candidate.type);
console.log('暴露的位址:', ipMatch[0]);
}
};
pc.createOffer().then((offer) => pc.setLocalDescription(offer));
如果 event.candidate.type 是 srflx(伺服器反射),而印出來的位址是你的真實公網 IP 而非 VPN 的 IP,那麼你就存在 WebRTC 洩露。
如何檢測 WebRTC 洩露
測試大約只需一分鐘:
- 連接 VPN 並確認它已生效。
- 記下 VPN 聲稱分配給你的公網 IP——BrowserInsight 的 IP 情報 頁面就會顯示它。
- 執行 BrowserInsight 的 VPN/代理檢測。它會在你自己的瀏覽器裡跑上面這套候選位址收集,把 WebRTC 取得的公網 IP 與你的 HTTP 請求實際來源 IP 並列呈現,兩者不一致就判定為 WebRTC 洩露。(想看原始輸出的話,也可以把上面那段程式碼貼進瀏覽器主控台。)
- 把 WebRTC 暴露出來的位址與你的 VPN IP 做對比。
如果 WebRTC 顯示的 IP 與你的 VPN 一致,表示你受到保護;如果它顯示的是另一個公網 IP——你家裡或 ISP 的位址——那就是洩露。一個洩露的 IP 只有在真能鎖定你時,對追蹤者才有意義,而 IP 地理定位並不如許多人想像的那麼精確——不過通常仍足以揭露你所在的城市與 ISP。要交叉驗證除 WebRTC 之外你的連線還暴露了什麼,這一步可以和 DNS 洩露檢測 搭配進行,因為 DNS 洩露和 WebRTC 洩露往往源自同一個根因:流量逃出了隧道。
各瀏覽器的緩解方法
沒有一個開關能在所有地方一勞永逸地解決 WebRTC,因為每個瀏覽器的處理方式都不同。下表總結了實用的選項。
| 瀏覽器/平台 | 緩解方法 | 取捨 |
|---|---|---|
| Chrome/Edge(桌面端) | 沒有內建設定項,IP 處理策略只能透過擴充功能來改。Google 自家的 WebRTC Network Limiter 會把它設成「只用預設公網介面」,也就是 RFC 8828 的模式 3,讓候選收集只發生在隧道上 | 擴充功能可能影響部分視訊應用 |
| Firefox | 開啟 about:config,將 media.peerconnection.enabled 設為 false,徹底停用 WebRTC | 會完全破壞 WebRTC 視訊/語音通話 |
| Safari(macOS/iOS) | 穩定版沒有面向使用者的關閉開關。在 iOS 上這甚至不是「換個瀏覽器」能解決的問題——所有 iOS 瀏覽器底層都是 WebKit,換瀏覽器毫無用處,只能靠能在系統層面攔截 WebRTC 洩露的 VPN | 可控性有限 |
| Brave | 內建設定:在隱私設定中將 WebRTC IP 處理策略改為「停用非代理 UDP」——這是最嚴格的一檔,相當於 RFC 8828 的模式 4 | 可能影響點對點應用 |
| 行動端(Android/iOS) | 使用帶 WebRTC 控制的瀏覽器(Brave、Firefox),或使用在網路層攔截 WebRTC 的 VPN 應用 | 應用層級 VPN 是行動端最可靠的方案 |
對大多數 VPN 用戶來說,最乾淨的修復根本不是某個瀏覽器開關——而是選擇一款桌面端和行動端都明確宣傳具備 WebRTC 洩露防護、並在作業系統網路層強制執行的 VPN,讓 STUN 請求永遠無法逃出隧道。
停用 WebRTC 與限制 WebRTC
徹底停用 WebRTC(即 Firefox 的 media.peerconnection.enabled 路線)可以保證零洩露,但它會破壞所有瀏覽器內的視訊通話、語音聊天和螢幕分享。對大多數人來說,這未免太激進了。
更好的平衡是限制 WebRTC,使其只使用 VPN 的介面——這正是洩露防護擴充功能或具備 WebRTC 感知能力的 VPN 所做的事。你既能保留可用的視訊通話,又堵住了公網 IP 洩露。把「完全停用」留給一個專門強化、且你從不在其中打電話的瀏覽器設定檔即可。
常見問題
使用 VPN 會自動阻止 WebRTC 洩露嗎?
不一定。VPN 會隧道傳輸你的一般網頁流量,但 WebRTC 的 STUN 請求可能會因路由和分流設定而走另一條路徑、經過你的真實網路介面。許多優質 VPN 會額外加入 WebRTC 洩露防護,但你應當實測,而不是想當然耳。
停用 WebRTC 會讓網站打不開嗎?
它只會影響那些用到 WebRTC 的功能——瀏覽器內的視訊會議、語音通話、螢幕分享,以及部分點對點檔案傳輸。一般瀏覽、影音串流和絕大多數網站都不受影響。如果你依賴視訊通話,請改為限制 WebRTC 而不是停用它。
mDNS .local 混淆能讓我高枕無憂嗎?
它隱藏的是你的本地區域網路 IP,這對減少指紋識別是有益的,但它不會隱藏 STUN 探索到的公網 IP。對 VPN 用戶而言最關鍵的那種公網 IP 洩露,並不受 mDNS 影響。
我怎麼知道 VPN 是否真的隱藏了我的 IP?
把 VPN 聲稱的 IP 與各類服務實際看到的位址做對比即可。BrowserInsight 的 VPN/代理檢測 和 IP 情報 會展示外部世界觀察到的位址和網路細節,讓隱藏的洩露一目了然。
結語
WebRTC 是一項實用的技術,瀏覽器預設內建它也是合理的,但它的候選位址收集過程可能在 VPN 之後依然暴露你的真實公網 IP。解決之道不是懼怕 WebRTC——而是理解 ICE/STUN 機制、測試自己的環境,並施加恰當程度的緩解:日常使用時把 WebRTC 限制在隧道內,或在強化設定檔中徹底停用它。先測試,再根據你的上網方式選擇合適的取捨。
推薦閱讀:


