全部文章

什麼是 JA4 TLS 指紋辨識,它究竟能說明什麼?

JA4 指紋描述的是一個客戶端如何說 TLS,早在它送出任何一個標頭之前。本文說明它的構成、它為何取代 JA3、它能抓到什麼,以及它在哪裡不再算證據。

2026年9月3日閱讀約 11 分鐘

客戶端送出的第一樣東西不是標頭,而是一個 TLS client hello:它支援的加密套件清單、它想要的擴充、它 接受的協定版本,以及它希望使用的應用層協定。這些內容全部以明文抵達,早於任何請求行,早於任何 User-Agent。JA4 指紋就是這條訊息的緊湊摘要,而它值得留意只有一個理由:客戶端並非把它當成關於自己 的說法而挑選出來,它是從客戶端所依賴的 TLS 程式庫裡自然落下來的。

這使它成為一種與 HTTP 層截然不同的訊號。User-Agent 是客戶端自己寫的一句話,JA4 指紋更接近一種口音。

讀懂這串字元

一個 JA4 取值由底線分隔的三部分組成:

t13d1516h2_8daaf6152771_b186095e22b6

第一部分不查表也能讀。t 代表 TCP,該位置若是 q 則代表 QUIC。13 代表 TLS 1.3。d 說明存在 SNI,即客戶端請求的是一個網域而非直接連往裸 IP。15 是所提供的加密套件數量,16 是擴充數量。 h2 是 ALPN 取值,說明這個客戶端請求的是 HTTP/2。

第二部分是排序後加密套件清單的截斷雜湊。第三部分涵蓋擴充清單與簽章演算法,同樣先行排序。GREASE 取值,即瀏覽器刻意摻入、用以令中介設備保持規矩的佔位項目,會在雜湊之前被剔除。

排序聽起來像枝節,它卻是這個格式存在的全部理由。

JA3 為何不再管用

2017 年的前身 JA3 按欄位在線路上的次序做雜湊。只要 TLS 協定堆疊仍然可預測,這套做法就沒有問題。 2023 年初 Chrome 推出擴充次序隨機化,每次連線都打亂 client hello 中擴充的排列,於是同一份 Chrome 安裝開始為每個請求產生不同的 JA3 雜湊值。建基於 JA3 放行名單的規則,在一個發布週期之內就由精確變 成無用。

JA4 先排序再雜湊,因此重新排列不會造成任何影響。它同時把可讀前綴留在雜湊以外,於是即使沒有已知取值 的資料庫,你也能分辨 QUIC 連線與 TCP 連線,或留意到某個客戶端只提供三個加密套件。JA4+ 家族的其餘成 員涵蓋其他層:JA4H 對應 HTTP 標頭,JA4T 對應 TCP 選項,JA4S 對應伺服器的回應。多數偵測工作使用的是 TLS 這一支。

看看這條連線的來源說明了什麼

它能抓到什麼

誠實的說法是:JA4 非常擅長抓住那些根本沒打算融入人群的客戶端。

使用 requests 的 Python 腳本所產生的 client hello,沒有任何瀏覽器會產生。Go 在 net/http 裡的 預設傳輸有它自己可辨認的形狀。curl 同樣如此,舊版本的 OpenSSL 同樣如此,多數 SDK 內建的 HTTP 客戶 端亦然。它們並沒有躲藏,它們本來就是這個樣子;即使請求自稱是 macOS 上的 Chrome 141,指紋照樣把實情 說出來。

有價值的正是這種不一致。單看一個 Go HTTP 客戶端的指紋,說明不了任何壞事。但一旦它與一個自稱瀏覽器 的 User-Agent 配在一起,就說明這個客戶端對自己的描述不實,而這樣做的理由多半並不清白。

同樣的邏輯對無頭瀏覽器亦成立,只是弱一些。真實的 Chrome 版本與由 Playwright 驅動的 Chrome 共用同一 套 TLS 協定堆疊,因此它們的 JA4 取值一致。把兩者分開的線索在別處:webdriver 旗標、欠缺的瀏覽器介 面、請求的時間節奏,以及客戶端有否去取瀏覽器會取的樣式表與字型。這正是指紋只能算一項輸入而非結論的 原因,這一點在機械人偵測最有效的訊號一文亦曾提及。

它在哪裡不再算證據

有兩個限制值得記住,而兩者在廠商文案中通常被一筆帶過。

指紋標示的是群體,不是身份。 Windows 上的每一個 Chrome 141 送出的 client hello 實際上都一樣, 那是數以百萬計的人共用一串字元。你可以說「這條連線來自形狀像 Chrome 141 的東西」,但關於是誰,你什 麼都說不出。把 JA4 取值當作訪客識別碼,你會不斷出錯,而且兩個方向都會錯。

指紋是可以複製的。 uTLS 能讓一個 Go 程式送出與指定 Chrome 版本逐位元組相同的 client hello, curl-impersonate 為 curl 做同樣的事。任何有動力讀完一篇文章的人,都能讓自己的爬蟲展示一個完全普通 的瀏覽器指紋。這件事的代價是投入,而投入本身就是一道真實的篩子:肯下這份功夫的腳本與不肯下的腳本之 間的差距,構成了互聯網上大部分自動化流量。但認真的對手能繞過這項訊號,因此任何只依賴 JA4 的方案都 會把他們放進來。

還有第三個更安靜的問題。做 TLS 檢查的企業代理會改寫 client hello,於是它後面的所有員工共用的是代理 的指紋,而不是自己瀏覽器的指紋。憑指紋攔截,你可能一次過把一整家公司擋在門外。

與其他訊號一併使用

真正站得住的做法是疊加,而非排名。每項訊號回答的問題都不同:

訊號它回答的問題何時失效
JA4這是哪一套 TLS 協定堆疊?客戶端使用 uTLS,或位於做 TLS 檢查的代理之後
IP 來源連線由哪裡發起?對方租用住宅位址
無頭瀏覽器痕跡是否有人在驅動瀏覽器?工具鏈修補了自己的痕跡
標頭一致性各項聲稱彼此吻合嗎?請求是被仔細人手拼裝的
反向 DNS 與 ASN這個爬蟲是它自稱的身份嗎?營運方沒有公布任何可核對的資料

把「何時失效」這一欄由上而下讀一遍,重點就很清楚:每一行對應的規避手法各不相同。攻破其中一項很容 易,同時攻破五項則是一項工程。資料中心 IP 加上 Go 的指紋,再加上 Chrome 的 User-Agent,毫無含糊之 處。住宅 IP 配上真實的 Chrome 指紋、又沒有無頭痕跡,那多半是個人,也應該按人來對待。

Agentscan 正是按這套邏輯運行。一次 POST 傳回一個判定類別,humanknown_botai_agentmalicious_automation,並附上信心值以及支撐判定的各項訊號,其中包括 JA4。命中快取的 判定可在 50 毫秒內傳回,這也是這項檢查能放進 middleware,而不必留待翌日早上翻查日誌的原因。

一套可落地的政策

  1. 在 TLS 終結的位置取得指紋。 應用程式碼永遠看不到 client hello。它來自你的 CDN、負載平衡器, 或擋在前面的偵測 API。
  2. 為不一致評分,而不是為指紋評分。 訊號是「TLS 協定堆疊與所聲稱的瀏覽器對不上」,而不是「這個 雜湊值是壞的」。維護一份雜湊封鎖清單會迅速過時,因為每個瀏覽器版本都會造出新的取值。
  3. 絕不讓它單獨決定。 至少要與來源配合。單獨使用時,它會抓住企業代理、放過熟練的爬蟲,兩邊都 錯。
  4. 預期取值會不斷變動。 瀏覽器更新會改變加密套件與擴充集合。你今天寫死的東西需要一個覆檢時間, 否則它遲早會悄悄開始標記真實使用者。
  5. 無論如何都要記錄。 即使不據此行動,把每個請求的 JA4 儲存下來,也能令下一次事件變得可讀。發現 有 40,000 個請求共用一個罕見指紋,比從原始日誌裡翻找要快得多。

結論

JA4 告訴你一個客戶端如何說 TLS。要隨手偽造它,比偽造任何標頭都難;要刻意偽造它,則比多數廠商願意承 認的更容易。它是關於另一端軟件形態的強訊號,是關於意圖的弱訊號,而關於身份則完全不是訊號。用它抓住 那些從未打算裝成人的自動化流量,對那些確實裝過的流量則把它與 IP 來源、無頭瀏覽器痕跡疊在一起,並且 不要建立任何只靠它支撐的攔截規則。

常見問題

常見問題解答

它是一串簡短字元,概括客戶端建立 TLS 連線的方式:協定版本、有否送出 SNI、提供了多少加密套件與擴充、ALPN 取值,再加上兩段截斷雜湊,分別涵蓋排序後的加密套件清單,以及排序後的擴充與簽章演算法清單。典型取值形如 t13d1516h2_8daaf6152771_b186095e22b6。它描述的是 TLS 協定堆疊,而非螢幕前的人。

相關文章