一份中立的偵測視角清單:TLS、Canvas 雜訊、字型、UA-CH 等 12 個信號,分辨真實瀏覽器與反偵測設定檔。
反偵測瀏覽器和真實瀏覽器可以送出完全相同的 User-Agent 字串,卻在偵測系統眼中截然不同。差距不在任何單一的請求標頭或 API 上——而在於一致性:真實裝置是一個整合系統,而偽造的設定檔是由替換值拼湊而成,很難做到端到端彼此吻合。這是一份偵測視角的清單,而非規避指南:12 個偵測系統如今確實在使用的具體信號,按其所在的層級分組,並說明當聲稱的身分與背後的流量不一致時,每個信號會暴露什麼。
核心要點
- 偵測很少依賴單一信號——它評估的是數十個獨立值彼此之間是否一致,而不僅僅是任何單一值看起來是否偽造。
- 網路層信號(TLS 交握、HTTP/2 幀)在頁面載入之前就會被檢查,對基於 JavaScript 的偽造工具而言完全不可見。
- 渲染層信號(Canvas、WebGL、字型)來自真實硬體和驅動程式,這使其成為最難令人信服地偽造的一層。
- 身分層信號(UA-CH、時區、語言環境)偵測成本低,能抓住最常見、最粗心的偽造嘗試。
- 目前沒有任何反偵測設定能同時通過所有層級的檢查——修好一處不一致,往往會暴露另一處。
12 個信號一覽
| # | 信號 | 真實瀏覽器會呈現什麼 |
|---|---|---|
| 1 | TLS ClientHello(JA3/JA4) | 與聲稱瀏覽器的 TLS 函式庫完全相符 |
| 2 | HTTP/2 幀與請求標頭順序 | 符合聲稱瀏覽器的技術堆疊,而非腳本函式庫 |
| 3 | Canvas 雜訊重測 | 同一頁面載入內重複繪製的雜湊完全一致 |
| 4 | WebGL 渲染字串與參數 | GPU 字串與擴充功能、精度、紋理上限一致 |
| 5 | 字型清單與 GPU/作業系統 | 字型集合與聲稱的作業系統相符 |
| 6 | 螢幕、觸控、硬體並行數 | 裝置類別(手機、筆電、桌機)內部一致 |
| 7 | UA-CH 與舊版 User-Agent | navigator.userAgentData 僅存在於 Chromium,且與 UA 字串一致 |
| 8 | 時區與 IP 地理位置 | 本地時區與 IP 解析出的地區相符 |
| 9 | 語言環境 / Accept-Language 與 IP | 瀏覽器語言與訪客所在地區大致相符 |
| 10 | navigator.webdriver 與自動化殘留 | 不存在,且全域作用域中沒有 CDP 或驅動殘留 |
| 11 | 屬性描述符 / 原型完整性 | 原生 API 的 .toString() 輸出和原型鏈未被竄改 |
| 12 | 無頭渲染異常 | 權限狀態一致,編解碼器清單完整,沒有純軟體渲染的 GPU |
網路層信號
1. TLS ClientHello——JA3/JA4
在頁面載入之前,瀏覽器會透過一則 ClientHello 訊息協商 HTTPS,其中列出的密碼套件、擴充功能和橢圓曲線的順序由 TLS 函式庫決定,而非任何你能調整的設定。JA3 和 JA4 將該訊息雜湊為一個與底層函式庫綁定的穩定指紋——Chromium 用 BoringSSL,Firefox 用 NSS。一個把 User-Agent 偽裝成「Firefox」的反偵測瀏覽器,如果底層其實是 Chromium 分支,交出的仍然是 Chromium 的 TLS 交握,因為更改 ClientHello 需要替換 TLS 函式庫本身,而不是 JavaScript 層。參見TLS 指紋技術詳解,了解 JA3、JA4 的計算方式,以及為什麼 GREASE——RFC 8701 定義的保留佔位值——會讓簡單的指紋比對變得複雜。
2. HTTP/2 幀與請求標頭指紋
再往上一層,HTTP/2 連線自帶其特徵:SETTINGS 幀的值、串流優先順序行為,以及偽標頭(:method、:path、:authority)的順序,在不同瀏覽器引擎和 HTTP 客戶端函式庫之間各不相同。一個 TLS 交握正確、但底層由自動化函式庫驅動的設定檔,仍可能洩漏不相符的 HTTP/2 指紋,因為這兩層由不同的程式碼路徑實作,很少被一起修補。
渲染層信號
3. Canvas 雜訊重測差異
Canvas 指紋之所以有效,是因為微小的像素差異來自真實的 GPU 和驅動程式行為——而這種輸出對給定裝置而言是確定性的:在同一次頁面載入中兩次繪製相同的圖形會得到相同的雜湊。反偵測工具透過在每次渲染時注入隨機雜訊來防禦 Canvas 追蹤,但這種雜訊本身是可偵測的:兩次繪製同一 Canvas 並比較即可。真實瀏覽器總是相符;逐次呼叫的雜訊注入器則很可能產生兩個不同的雜湊。EFF 的 Cover Your Tracks 專案記錄了 Canvas 唯一性在實務中是如何被測量的。
4. WebGL 渲染字串與下游參數的相符
未遮蔽的 WEBGL_debug_renderer_info 擴充功能暴露真實的 GPU 廠商和渲染字串。替換成一個看起來合理的字串很容易;讓所有依賴該 GPU 的參數都與之吻合卻很難——支援的擴充功能、最大紋理尺寸、著色器精度都取決於真正執行渲染的硬體,而非腳本聲稱的字串。聲稱的 GPU 與渲染出的像素輸出不相符,是最強的信號之一,因為偽造它需要模擬整個 GPU 的行為,而不只是覆寫一個屬性。
5. 字型清單與 GPU/作業系統的一致性
已安裝的字型在很大程度上由作業系統決定:Windows 內建 Segoe UI 和 Calibri,macOS 內建 San Francisco 和 Helvetica Neue,每個 Linux 發行版也有自己的預設字型。一個聲稱是 macOS、卻帶著 Windows 字型清單的設定檔——或是一個只在 Windows 上出現的 GPU 渲染字串,卻搭配了僅限 Apple 的字型集——無需知道「正確」的指紋應該是什麼樣,就已經暴露了不一致。
6. 螢幕、觸控與硬體並行數
裝置的螢幕尺寸、觸控事件支援情況和回報的 CPU 核心數,理應描述同一類硬體。一個「行動版 Safari」的身分卻沒有觸控事件、回報桌機等級的核心數,不符合任何一款真實 iPhone 的特徵。這些檢查成本很低,這也正是粗糙的偽造工具依然會在這些地方被抓的原因。
身分層信號
7. UA-CH 與舊版 User-Agent
Chromium 瀏覽器透過 navigator.userAgentData 暴露結構化的 User-Agent Client Hints——這是一個 JavaScript 可讀的物件,無論舊版 User-Agent 字串聲稱什麼,它要嘛存在(Chromium),要嘛不存在(Firefox、Safari):
// Chromium:回傳一個物件。Firefox/Safari:undefined —— 無論 UA 字串被偽造成什麼。
console.log(navigator.userAgentData);
一個「Safari」身分如果暴露出一個已填入資料的 userAgentData 物件,那就明確是執行在 Chromium 之上。這是偵測 User-Agent 偽造時最快的檢查之一——完整的請求標頭與 client hints 層面的破綻,參見如何偵測 User-Agent 偽造。
8. 時區與 IP 地理位置
每個瀏覽器都透過 Intl.DateTimeFormat().resolvedOptions().timeZone 暴露其本地時區。偵測系統會將其與訪客 IP 位址解析出的時區進行比對。一個聲稱在東京瀏覽、本地時區卻回報 America/New_York 的設定檔,是一個立即觸發的危險訊號——而且修正成本很低,這也是為什麼較為粗糙的反偵測設定仍然會在這一點上失手。
9. 語言環境與 Accept-Language 與 IP 地區
類似地,Accept-Language 請求標頭和 navigator.language 理應與 IP 解析出的地區大致相符。一個越南住宅 IP 搭配 Accept-Language: ru-RU 請求標頭並非不可能——真實的旅行者和外派人士確實存在——但它會引發和時區不符同樣的懷疑評分,尤其是疊加其他不一致時。
自動化與竄改信號
10. navigator.webdriver 與自動化殘留
當一個工作階段由 WebDriver 協定驅動時,標準化的 navigator.webdriver 屬性會被設為 true。除了這一個旗標之外,自動化框架還會在全域作用域中留下殘留——注入的 CDP 工件、window 上異常的屬性,以及粗糙的偽造層忘記清理的驅動專屬變數。更完整的自動化破綻清單參見Bot 偵測技術。
11. 屬性描述符與原型完整性
反偵測瀏覽器透過在原型層攔截 API 來修改指紋值——重新賦值 HTMLCanvasElement.prototype.toDataURL,或包裝 WebGLRenderingContext.prototype.getParameter。原生方法的 .toString() 回傳 "function toDataURL() { [native code] }";被粗糙修改過的版本往往不會,而 Object.getOwnPropertyDescriptor() 即使在精密工具試圖合成一個可信的原生程式碼標記時,也能揭露這種替換。
12. 無頭渲染異常
無頭和虛擬化的瀏覽器環境渲染頁面的方式與一般桌機工作階段不同:permissions API 回報相互矛盾的狀態、編解碼器清單被截斷,或者 WebGL 渲染字串指向像 SwiftShader 這樣的軟體光柵化器,而非真實 GPU 硬體。這些異常不需要與聲稱的身分比對——它們本身就內部不一致。
偽造能隱藏什麼,不能隱藏什麼
偽造單一屬性——一個 User-Agent 字串、一個 Canvas 雜湊、一個時區——很簡單。讓這十二個信號持續彼此一致,並在瀏覽器和作業系統更新中保持一致,則完全是另一回事。這與瀏覽器指紋本身背後的一致性原理相同,只是反過來讀:偵測系統衡量的不是指紋有多獨特,而是它有多內部一致。修復成本最低的信號——時區、語言環境、舊版 UA 字串——會被任何有能力的操作者最先修好。而那些根植於硬體和網路堆疊的信號——TLS 函式庫、GPU 渲染出的實際輸出、JavaScript 引擎行為——依然是持久的破綻,因為偽造它們意味著替換真正產生這些信號的元件本身,而不只是它回報的值。
檢查你自己的設置
BrowserInsight 的指紋檢測會並排呈現你的 Canvas 雜湊、WebGL 渲染字串和字型清單,Bot 偵測工具則展示偵測系統會評分的自動化與無頭信號。如果你在執行多設定檔或強化隱私的設置,同時檢查這兩者是發現十二個信號中是否有任何一個與你所呈現的身分不符的最快方式。
常見問題
單一信號足以證明瀏覽器被偽造了嗎?
單獨看很少能。偵測是機率性的——每一處不相符都會提高懷疑評分,而系統是把多個信號綜合起來判斷,而不是依賴某一項絕對檢查。一個有能力的操作者可以修好任意單一信號;難的是同時修好全部十二個,並在更新中持續保持修好狀態。
這 12 個信號中哪個最難偽造?
渲染層和網路層的信號——WebGL 輸出、Canvas 重測一致性,以及 TLS 交握——因為它們由硬體、驅動程式和 TLS 函式庫產生,而非腳本可以直接覆寫的值。要令人信服地偽造它們,意味著要重現整個元件的真實行為,而不只是編輯一個屬性。
VPN 或代理會影響這些信號嗎?
會間接影響時區和語言環境——如果出口位置與瀏覽器配置的語言環境不符;但一般的隧道式 VPN 不會觸及 TLS、Canvas、WebGL 或 UA-CH,因為這些是由瀏覽器自身計算的,而非網路路徑。與之並行運作的網路層檢查,參見網站如何偵測 VPN 與代理。
使用反偵測瀏覽器違法嗎?
不違法。反偵測瀏覽器有合法用途——管理多個店面、在平台規則允許的情況下執行並行廣告帳戶,以及注重隱私的瀏覽。工具本身是中性的;偵測系統關心的是它產生的信號是否內部一致,而不是操作者的意圖。


