Hệ thống phát hiện bot của TRACIO nhận diện các trình duyệt tự động, công cụ headless và các cuộc tấn công bằng script thông qua kiến trúc hai lớp: thu thập tín hiệu phía client và phân tích phía server. Nó phát hiện các framework tự động hóa phổ biến, các trình duyệt headless, tác tử duyệt web AI và trình duyệt antidetect với tỷ lệ dương tính giả gần bằng không, đồng thời tự động đưa các trình thu thập dữ liệu (crawler) hợp lệ của công cụ tìm kiếm vào danh sách trắng.
Tác tử trình duyệt thu thập một loạt tín hiệu đặc thù cho bot và tín hiệu kiểm chứng chéo (cross-validation) để đưa vào các quyết định phía server. Các mã tín hiệu (Signal ID) dưới đây chỉ mang tính minh họa — các ID nội bộ không phải là một hợp đồng công khai ổn định:
| Signal | Mô tả |
|---|---|
s300 (webdriver) | Cờ navigator.webdriver — được các framework tự động hóa đặt thành true |
s301 (eval length) | eval.toString().length — Chrome/Edge: 33, Firefox: 37. Giá trị khác cho thấy có sự can thiệp đo đạc (instrumentation). |
s305 (bot composite) | Quét window/document để tìm 14 dấu vết của framework tự động hóa |
s97 (headless markers) | Dấu vết CDP, quyền thông báo, số lượng plugin, kích thước ngoài (outer dimensions) |
s157 (automation scan) | Quét toàn diện để tìm Selenium, Puppeteer, PhantomJS, Playwright và 10 công cụ khác |
s158 (iframe webdriver) | Tạo một iframe ẩn và đọc navigator.webdriver bên trong nó. Bắt được các công cụ vá frame chính nhưng bỏ quên iframe. |
s159 (native function) | Xóa Function và Object, kiểm tra xem các getter có thực sự là native hay không. Phát hiện instrumentation dựa trên Proxy. |
s155 (window CRC32) | Quét băm CRC32 mọi thuộc tính của window để phát hiện các biến global tự động hóa được tiêm vào |
s163 (devtools trap) | Bẫy getter của console — phát hiện khi DevTools đang được mở |
Server chạy một tập hợp các bộ phát hiện (detector) có các đầu ra được đánh
trọng số kết hợp thành một điểm bot (bot score). Điểm này được ánh xạ thành một
phán quyết (verdict) qua các ngưỡng — bot khi ≥ 0,70,
suspicious khi ≥ 0,30, còn lại là human — và một tín hiệu thất bại tuyệt đối
(hard-fail), chẳng hạn navigator.webdriver, buộc ra ngay một phán quyết bot.
Các phán quyết bot mang theo một nhãn bot_type ở dạng tự do.
Các bộ phát hiện tiêu biểu và tác động của chúng:
| Bộ phát hiện | Tác động |
|---|---|
| Cờ Webdriver | Hard-fail → bot (loại webdriver) |
| Quét tổng hợp tự động hóa / framework | Trọng số cao → bot (loại {framework}) |
| Dấu hiệu headless | Có trọng số → bot (loại headless) |
| Bất thường độ dài eval | Có trọng số → bot (loại unknown) |
| Mẫu UA của bot xấu | Có trọng số → bot (loại {label}) |
| Bot tốt đã xác minh (reverse DNS) | Danh sách trắng → human |
| Hành vi (tần suất / entropy / tương tác) | Có trọng số → bot (loại rateBot) |
| VM (Enterprise) · Emulator · DevTools (Business+) | Tín hiệu thiết bị/giả mạo có trọng số |
Gói dịch vụ & khả dụng. Phát hiện DevTools chạy trên Business và Enterprise; phát hiện VM là Enterprise; phát hiện emulator chạy trên mọi gói. Tất cả những thứ này đều hoạt động trong tác tử web. Phát hiện root, jailbreak, ứng dụng nhân bản/kép, Frida và khôi phục cài đặt gốc phụ thuộc vào các tín hiệu native trên di động và không hiệu quả trong triển khai chỉ-web (đang phát triển). Hãy dựa vào các phán quyết về tự động hóa, headless, tác tử AI, antidetect, VM/emulator và hành vi, vốn hoàn toàn hoạt động trên web.
Phát hiện bot ghi một trường bot_result trên mọi sự kiện (và bot.result trong
payload của webhook).
bot_result là một trong ba giá trị chuẩn tắc:
| Kết quả | Mô tả |
|---|---|
human | Không tìm thấy chỉ dấu tự động hóa. Các crawler công cụ tìm kiếm đã xác minh cũng cho ra human. |
bot | Phát hiện truy cập tự động hoặc bằng script. Kèm theo một nhãn bot_type ở dạng tự do. |
uncertain | Tín hiệu lẫn lộn hoặc yếu — không rõ ràng là người mà cũng không rõ ràng là tự động. |
Giá trị này được ánh xạ tới trường decision nghiệp vụ (real, fake hoặc suspicious)
được dùng xuyên suốt bảng điều khiển, và tới bot.result trong
payload của webhook.
"bot")bot_type là một chuỗi ở dạng tự do. Các giá trị dưới đây là ví dụ minh họa về
những gì các bộ phát hiện xuất ra, không phải là một enum đầy đủ:
| Loại | Phương pháp phát hiện |
|---|---|
webdriver | navigator.webdriver là true |
selenium | Phát hiện các thuộc tính window/document đặc thù của Selenium |
puppeteer | Khớp các chỉ dấu headless của Puppeteer/Chromium |
playwright | Phát hiện các dấu hiệu đặc thù hoặc chuỗi UA của Playwright |
headless | Kích hoạt 2+ trong số 11 dấu hiệu headless |
phantomjs | Phát hiện các biến global của PhantomJS (callPhantom, _phantom) |
nightmare | Phát hiện các biến global của NightmareJS |
unknown | Bất thường về độ dài eval hoặc chỉ dấu tự động hóa không đặc thù khác |
rateBot | Phân tích tần suất hành vi vượt các ngưỡng |
Cách phát hiện trực tiếp nhất. Mọi framework tự động hóa lớn đều đặt navigator.webdriver = true theo đặc tả WebDriver. Điều này được kiểm tra ở cả frame chính (s300) và một iframe ẩn (s158) để bắt các công cụ chỉ vá frame chính.
Quét toàn diện các thuộc tính của window và document để tìm các dấu vết đặc thù của framework:
| Framework | Thuộc tính được phát hiện |
|---|---|
| Selenium | _Selenium_IDE_Recorder, _selenium, calledSelenium, __selenium_evaluate, $cdc_* (ChromeDriver) |
| Puppeteer | domAutomation, domAutomationController, HeadlessChrome UA |
| Playwright | __playwright, cờ automation-controlled |
| PhantomJS | callPhantom, _phantom |
| NightmareJS | __nightmare, nightmare |
| CefSharp | CefSharp |
| Awesomium | awesomium |
| WebDriverIO | wdioElectron |
| Cypress | thuộc tính window __cypress |
Bản quét cũng dùng mẫu regex /^([a-z]){3}_.*_(Array|Promise|Symbol)$/ để phát hiện các biến global trợ giúp do Selenium tiêm vào.
11 dấu hiệu được đánh giá, với ngưỡng phân loại là từ 2 dấu hiệu trở lên:
| Dấu hiệu | Signal | Điều kiện |
|---|---|---|
| webdriver | s300 | = "true" |
| missing vendor flavors | s28 | Không có đối tượng chrome/safari trên window |
| CDP headless chrome | s305 | headlessChrome = true |
| notification denied | s88 | Notification.permission = "denied" trong lần đầu ghé thăm |
| chrome no runtime | s89 | window.chrome tồn tại nhưng thiếu chrome.runtime |
| single language | s90 | navigator.languages.length <= 1 |
| default screen 800x600 | s5 | Độ phân giải mặc định của Chrome headless |
| HeadlessChrome UA | UA | User-Agent chứa "HeadlessChrome" |
| zero outer dimensions | s97 | outerWidth = 0 và outerHeight = 0 |
| WebGL SwiftShader | s70 | Bộ kết xuất chứa "swiftshader" (GPU phần mềm) |
| WebGL llvmpipe | s70 | Bộ kết xuất chứa "llvmpipe" (GPU phần mềm) |
Các bot tốt đã biết được nhận diện qua mẫu User-Agent. Mỗi bot được xác minh qua reverse DNS để chống giả mạo:
.googlebot.com)| Bot | Domain được phép |
|---|---|
.googlebot.com, .google.com | |
| Bing | .search.msn.com |
| Apple | .applebot.apple.com |
| Yahoo | .crawl.yahoo.net |
| Yandex | .yandex.com, .yandex.net, .yandex.ru |
| DuckDuckGo | .duckduckgo.com |
Nếu một yêu cầu tự nhận là Googlebot nhưng reverse DNS của IP lại phân giải ra một domain lạ (một sự không khớp PTR đã xác nhận, chứ không chỉ là tra cứu bị thiếu/hết thời gian chờ), thì nó bị phân loại là bot (loại spoofed:google).
Phát hiện dựa trên tần suất kèm chấm điểm entropy:
| Tần suất (req/phút) | Ngưỡng entropy | Hành động |
|---|---|---|
| 120+ | < 0.1 | bot (type: rateBot) |
| 60-120 | < 0.3 | bot (type: rateBot) |
| 45-60 | < 0.1 | bot (type: rateBot) |
| < 45 | Bất kỳ | Bình thường |
Quy tắc bổ sung: Không có sự kiện chuột/bàn phím sau 30+ giây tuổi phiên sẽ phân loại lượt truy cập là bot với loại noInteraction.
eval.toString().length cho ra các giá trị nhất quán tùy theo engine:
Bất kỳ giá trị nào khác đều cho thấy hàm eval đã bị một framework tự động hóa móc (hook) vào, phân loại lượt truy cập là bot với loại unknown.
SDK phía client cung cấp một boolean tiện lợi, result.bot.detected:
const result = await tracio.getResult()
if (result.bot.detected) { // Log and block console.warn(`Bot detected (confidence ${result.bot.confidence})`) showCaptcha() return}
// Proceed with loginawait login(credentials)Trên server của bạn, hãy hành động dựa trên gói tin webhook. Thông tin phát hiện bot
nằm trong đối tượng bot — bot.result và bot.type:
// `event` is the webhook delivery body (/docs/webhooks)app.post("/webhook/tracio", async (req, res) => { const event = req.body
if (event.bot.result === "bot") { await db.blockedRequests.insert({ visitorId: event.visitorId, botType: event.bot.type, ip: event.ip, timestamp: new Date(), }) }
res.status(200).send("OK")})Phát hiện bot của TRACIO được thiết kế để có tỷ lệ dương tính giả gần bằng không. Tuy nhiên, các trường hợp biên vẫn có thể xảy ra:
| Kịch bản | Rủi ro | Biện pháp giảm thiểu |
|---|---|---|
Tiện ích trình duyệt sửa đổi navigator | Thấp | Kiểm chứng chéo nhiều tín hiệu ngăn việc kích hoạt bởi một tín hiệu đơn lẻ |
| Phần mềm bảo mật doanh nghiệp | Rất thấp | Phát hiện headless cần từ 2 dấu hiệu trở lên |
| Công cụ trợ năng | Không | Các API trợ năng không kích hoạt bất kỳ tín hiệu phát hiện nào |
| Người dùng VPN/proxy | Không | Việc dùng VPN được theo dõi tách biệt với phát hiện bot |
Nếu bạn gặp phải dương tính giả, hãy xem trường bot.type để hiểu bộ phát hiện nào đã được kích hoạt và điều chỉnh chính sách của bạn cho phù hợp.