Chuyển đến nội dung

Thiết lập khuyến nghị — nên bật gì và nên để nguyên gì

Phần lớn các trường hợp bị chặn mà chúng tôi truy ra nguyên nhân nằm ở cấu hình đều là do giả mạo nhiều hơn, chứ không phải ít hơn. Trang này là bản tóm tắt những gì chúng tôi đã đo: các thiết lập đáng dùng, những thiết lập mà cái giá phải trả lớn hơn lợi ích mang lại, và một số ít vấn đề mà không thiết lập nào khắc phục được.

Bắt đầu từ đây

Nếu bạn không đọc gì khác trên trang này, thì đây là cấu hình để bắt đầu. Nó thay đổi những trục có thể thay đổi một cách an toàn, và giữ nguyên phần render, TLS và phiên bản trình duyệt.

javascript
import { launch } from "clearcote";

const browser = await launch({
  lightStealth: true,        // metadata identity only — rendering, TLS and version stay real
  fingerprint: "account-42", // picks this identity's metadata bundle; keep it stable per identity
  proxy: { server: "http://gateway:8080", username: "u", password: "p" },
  geoip: true,               // timezone + languages + the address WebRTC reports follow the proxy exit
  humanize: true,            // trusted native input; navigator.webdriver stays false
});

Python có cùng bộ API, viết theo snake_case: light_stealth, fingerprint, geoip, humanize. Hãy thêm các trục khác một cách có chủ đích, từng trục một, và chỉ khi bạn nói được thứ gì trên host sẽ xác nhận cho chúng. Một số dòng bên dưới — các control hẹp của r12, humanize bằng chuyển động được ghi lại, socks5Udp, các switch về cookie bên thứ ba và proxy — áp dụng cho bản build có giấy phép (Miễn phí với GitHub hoặc Pro). Bản build mở bỏ qua chúng: humanize quay về dùng đường di chuyển được sinh ra, và proxy SOCKS5 có mật khẩu sẽ từ chối kết nối.

Nguyên tắc: mỗi giá trị giả mạo là một lời khẳng định mà host phải chứng minh được

Cơ chế phát hiện không đi tìm các giá trị bất thường. Nó đi tìm mâu thuẫn — hai tín hiệu không thể cùng đúng trên một máy. Một giá trị bình thường mà không ai giả mạo thì không mâu thuẫn với điều gì. Một giá trị giả mạo mà không có gì đứng sau lại là một tín hiệu dương tính, và còn là tín hiệu mạnh hơn cả giá trị mà nó đang che giấu.

Vì vậy, câu hỏi hữu ích trước khi bật bất kỳ tùy chọn nào không phải là “giá trị này có hợp lý không?” mà là “trên máy này có gì có thể được hỏi để xác nhận nó, và câu trả lời có khớp không?” Kích thước màn hình được đối chiếu với bề mặt render. Chuỗi GPU được đối chiếu với các pixel mà GPU tạo ra. Hệ điều hành được khai báo được đối chiếu với các font mà nền tảng phân giải. Nếu host không chứng minh được lời khẳng định đó, thì giá trị thật là lựa chọn an toàn hơn. Xem Cơ chế phát hiện hoạt động thế nào để hiểu chi tiết.

Nên làm

Thiết lậpLý do
lightStealth: trueChỉ áp dụng một tập giá trị nhất quán, suy ra từ seed, cho các trục metadata — hardwareConcurrency, deviceMemory, colorDepth, devicePixelRatio, maxTouchPoints — thông qua các switch native đơn giá trị. Output canvas, WebGL và audio, TLS và phiên bản trình duyệt thật được giữ nguyên. Seed chỉ quyết định danh tính nhận bundle nào trong một tập nhỏ, và không có noise khi render, nên các tài khoản trên cùng một máy có chung canvas hash. Trên màn hình có scale hoặc cấu hình bất thường, hãy kiểm tra pixel ratio mà bundle chọn so với màn hình thật của bạn trên trang audit.
Mỗi danh tính một seed fingerprint ổn địnhCùng seed ⇒ cùng danh tính. Dùng lại seed đó suốt vòng đời của tài khoản. Xoay seed theo từng request khiến một tài khoản đã đăng nhập lần nào cũng đến từ một máy mới, và đó là tín hiệu lộ liễu hơn nhiều so với bất kỳ giá trị nào đang được xoay. Với nhiều tài khoản trên một máy mà không được dùng chung canvas, hãy dùng persona theo seed (bỏ lightStealth) để mỗi tài khoản có noise render riêng.
geoip: true ở mọi lần launchMúi giờ, ngôn ngữ và địa chỉ mà WebRTC báo cáo đi theo IP đầu ra — dù có proxy hay không (hoặc tự đặt timezone và acceptLanguage). Nếu không dùng cách nào trong hai cách này, SDK mặc định là New York và en-US. Một IP đầu ra dân cư ở Mỹ mà báo Europe/Amsterdam thì chỉ cần một dòng code để phát hiện, và đây là kiểu lệch rất dễ vô tình mắc phải. Nếu không xác định được khu vực, lần launch sẽ dừng với GeoipError thay vì khởi động theo đồng hồ của máy này — hãy sửa proxy hoặc tăng CLEARCOTE_GEOIP_TIMEOUT_SECONDS.
humanize: trueInput được tạo dưới dạng các native event đáng tin cậy (trusted) trên những đường di chuyển con trỏ giống người (chuyển động ghi lại từ người thật cho các cú nhấp theo tọa độ trên Pro, còn lại là đường được sinh ra). Đừng tự chồng thêm easing theo từng bước lên trên — hãy đặt các waypoint và để humanize nội suy; easing tự viết tạo ra thống kê chuyển động mà input nguyên bản không bao giờ tạo ra.
widevine: true khi dùng brand ChromePersona mặc định tự nhận là Google Chrome, vốn trả lời được truy vấn Widevine DRM. Không có CDM, truy vấn sẽ bị từ chối, và bất kỳ trang nào cũng đọc được điều đó. Xem Widevine & DRM.
allowThirdPartyCookies: true nếu đăng nhập nhúng hoặc challenge bị lỗiBản nền đã loại bỏ Google chặn cookie bên thứ ba, trong khi Chrome nguyên bản cho phép. Khi đó các frame đăng nhập, thanh toán và challenge nhúng dựa vào chúng sẽ lỗi theo cách mà một trình duyệt bình thường không gặp (bản build có giấy phép, 152 r22+).
Mỗi danh tính một persistent contextCookie, dữ liệu lưu trữ của site và cache là một phần của danh tính. Một máy mà lần truy cập nào cũng như chưa từng thấy site đó bao giờ thì bản thân điều đó đã là một pattern.
Chạy headful dưới Xvfb trong containerChrome có giao diện (headed) tránh được hoàn toàn các dấu hiệu của chế độ headless. Image chính thức mặc định chạy theo cách này.
Chạy trên hệ điều hành mà bạn định khai báoCác từ khóa system font của CSS2 do nền tảng bên dưới trình duyệt trả lời, chứ không phải bất cứ thứ gì mà trang hay user agent kiểm soát, nên đổi user agent cũng không thay đổi được chúng. Nếu không làm được như vậy, hãy giữ nguyên font bundle Linux — xem bên dưới.
tlsProfile để ở match-personaClientHello đi theo phiên bản Chrome mà persona khai báo, nên tầng mạng và UA khớp nhau. Giá trị mặc định đã đúng; lý do nên biết tùy chọn này tồn tại là để tránh ghim nó vào một giá trị mâu thuẫn với phiên bản brand của bạn.

Nên tránh

Mỗi mục dưới đây là điều chúng tôi đã đo được là gây lỗi, không phải một lời cảnh báo chung chung.

TránhVấn đề xảy ra
Giả mạo screen / avail* trên một host có màn hình không khớpMột kích thước màn hình giả không thể khớp được với cửa sổ và bề mặt render thật là thứ kích hoạt việc chặn một cách ổn định trên các hệ thống chống bot nghiêm ngặt nhất. Đây chính là lý do kích thước màn hình không thuộc lightStealth và chỉ được bật khi bạn chủ động chọn (opt-in). Nếu bạn có đặt, hãy đặt trọn bộ nhất quán — screenWidth, screenHeight, availWidth, availHeight — và chừa một khoảng taskbar hợp lý thay vì để avail bằng screen. Ở chế độ headless, SDK đã tự chọn sẵn một màn hình hợp lý cho bạn.
Khai báo GPU trên một host render bằng phần mềmTrên container, hoặc cloud VM rasterize qua WARP, SwiftShader hay llvmpipe, một persona khai báo GPU desktop là đang mô tả một con chip không thể tạo ra những pixel mà trang đọc lại được. Từ bản build có giấy phép 150 r12 (bản build mở bỏ qua tùy chọn này), gpuStringSpoof: false báo cáo WebGL vendor và renderer thật của host mà vẫn giữ nguyên mọi thứ khác — trên phần cứng đó, đây thường là sự đánh đổi tốt hơn. Lưu ý điểm hạn chế: WebGPU vẫn đi theo disableGpuFingerprint rộng hơn, nên nếu chỉ dùng switch hẹp này thì navigator.gpu vẫn tiếp tục mô tả persona trong khi WebGL báo cáo thiết bị thật.
Dùng disableGpuFingerprint hoặc fingerprintNoise: false chỉ để thay đổi một thứCả hai đều là bundle. disableGpuFingerprint thay đổi các chuỗi và bảng tham số và farble của readPixels và việc ẩn các trường persona; fingerprintNoise: false tắt noise canvas 2D và WebGL cùng lúc. Từ bản build có giấy phép 150 r12 đã có các control hẹp: gpuStringSpoof: false chỉ cho các chuỗi và canvasNoise: false chỉ cho canvas 2D. Cả hai control hẹp đều có cái giá cần biết: gpuStringSpoof: false thay đổi chuỗi WebGL nhưng không thay đổi navigator.gpu, nên WebGL và WebGPU rốt cuộc nêu tên hai vendor khác nhau trên cùng một trang — điểm số thì đẹp nhưng nhìn kỹ lại lộ. Còn canvasNoise: false đi cùng một seed sẽ loại bỏ hoàn toàn canvas riêng theo từng tài khoản. Hãy ưu tiên switch rộng disableGpuFingerprint, vốn thay đổi WebGL và WebGPU cùng nhau.
Xoay danh tính giữa chừng một phiênĐổi seed, IP đầu ra của proxy hay múi giờ trong lúc phiên đang chạy sẽ mâu thuẫn với chính phần phiên trước đó. Hãy xoay giữa các danh tính, đừng bao giờ xoay bên trong một danh tính.
Persona Windows trên Linux khi font bundle đã bị gỡ bỏBản phát hành Linux đi kèm các bản clone tương thích về metric (Segoe UI→Selawik, Arial→Arimo, Times New Roman→Tinos, …) và SDK nối chúng vào qua FONTCONFIG_FILE khi launch. Nếu gỡ chúng đi, hoặc build một image tùy chỉnh bỏ mất <binDir>/fonts/, thì tất cả các họ font Windows mà persona khai báo sẽ sụp về cùng một font mặc định. Điều này lộ ra mà không cần dữ liệu tham chiếu nào: hai kiểu chữ mà Windows cung cấp như hai font riêng biệt lại đo ra kích thước giống hệt nhau.
Chồng thêm một plugin stealth bằng JSCác control của Clearcote được biên dịch vào engine. Thêm một lớp shim ở mức script lên trên chúng sẽ đưa trở lại đúng cái lớp tự làm lộ mình mà cách tiếp cận ở cấp engine sinh ra để loại bỏ — một getter bị ghi đè khi chuyển thành chuỗi sẽ ra mã nguồn của chính nó, và chỉ một lệnh toString() là đọc được.
Persona di động trên engine desktop, dùng mà không kèm lưu ýplatform: "android" thay đổi UA, touch, loại con trỏ, màn hình và viewport, nhưng pixel vẫn đến từ GPU desktop (dưới một tên GPU di động) và hình học chi tiết của trang vẫn là của desktop. Đây là persona ở mức best-effort; hãy coi bề mặt render là phần bạn vẫn phải tự giải quyết.

Proxy

Proxy thường quyết định kết quả nhiều hơn bất kỳ cờ trình duyệt nào, và lại là thứ hay bị để mặc định nhất.

  • IP đầu ra cố định (sticky). Mỗi danh tính một IP đầu ra, giữ nguyên trong suốt phiên. Một phiên có IP thay đổi giữa chừng sẽ tự mâu thuẫn với chính nó, bất kể fingerprint tốt đến đâu.
  • Khớp vị trí địa lý với persona, rồi để geoip: true suy ra múi giờ và ngôn ngữ thay vì tự đặt bằng tay.
  • Proxy có thông tin đăng nhập được giao cho engine xử lý. Mật khẩu proxy HTTP(S) do chính trình duyệt trả lời (bản build có giấy phép 151 r19+, SDK Python & Node), nên page cache vẫn bật và request không bị đánh dấu bởi interception. SOCKS5 có mật khẩu hoạt động trực tiếp trên bản build có giấy phép — hãy truyền username và password thành các trường riêng. transparentProxy: true (152 r22+) ẩn proxy khỏi request header và timing của kết nối.
  • Hiểu rõ sự đánh đổi của WebRTC. Chromium không bao giờ gửi media qua proxy HTTP hay SOCKS, nên nếu không xử lý thì lưu lượng peer sẽ đi qua kết nối thật của bạn, nơi một relay có thể đọc được địa chỉ thật của bạn. Vì vậy SDK chặn các gói WebRTC UDP không đi qua proxy. Trên bản build mở, geoip / webrtcIp gỡ bỏ việc chặn đó; bản build có giấy phép thì vẫn giữ. Hãy kết hợp với geoip: true (hoặc webrtcIp) để trang vẫn thấy các candidate mà một Chrome thật tạo ra, báo cáo địa chỉ của proxy; không có nó, WebRTC không thu thập được gì, và điều đó trông như đã bị chặn. Để có kết nối peer hoạt động qua proxy SOCKS5, hãy đặt socks5Udp: true (bản build có giấy phép; nhà cung cấp của bạn phải cho phép relay UDP), hoặc dùng một tunnel toàn phần (WireGuard/OpenVPN) không có proxy trình duyệt và tự truyền --webrtc-ip-handling-policy trong args. Ngoài những trường hợp đó, hãy giữ chính sách chặn mặc định.

Những gì thiết lập không khắc phục được

Một số bề mặt bị đọc nhiều nhất lại do chiếc máy bạn thuê quyết định, chứ không phải trình duyệt bạn chạy trên đó.

Bề mặtNhững gì host quyết định
RenderHost không có GPU sẽ rasterize bằng phần mềm. Mọi sản phẩm trong nhóm này đều chỉ còn hai lựa chọn: hoặc khai báo phần cứng không render được, hoặc thừa nhận rasterizer phần mềm. Nếu pixel render ra là điều quan trọng với mục tiêu của bạn, cách khắc phục là một host có GPU — hoặc canvas bridge, thứ chuyển công việc render sang một host như vậy.
FontDanh sách font bị giới hạn bởi những gì host thực sự vẽ được — kể từ bản build có giấy phép 150 r12, danh sách chuẩn được lấy từ ba nghìn máy thật và vẫn được giao với tập font của host, nên trang không bao giờ được báo về một font không render được. Trên Linux, SDK dùng font bundle đi kèm trình duyệt và bỏ qua các font cài trên host, nên cài thêm package vào image cũng không thay đổi những gì trang nhìn thấy. Bundle của bản build mở không có font CJK, nên văn bản tiếng Trung, tiếng Nhật và tiếng Hàn ở đó hiển thị thành glyph bị thiếu; bundle của bản build có giấy phép thì có. Trên Windows, font của chính host được sử dụng. Các font trông giống font Windows trong bundle giúp độ rộng chữ trông hợp lý, nhưng trang cũng có thể nạp font theo tên bằng local(), và một font trông giống thì không mang tên thật: khi đo với persona Windows trên Linux, Segoe UI và Georgia được đo là đã cài nhưng không nạp được.
Bộ scale chữ (text scaler)Mỗi glyph được định kích thước bởi font scaler của hệ điều hành: DirectWrite trên Windows, FreeType trên Linux. Không thiết lập nào can thiệp được vào nó. Tăng cỡ chữ theo từng bước 0,01 px làm thay đổi độ rộng văn bản ở 99% số bước trên Windows và 66% trên Linux, và một host Linux giả làm Windows vẫn cho ra 66%. Nếu một trang đọc kỹ văn bản của bạn, hãy chạy trên đúng hệ điều hành mà bạn khai báo. Xem font stack bên dưới user agent.

Kiểm tra thay vì phỏng đoán

Mọi khẳng định trên trang này đều đo được từ bên trong trình duyệt. Hãy trỏ phiên đã cấu hình của bạn tới trang audit và đọc những dòng mà nó báo là không khớp — đó cũng chính là bộ công cụ chúng tôi đã dùng để tìm ra các vấn đề mô tả ở trên, và nó sẽ cho bạn biết cấu hình hiện tại của bạn đang vi phạm khuyến nghị nào trong số này.