ระบบตรวจจับบอทของ TRACIO ระบุเบราว์เซอร์อัตโนมัติ เครื่องมือแบบ headless และการโจมตีด้วยสคริปต์ โดยใช้สถาปัตยกรรมสองชั้น ได้แก่ การเก็บสัญญาณฝั่งไคลเอนต์และการวิเคราะห์ฝั่งเซิร์ฟเวอร์ ระบบตรวจจับเฟรมเวิร์กอัตโนมัติทั่วไป เบราว์เซอร์แบบ headless เอเจนต์เรียกดูเว็บด้วย AI และ เบราว์เซอร์ต่อต้านการตรวจจับ ด้วยอัตราผลบวกลวงที่ใกล้ศูนย์ พร้อมทั้งเพิ่มครอว์เลอร์ของเครื่องมือค้นหาที่ถูกต้องเข้าใน allowlist โดยอัตโนมัติ
เอเจนต์ในเบราว์เซอร์เก็บสัญญาณเฉพาะสำหรับบอทและสัญญาณตรวจสอบยืนยันข้ามหลากหลายรายการ ซึ่งป้อนเข้าสู่การตัดสินใจฝั่งเซิร์ฟเวอร์ รหัสสัญญาณด้านล่างเป็นเพียงตัวอย่างประกอบ — รหัสภายในไม่ใช่สัญญาสาธารณะที่คงที่:
| Signal | Description |
|---|---|
s300 (webdriver) | แฟล็ก navigator.webdriver — ถูกตั้งเป็น true โดยเฟรมเวิร์กอัตโนมัติ |
s301 (eval length) | eval.toString().length — Chrome/Edge: 33, Firefox: 37 ค่าอื่น ๆ บ่งชี้ถึงการฝังเครื่องมือ |
s305 (bot composite) | สแกน window/document เพื่อหาสิ่งตกค้างของเฟรมเวิร์กอัตโนมัติ 14 รายการ |
s97 (headless markers) | สิ่งตกค้างจาก CDP, สิทธิ์การแจ้งเตือน, จำนวนปลั๊กอิน, ขนาดภายนอก |
s157 (automation scan) | สแกนอย่างครอบคลุมเพื่อหา Selenium, Puppeteer, PhantomJS, Playwright และอีก 10 รายการ |
s158 (iframe webdriver) | สร้าง iframe ที่ซ่อนไว้และอ่านค่า navigator.webdriver ภายในนั้น จับเครื่องมือที่แพตช์เฉพาะเฟรมหลักแต่ลืม iframe |
s159 (native function) | ลบ Function และ Object แล้วทดสอบว่า getter เป็นแบบ native จริงหรือไม่ ตรวจจับการฝังเครื่องมือที่อาศัย Proxy |
s155 (window CRC32) | สแกนแฮช CRC32 ของทุกพร็อพเพอร์ตี้ของ window เพื่อตรวจจับ global ของระบบอัตโนมัติที่ถูกฉีดเข้ามา |
s163 (devtools trap) | กับดัก getter ของ console — ตรวจจับเมื่อ DevTools ถูกเปิดอยู่ |
เซิร์ฟเวอร์รันชุดของตัวตรวจจับ ซึ่งผลลัพธ์ที่ถ่วงน้ำหนักจะถูกรวมเป็น
คะแนนบอท คะแนนนี้จะถูกจับคู่กับคำตัดสินผ่านค่าเกณฑ์ — bot เมื่อคะแนน ≥ 0.70,
suspicious เมื่อ ≥ 0.30 มิฉะนั้นเป็น human — และสัญญาณ hard-fail (เช่น
navigator.webdriver) จะบังคับให้เป็นคำตัดสิน bot ทันที คำตัดสิน bot จะมาพร้อมกับ
ป้าย bot_type แบบอิสระ
ตัวตรวจจับตัวแทนและผลลัพธ์ของแต่ละตัว:
| Detector | Effect |
|---|---|
| แฟล็ก Webdriver | Hard-fail → bot (ชนิด webdriver) |
| การสแกน Composite automation / framework | น้ำหนักสูง → bot (ชนิด {framework}) |
| Headless markers | ถ่วงน้ำหนัก → bot (ชนิด headless) |
| ความผิดปกติของ Eval-length | ถ่วงน้ำหนัก → bot (ชนิด unknown) |
| รูปแบบ UA ของ bad-bot | ถ่วงน้ำหนัก → bot (ชนิด {label}) |
| บอทที่ดีซึ่งผ่านการยืนยัน (reverse DNS) | Allowlist → human |
| เชิงพฤติกรรม (rate / entropy / interaction) | ถ่วงน้ำหนัก → bot (ชนิด rateBot) |
| VM (Enterprise) · Emulator · DevTools (Business+) | สัญญาณอุปกรณ์/การดัดแปลงแบบถ่วงน้ำหนัก |
แพ็กเกจและความพร้อมใช้งาน การตรวจจับ DevTools ทำงานบน Business และ Enterprise; การตรวจจับ VM เป็นของ Enterprise; การตรวจจับ emulator ทำงานบนทุกแพ็กเกจ ทั้งหมดนี้ทำงาน ในเว็บเอเจนต์ ส่วนการตรวจจับ Root, jailbreak, แอปที่ถูกโคลน/แอปคู่, Frida และการรีเซ็ตโรงงาน ขึ้นอยู่กับสัญญาณ native-mobile และไม่มีผลในการติดตั้งแบบเว็บอย่างเดียว (อยู่ระหว่างการพัฒนา) ให้พึ่งพาคำตัดสินด้าน automation, headless, AI-agent, antidetect, VM/emulator และเชิงพฤติกรรม ซึ่งทำงาน อย่างเต็มรูปแบบบนเว็บ
การตรวจจับบอทจะเขียนฟิลด์ bot_result ในทุกอีเวนต์ (และ bot.result ใน
payload ของ webhook)
bot_result เป็นหนึ่งในสามค่ามาตรฐาน:
| Result | Description |
|---|---|
human | ไม่พบตัวบ่งชี้ระบบอัตโนมัติ ครอว์เลอร์ของเครื่องมือค้นหาที่ผ่านการยืนยันก็จะได้ผลเป็น human เช่นกัน |
bot | ตรวจพบการเข้าถึงแบบอัตโนมัติหรือด้วยสคริปต์ พร้อมป้าย bot_type แบบอิสระที่มาด้วยกัน |
uncertain | สัญญาณผสมหรืออ่อน — ไม่ชัดเจนว่าเป็นมนุษย์หรืออัตโนมัติ |
ค่านี้จะถูกจับคู่กับฟิลด์ decision เชิงธุรกิจ (real, fake หรือ suspicious)
ที่ใช้ทั่วทั้งแดชบอร์ด และกับ bot.result ใน
payload ของ webhook
"bot")bot_type เป็นสตริงแบบอิสระ ค่าด้านล่างเป็นตัวอย่างประกอบของสิ่งที่
ตัวตรวจจับส่งออกมา ไม่ใช่ enum ที่ครอบคลุมทั้งหมด:
| Type | Detection Method |
|---|---|
webdriver | navigator.webdriver เป็น true |
selenium | ตรวจพบพร็อพเพอร์ตี้ window/document เฉพาะของ Selenium |
puppeteer | ตัวบ่งชี้ headless ของ Puppeteer/Chromium ตรงกัน |
playwright | ตรวจพบ marker เฉพาะของ Playwright หรือสตริง UA |
headless | 2+ จาก 11 headless markers ถูกกระตุ้น |
phantomjs | ตรวจพบ global ของ PhantomJS (callPhantom, _phantom) |
nightmare | ตรวจพบ global ของ NightmareJS |
unknown | ความผิดปกติของ eval length หรือตัวบ่งชี้ระบบอัตโนมัติที่ไม่เฉพาะเจาะจงอื่น ๆ |
rateBot | การวิเคราะห์อัตราเชิงพฤติกรรมเกินค่าเกณฑ์ |
การตรวจจับที่ตรงไปตรงมาที่สุด เฟรมเวิร์กอัตโนมัติหลักทั้งหมดตั้งค่า navigator.webdriver = true ตามข้อกำหนดของ WebDriver ค่านี้จะถูกตรวจสอบทั้งในเฟรมหลัก (s300) และใน iframe ที่ซ่อนไว้ (s158) เพื่อจับเครื่องมือที่แพตช์เฉพาะเฟรมหลัก
การสแกนพร็อพเพอร์ตี้ของ window และ document อย่างครอบคลุมเพื่อหาสิ่งตกค้างเฉพาะของเฟรมเวิร์ก:
| Framework | Properties Detected |
|---|---|
| Selenium | _Selenium_IDE_Recorder, _selenium, calledSelenium, __selenium_evaluate, $cdc_* (ChromeDriver) |
| Puppeteer | domAutomation, domAutomationController, HeadlessChrome UA |
| Playwright | __playwright, automation-controlled flag |
| PhantomJS | callPhantom, _phantom |
| NightmareJS | __nightmare, nightmare |
| CefSharp | CefSharp |
| Awesomium | awesomium |
| WebDriverIO | wdioElectron |
| Cypress | พร็อพเพอร์ตี้ window __cypress |
การสแกนยังใช้รูปแบบ regex /^([a-z]){3}_.*_(Array|Promise|Symbol)$/ เพื่อตรวจจับ helper global ที่ Selenium ฉีดเข้ามา
มีการประเมิน 11 markers โดยใช้ค่าเกณฑ์ 2 ตัวขึ้นไปสำหรับการจัดประเภท:
| Marker | Signal | Condition |
|---|---|---|
| webdriver | s300 | = "true" |
| ขาด vendor flavors | s28 | ไม่มีอ็อบเจกต์ chrome/safari บน window |
| CDP headless chrome | s305 | headlessChrome = true |
| notification denied | s88 | Notification.permission = "denied" ในการเข้าชมครั้งแรก |
| chrome no runtime | s89 | window.chrome มีอยู่ แต่ chrome.runtime ขาดหายไป |
| single language | s90 | navigator.languages.length <= 1 |
| default screen 800x600 | s5 | ความละเอียดเริ่มต้นของ Headless Chrome |
| HeadlessChrome UA | UA | User-Agent มี "HeadlessChrome" |
| zero outer dimensions | s97 | outerWidth = 0 และ outerHeight = 0 |
| WebGL SwiftShader | s70 | Renderer มี "swiftshader" (GPU ซอฟต์แวร์) |
| WebGL llvmpipe | s70 | Renderer มี "llvmpipe" (GPU ซอฟต์แวร์) |
บอทที่ดีซึ่งเป็นที่รู้จักจะถูกจดจำจากรูปแบบของ User-Agent แต่ละตัวจะถูกยืนยันผ่าน reverse DNS เพื่อป้องกันการปลอมแปลง:
.googlebot.com)| Bot | Allowed Domains |
|---|---|
.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 |
หากคำขออ้างว่าเป็น Googlebot แต่ reverse DNS ของ IP นั้นแปลงกลับไปเป็นโดเมนต่างถิ่น (เป็นความไม่ตรงกันของ PTR ที่ยืนยันแล้ว ไม่ใช่เพียงการ lookup ที่ขาดหายไป/หมดเวลา) คำขอนั้นจะถูกจัดประเภทเป็น bot (ชนิด spoofed:google)
การตรวจจับตามอัตราพร้อมการให้คะแนนเอนโทรปี:
| Rate (req/min) | Entropy Threshold | Action |
|---|---|---|
| 120+ | < 0.1 | bot (type: rateBot) |
| 60-120 | < 0.3 | bot (type: rateBot) |
| 45-60 | < 0.1 | bot (type: rateBot) |
| < 45 | Any | Normal |
กฎเพิ่มเติม: การไม่มีอีเวนต์เมาส์/คีย์บอร์ดหลังจากอายุเซสชัน 30+ วินาที จะจัดประเภทการเข้าชมเป็น bot ด้วยชนิด noInteraction
eval.toString().length ให้ค่าที่สอดคล้องกันตามแต่ละเอนจิน:
ค่าอื่นใดบ่งชี้ว่าฟังก์ชัน eval ถูก hook โดยเฟรมเวิร์กอัตโนมัติ ซึ่งจะจัดประเภทการเข้าชมเป็น bot ด้วยชนิด unknown
Client SDK เปิดให้ใช้บูลีนที่สะดวก คือ 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)บนเซิร์ฟเวอร์ของคุณ ให้ดำเนินการกับการส่งมอบผ่าน webhook การตรวจจับบอท
อยู่ในอ็อบเจกต์ bot — bot.result และ 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")})การตรวจจับบอทของ TRACIO ออกแบบมาเพื่อให้มีผลบวกลวงใกล้ศูนย์ อย่างไรก็ตาม กรณีขอบยังอาจเกิดขึ้นได้:
| Scenario | Risk | Mitigation |
|---|---|---|
ส่วนขยายเบราว์เซอร์ที่แก้ไข navigator | ต่ำ | การตรวจสอบยืนยันข้ามหลายสัญญาณป้องกันการกระตุ้นจากสัญญาณเดียว |
| ซอฟต์แวร์ความปลอดภัยขององค์กร | ต่ำมาก | การตรวจจับ headless ต้องมี 2+ markers |
| เครื่องมือช่วยการเข้าถึง | ไม่มี | API ช่วยการเข้าถึงไม่กระตุ้นสัญญาณการตรวจจับใด ๆ |
| ผู้ใช้ VPN/proxy | ไม่มี | การใช้ VPN ถูกติดตามแยกต่างหากจากการตรวจจับบอท |
หากคุณพบผลบวกลวง ให้ตรวจสอบฟิลด์ bot.type เพื่อทำความเข้าใจว่าตัวตรวจจับใดถูกกระตุ้น แล้วปรับนโยบายของคุณให้เหมาะสม