Phát hiện headless browser: Playwright, Puppeteer và hơn thế nữa
Engine Bot Detection của chúng tôi nhận diện hơn 15 framework tự động hóa thông qua tín hiệu mâu thuẫn, API thiếu và mẫu hành vi mà bot không thể giả mạo.
Headless browser là vũ khí ưa thích cho việc web scraping tinh vi, credential stuffing và các chiến dịch gian lận. Khác với HTTP client đơn giản, headless browser thực thi JavaScript, render trang và hỗ trợ các web API hiện đại — khiến chúng khó bị phát hiện hơn nhiều. Engine Bot Detection của chúng tôi dùng nhiều phương pháp phát hiện độc lập để nhận diện hơn 15 framework tự động hóa với gần như không có false positive.
Sự tiến hóa của tự động hóa trình duyệt
Tự động hóa trình duyệt đã đi một chặng đường dài từ những script curl đơn giản. Các công cụ hiện đại như Playwright, Puppeteer và Selenium WebDriver điều khiển engine trình duyệt thật — Chromium, Firefox hay WebKit — ở chế độ headless. Chúng thực thi JavaScript, xử lý CSS, render phần tử canvas và xử lý truy vấn WebGL y hệt trình duyệt có giao diện. Điều này khiến chúng vô hình trước các phương pháp phát hiện chỉ đơn thuần kiểm tra khả năng thực thi JavaScript.
Thế hệ công cụ mới nhất còn đi xa hơn. Chế độ stealth của Playwright vá nhiều tín hiệu mà bot detection truyền thống dựa vào. Puppeteer-extra-plugin-stealth chỉnh sửa thuộc tính navigator, ghi đè chuỗi vendor của WebGL và làm giả sự kiện tương tác của người dùng. Những biện pháp chống phát hiện này đã tạo ra một cuộc chạy đua vũ trang giữa người vận hành bot và các hệ thống phát hiện.
Phương pháp phát hiện 1: Phân tích cờ WebDriver
Thuộc tính navigator.webdriver được đặt thành true khi trình duyệt bị điều khiển bởi tự động hóa. Trước đây, việc phát hiện đơn giản chỉ là kiểm tra thuộc tính này. Nhưng công cụ stealth hiện đại xóa hoặc ghi đè nó. Cách phát hiện của chúng tôi đi sâu hơn — chúng tôi kiểm tra không chỉ giá trị thuộc tính mà cả property descriptor của nó, sự hiện diện của nó trong prototype chain, và liệu đã có nỗ lực định nghĩa lại nó hay chưa. Chúng tôi cũng kiểm tra các thuộc tính liên quan như bất thường về độ dài của navigator.plugins vốn đi kèm với việc ghi đè WebDriver.
Phương pháp phát hiện 2: Artifact của Chrome DevTools Protocol
Playwright và Puppeteer điều khiển trình duyệt thông qua Chrome DevTools Protocol (CDP). Ngay cả khi chế độ stealth đang hoạt động, CDP vẫn để lại artifact trong runtime: các biến global cụ thể, hàm getter bị chỉnh sửa và property descriptor bị thay đổi trên đối tượng Window và Navigator. Chúng tôi dò tìm các artifact này bằng những kỹ thuật vững vàng trước những lần ghi đè đơn giản.
Phương pháp phát hiện 3: Fingerprinting headless browser
Chrome headless có tập năng lực khác với Chrome có giao diện. Nó thiếu một số plugin trình duyệt, có đặc tính render khác nhau đối với vài thuộc tính CSS, và báo cáo giá trị khác nhau cho một số kết quả MediaQuery. Chúng tôi duy trì một cơ sở dữ liệu về các đặc tính đã biết của headless browser và đối chiếu fingerprint đến với nó.
Các chỉ dấu headless quan trọng bao gồm: thiếu chrome.runtime (có ở Chrome giao diện nhưng vắng ở headless), mảng navigator.plugins có độ dài bằng không, các mẫu user agent cụ thể từng gắn với chế độ headless ở các phiên bản trước, và khác biệt trong cách Chrome headless xử lý context bảo mật của iframe.
Phương pháp phát hiện 4: Phân tích độ dài eval
Các engine JavaScript khác nhau có cách hiện thực khác nhau cho các hàm dựng sẵn, và những cách hiện thực đó có biểu diễn chuỗi khác nhau. Bằng cách kiểm tra độ dài của Function.prototype.toString.call(eval) và so sánh với giá trị đã biết cho từng engine trình duyệt, chúng tôi có thể phát hiện việc giả mạo môi trường — ví dụ, một instance Chrome headless đang giả vờ là Firefox.
Phương pháp phát hiện 5: Kiểm tra chéo TLS
Như đã bàn trong bài viết về TLS fingerprinting, thông điệp TLS Client Hello tiết lộ trình duyệt hay thư viện HTTP thực sự đang tạo kết nối. Khi một script Playwright điều khiển Chrome, TLS fingerprint khớp với Chrome — điều này là dự kiến. Nhưng khi một bot tùy biến dùng thư viện requests của Python hay net/http của Go, TLS fingerprint phơi bày sự lừa dối bất kể chuỗi user agent nào được gửi đi.
Phương pháp phát hiện 6: Phân tích thời gian và hành vi
Người dùng thật thể hiện sự biến thiên tự nhiên trong nhịp tương tác. Họ di chuyển chuột theo đường cong, không phải đường thẳng. Họ dừng lại trước khi nhấp. Họ cuộn ở tốc độ thay đổi. Các công cụ tự động, ngay cả những công cụ mô phỏng hành vi con người, cũng tạo ra những mẫu có thể phân biệt được về mặt thống kê — nhịp thời gian quá nhất quán, đường đi chuột thẳng hoàn hảo, và vận tốc cuộn không tự nhiên.
Chúng tôi thu thập tín hiệu hành vi tối thiểu ngay trong quá trình fingerprinting — thời điểm của các lệnh gọi API, thứ tự thu thập tín hiệu, và độ phản hồi của một số browser API. Những tín hiệu vi hành vi này khó để công cụ tự động giả mạo vì chúng phụ thuộc vào môi trường thực thi thực tế, chứ không phải vào các thuộc tính có thể ghi đè.
Phương pháp phát hiện 7: Mâu thuẫn về quyền và API
Trình duyệt thật có trạng thái quyền và mức độ khả dụng API nhất quán. Một trình duyệt tuyên bố hỗ trợ notification nhưng không có constructor Notification, hoặc báo cáo một độ phân giải màn hình cụ thể nhưng lại trả về giá trị khác từ window.screen và CSS media query, đang thể hiện những mâu thuẫn cho thấy có sự can thiệp hoặc mô phỏng.
Chúng tôi kiểm tra hàng chục điểm kiểm tra chéo như vậy, tìm những mâu thuẫn nảy sinh khi công cụ tự động ghi đè có chọn lọc một số tín hiệu mà không duy trì tính nhất quán trên tất cả các API liên quan.
Phương pháp phát hiện 8: Phát hiện máy ảo và mô phỏng
Nhiều chiến dịch bot chạy bên trong máy ảo hoặc cloud instance. Bản thân điều này không phải bằng chứng của tự động hóa, nhưng là một tín hiệu mạnh khi kết hợp với các chỉ dấu khác. Ở đây có hai thứ riêng biệt đáng được phân định rạch ròi, vì chúng thường bị gộp làm một.
Thứ nhất là render bằng phần mềm. Một máy không có GPU thật sẽ lùi về bộ rasterize phần mềm, và chuỗi renderer WebGL nói thẳng điều đó — "llvmpipe", "SwiftShader" cùng các biến thể của chúng gọi tên nó một cách trực tiếp. Đó là một chỉ dấu headless: nó cho biết về đường render, và nó tham gia vào phán quyết bot trên mọi gói.
Thứ hai là phát hiện máy ảo theo đúng nghĩa, vốn là năng lực của gói Enterprise. Nó đọc chuỗi renderer và vendor của WebGL để tìm chữ ký hypervisor — VMware, VirtualBox, Parallels, QEMU, Hyper-V — rồi đối chiếu chéo với những đặc tính phần cứng không phù hợp với thiết bị người dùng phổ thông: độ phân giải màn hình mặc định của máy ảo, một hoặc hai nhân CPU đứng sau một User-Agent desktop, hai gigabyte bộ nhớ hoặc ít hơn. Không dấu hiệu đơn lẻ nào tự quyết định; bộ phát hiện chấm điểm cho tổ hợp và báo cáo một con số tin cậy kèm theo những dấu hiệu đã kích hoạt. Các dải địa chỉ của datacenter và nhà cung cấp hosting, phân giải từ dữ liệu tình báo IP, bổ trợ từ phía mạng.
Không tín hiệu nào trong hai tín hiệu này tự thân là bằng chứng của tự động hóa — kiểm thử trình duyệt chạy trên cloud và desktop ảo không GPU đều là chính đáng — và đó là lý do cả hai đều tham gia vào phán quyết có trọng số thay vì tự mình kích hoạt việc chặn.
Lợi thế đa phương pháp
Mỗi phương pháp phát hiện riêng lẻ đều có hạn chế — một người vận hành bot tinh vi có thể né được bất kỳ phương pháp đơn lẻ nào. Nhưng né tất cả phương pháp cùng lúc, trong khi vẫn duy trì tính nhất quán của kiểm tra chéo trên toàn bộ, thì tốn kém đến mức không thể chấp nhận. Chi phí phát triển và duy trì một bot vượt qua mọi kiểm tra vượt quá giá trị kinh tế của hầu hết các chiến dịch bot.
Gần như không có false positive
Cơ chế phát hiện của chúng tôi vận hành theo mô hình danh sách trắng cho bot của công cụ tìm kiếm (Googlebot, Bingbot, v.v.) được xác minh qua reverse DNS, và mô hình đa tín hiệu cho lưu lượng khác. Chúng tôi yêu cầu nhiều tín hiệu bổ trợ trước khi phân loại lưu lượng là tự động. Đó chính là toàn bộ ý nghĩa của thiết kế thận trọng: một dấu hiệu mơ hồ đơn lẻ không bao giờ là đủ, nên một khách truy cập bình thường tình cờ vướng vào một phép kiểm tra sẽ không bị phân loại là bot.