Cách UA Client Hints (UA-CH) hoạt động: tầng entropy thấp và cao, cơ chế Accept-CH và ý nghĩa với browser fingerprinting.
Chuỗi User-Agent đã tồn tại từ đầu những năm 1990 — một header duy nhất thông báo ngay lập tức trình duyệt, phiên bản, engine, hệ điều hành và loại thiết bị của bạn. Qua nhiều thập kỷ, chuỗi này ngày càng cồng kềnh: nó mang theo những token như Mozilla/5.0 — dấu vết của các trình duyệt đã biến mất từ lâu — cùng với đủ chi tiết nền tảng để trở thành tín hiệu thu thập dấu vân tay thụ động trên mỗi yêu cầu. User-Agent Client Hints (UA-CH) là phương án thay thế có cấu trúc của Chromium. Thay vì phát sóng mọi thứ từ đầu, API này hoạt động theo mô hình tiết lộ hai tầng: một tập nhỏ các gợi ý entropy thấp được gửi theo mặc định trong mỗi yêu cầu, còn tầng entropy cao hơn chỉ được cung cấp khi máy chủ yêu cầu rõ ràng.
Tóm tắt nhanh
- Trình duyệt Chromium mặc định gửi ba gợi ý entropy thấp (danh sách thương hiệu, cờ thiết bị di động, tên nền tảng) trên mỗi yêu cầu HTTPS — không cần máy chủ phải làm gì.
- Các chi tiết entropy cao (kiến trúc, phiên bản đầy đủ, phiên bản OS, mẫu thiết bị) chỉ được cung cấp sau khi máy chủ gửi header phản hồi
Accept-CHtrước. - Đối tác JavaScript là
navigator.userAgentData— API chỉ có trong Chromium; Firefox và Safari trả vềundefined. - Chromium đang dần đóng băng chuỗi
User-Agentcũ thành một stub ít thông tin trong khi mở rộng UA-CH làm kênh nhận dạng chính. - Đối với việc lấy dấu vân tay và phát hiện giả mạo, chính sự hiện diện của
navigator.userAgentDatađã đủ để xác định đáng tin cậy Chromium — và các giá trị entropy cao, khi được cấp phép, tiết lộ danh tính trình duyệt cụ thể hơn bao giờ hết so với chuỗi UA cũ.
Tại sao chuỗi User-Agent cũ cần được thay thế
Chuỗi UA ban đầu được thiết kế để phát hiện trình duyệt — máy chủ đọc nó, xác định engine nào đang được dùng, rồi gửi nội dung phù hợp. Nó chưa bao giờ được thiết kế với mục đích bảo vệ quyền riêng tư. Một chuỗi UA Chromium điển hình trông như thế này:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Header đơn đó thụ động tiết lộ tên và phiên bản OS, kiến trúc CPU, loại nền tảng, thương hiệu trình duyệt và số phiên bản thô — trong mỗi yêu cầu, mà không cần bất kỳ máy chủ nào hỏi. Nó cũng trở thành bẫy tương thích: các trang web bắt đầu phân nhánh logic dựa trên các chuỗi con cụ thể, khiến trình duyệt không thể thay đổi định dạng mà không làm hỏng những trang đó. Đây vừa là vấn đề bảo trì vừa là vấn đề quyền riêng tư. UA-CH giải quyết cả hai: nó đóng băng chuỗi cũ thành stub trong khi cung cấp API được phiên bản hóa rõ ràng, qua đó máy chủ có thể yêu cầu chính xác những gì cần.
Hai tầng: gợi ý entropy thấp và entropy cao
Mô hình UA-CH chia thông tin trình duyệt thành hai tầng dựa trên mức độ thu hẹp danh tính người dùng.
Gợi ý entropy thấp (gửi theo mặc định)
Chromium đính kèm ba header Sec-CH-UA-* vào mỗi yêu cầu HTTPS xuyên miền mà không cần máy chủ nhắc:
| Header | Giá trị ví dụ | Tiết lộ gì |
|---|---|---|
Sec-CH-UA | "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99" | Thương hiệu trình duyệt và phiên bản chính |
Sec-CH-UA-Mobile | ?0 | Thiết bị có phải di động không (?1) hay không (?0) |
Sec-CH-UA-Platform | "Windows" | Chỉ tên OS ở cấp cao |
Đây là entropy thấp vì các giá trị này được chia sẻ bởi số lượng lớn người dùng: biết ai đó dùng Chrome 124 trên Windows chỉ thu hẹp xuống hàng triệu người dùng, không phải một vài người.
Gợi ý entropy cao (yêu cầu Accept-CH)
Các chi tiết có độ phân giải cao hơn — loại có thể xác định bản build thiết bị cụ thể — mặc định bị tắt; máy chủ phải yêu cầu rõ ràng:
| Header | Giá trị ví dụ | Tiết lộ gì |
|---|---|---|
Sec-CH-UA-Arch | "x86" | Kiến trúc CPU |
Sec-CH-UA-Bitness | "64" | Nền tảng 32 hoặc 64 bit |
Sec-CH-UA-Full-Version-List | "Google Chrome";v="124.0.6367.60" | Chuỗi phiên bản đầy đủ cho mỗi thương hiệu |
Sec-CH-UA-Model | "Pixel 7" | Mẫu thiết bị (chủ yếu có ý nghĩa với di động) |
Sec-CH-UA-Platform-Version | "10.0.0" | Phiên bản OS |
Cơ chế thương lượng Accept-CH
Giao thức yêu cầu gợi ý entropy cao rất đơn giản. Khi truy cập lần đầu, máy chủ phản hồi với header Accept-CH liệt kê tên các gợi ý cần:
HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Full-Version-List, Sec-CH-UA-Arch, Sec-CH-UA-Platform-Version
Trong các yêu cầu tiếp theo (và khi tải lại trang), trình duyệt bao gồm các gợi ý đó:
GET /page HTTP/1.1
Sec-CH-UA: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"
Sec-CH-UA-Full-Version-List: "Chromium";v="124.0.6367.60", "Google Chrome";v="124.0.6367.60", "Not-A.Brand";v="99.0.0.0"
Sec-CH-UA-Arch: "x86"
Sec-CH-UA-Platform-Version: "10.0.0"
Lần tải trang đầu tiên cố ý ít thông tin: nếu không có opt-in trước, máy chủ chỉ thấy ba giá trị mặc định entropy thấp.
JavaScript API: navigator.userAgentData
Cùng dữ liệu đó có thể truy cập phía client qua navigator.userAgentData. API này chỉ tồn tại trong Chromium — Firefox và Safari trả về undefined — vì vậy sự hiện diện của nó tự thân là tín hiệu nhận dạng engine đáng tin cậy.
Dữ liệu entropy thấp là đồng bộ:
const uaData = navigator.userAgentData;
console.log(uaData.brands); // [{brand: "Chromium", version: "124"}, ...]
console.log(uaData.mobile); // false
console.log(uaData.platform); // "Windows"
Dữ liệu entropy cao là bất đồng bộ, yêu cầu yêu cầu rõ ràng — phản chiếu mô hình HTTP Accept-CH:
navigator.userAgentData
.getHighEntropyValues(["architecture", "platformVersion", "fullVersionList"])
.then(ua => {
console.log(ua.architecture); // "x86"
console.log(ua.platformVersion); // "10.0.0"
console.log(ua.fullVersionList); // [{brand: "Google Chrome", version: "124.0.6367.60"}, ...]
});
Gọi getHighEntropyValues() không kích hoạt lời nhắc cấp phép hiện thị cho người dùng. Nó cung cấp cho các trang web một cơ chế có thể theo dõi, rõ ràng để lấy thông tin nhận dạng chi tiết, thay vì âm thầm đọc chuỗi được phát sóng. Các iframe xuyên miền có thể bị chặn khỏi gợi ý entropy cao thông qua Permissions-Policy.
UA-CH so với User-Agent cũ
| Thuộc tính | User-Agent cũ | User-Agent Client Hints |
|---|---|---|
| Hỗ trợ trình duyệt | Tất cả trình duyệt | Chỉ Chromium |
| Mô hình tiết lộ | Tất cả được phát sóng thụ động | Entropy thấp mặc định + entropy cao theo yêu cầu |
| Định dạng | Chuỗi tự do không cấu trúc | Cặp key-value có cấu trúc |
| Khả năng giả mạo | Tầm thường (một chuỗi để đổi) | Từng trường; khó duy trì nhất quán |
| Ý định về quyền riêng tư | Không có (di sản lịch sử) | Tiết lộ dần được thiết kế sẵn |
| Xu hướng | Dần đóng băng thành stub | Mở rộng; kênh nhận dạng chính của Chromium |
Chromium đã dần dần giảm chi tiết trong chuỗi UA cũ. Từ Chrome 101, phiên bản phụ của OS đã bị đóng băng thành 0.0.0 và phiên bản phụ của trình duyệt trong chuỗi UA bị rút gọn. Xu hướng là hướng tới một stub chỉ truyền đạt "đây là trình duyệt Chromium" — tất cả thông tin cụ thể chuyển sang UA-CH.
Tác động đến fingerprinting
UA-CH thay đổi bối cảnh lấy dấu vân tay theo cả hai chiều.
Sự hiện diện của navigator.userAgentData là bộ phát hiện engine đáng tin cậy. Firefox và Safari không tiết lộ API này. Kiểm tra navigator.userAgentData !== undefined sẽ ngay lập tức xác định Chromium — đáng tin cậy hơn việc phân tích chuỗi UA có thể bị làm giả bằng một tiện ích mở rộng. Nếu UA bị giả mạo tuyên bố là Firefox nhưng navigator.userAgentData tồn tại và báo cáo thương hiệu Chromium, mâu thuẫn là hiển nhiên. Đây là một trong những kỹ thuật cốt lõi trong phát hiện giả mạo user-agent.
Gợi ý entropy cao có thể cụ thể hơn chuỗi UA cũ. Chuỗi UA đã đóng băng không còn tiết lộ phiên bản phụ đầy đủ của trình duyệt; Sec-CH-UA-Full-Version-List thì có. Kết hợp với Sec-CH-UA-Arch và Sec-CH-UA-Platform-Version, một máy chủ yêu cầu bộ đầy đủ sẽ nhận được dấu vân tay nền tảng phong phú hơn so với thời kỳ phát sóng thụ động — nhưng chỉ với sự hợp tác của trình duyệt và chỉ từ các máy chủ yêu cầu rõ ràng.
Đóng băng chuỗi UA ≠ cải thiện quyền riêng tư tự thân. Giảm chuỗi UA chỉ xóa một tín hiệu thụ động, không ảnh hưởng đến nhiều tín hiệu khác tạo nên dấu vân tay trình duyệt: đầu ra canvas, chuỗi renderer WebGL, thông số màn hình, xử lý âm thanh, phông chữ đã cài đặt. UA-CH cải thiện vệ sinh thông tin phía máy chủ mà không thu hẹp bề mặt dấu vân tay tổng thể.
UA-CH được kiểm soát bởi máy chủ, không phải người dùng. Không có giao diện trình duyệt nào để từ chối một lời gọi getHighEntropyValues() cụ thể từ JavaScript bên thứ nhất. Chế độ ngẫu nhiên hóa dấu vân tay của Brave thực sự ghi đè các giá trị UA-CH; các trình duyệt dựa trên Chromium khác thì không. Người dùng muốn hạn chế tiết lộ chỉ có thể dựa vào chế độ chống dấu vân tay của trình duyệt.
Tự kiểm tra
Mở bảng điều khiển DevTools và chạy navigator.userAgentData để xem các giá trị entropy thấp. Sau đó chạy:
navigator.userAgentData?.getHighEntropyValues(
["architecture", "model", "platformVersion", "fullVersionList"]
)
Trong Firefox hoặc Safari, API trả về undefined. Trong Chromium, nó phân giải thành một đối tượng với chi tiết nền tảng thực của bạn. Công cụ kiểm tra dấu vân tay của BrowserInsight hiển thị toàn bộ dữ liệu UA-CH cùng với các tín hiệu dấu vân tay còn lại, để bạn thấy tất cả các tín hiệu nhận dạng kết hợp như thế nào.
Câu hỏi thường gặp
UA-CH có thay thế hoàn toàn chuỗi User-Agent không?
Chưa, và chắc chắn không với các trình duyệt không dựa trên Chromium. Firefox và Safari vẫn chỉ gửi header User-Agent truyền thống. Với Chromium, UA-CH là kênh ưu tiên và UA cũ đang bị đóng băng, nhưng cả hai cùng tồn tại trong các phiên bản hiện tại. Các trang web cần tương thích rộng vẫn đọc User-Agent như phương án dự phòng.
Tôi có thể giả mạo các giá trị UA-CH không?
Không thể qua cài đặt trình duyệt thông thường. Tính năng mô phỏng thiết bị trong DevTools Chrome ghi đè chuỗi UA nhưng không ghi đè navigator.userAgentData, đó là lý do tại sao mô phỏng thiết bị dễ bị phát hiện. Chế độ ngẫu nhiên hóa dấu vân tay của Brave cung cấp khả năng giả mạo UA-CH, nhưng duy trì nhất quán trên cả HTTP headers lẫn JavaScript API đòi hỏi vá lỗi phối hợp ở cấp trình duyệt.
UA-CH có hoạt động qua HTTP không?
Không. Thương lượng Accept-CH và các header Sec-CH-UA-* chỉ áp dụng qua HTTPS (và localhost). Kết nối HTTP thông thường không gửi header UA-CH.
Firefox có hỗ trợ UA-CH không?
Firefox không triển khai UA-CH. Nhóm Mozilla đã bày tỏ lo ngại rằng khi các giá trị entropy cao được yêu cầu thường xuyên, API này có thể làm cho việc lấy dấu vân tay dễ dàng hơn thay vì khó hơn. Firefox tiếp tục sử dụng header User-Agent cũ.
Kết luận
User-Agent Client Hints đại diện cho một sự thay đổi kiến trúc có chủ ý: từ một luồng phát sóng thụ động duy nhất tiết lộ chi tiết nền tảng dù có ai hỏi hay không, sang một hệ thống phân tầng nơi các sự thật entropy thấp được gửi theo mặc định và các chi tiết entropy cao yêu cầu opt-in. Đối với nhà phát triển, API có cấu trúc dễ phân tích và quản lý phiên bản hơn chuỗi UA tự do. Đối với công việc lấy dấu vân tay và phát hiện, nó giới thiệu tín hiệu phân biệt Chromium và không-Chromium rõ ràng, đồng thời cung cấp kênh nhận dạng rõ ràng và phong phú hơn cho các máy chủ cần nó. Đóng băng chuỗi UA cũ giảm một vector thụ động; thứ thay thế nó là sự thương lượng chủ động giữa trình duyệt và máy chủ.
Đề xuất đọc thêm:


