Trang web không thể hỏi bạn có dùng trình chặn quảng cáo hay không — nó kiểm tra kết quả: phần tử mồi, yêu cầu bị chặn, hoặc biến script bị thiếu.
Không có API trình duyệt nào trả lời được câu hỏi "có trình chặn quảng cáo đang chạy không?". Một trang web không thể truy vấn điều đó trực tiếp như cách nó truy vấn múi giờ hay kích thước màn hình của bạn. Vì vậy, các trang muốn biết câu trả lời không hỏi — họ đặt một cái bẫy nhỏ và xem điều gì xảy ra với nó. Nếu cái bẫy còn nguyên, nghĩa là không có gì bị chặn. Nếu không, nghĩa là có thứ gì đó đã can thiệp.
Tóm tắt nhanh
- Một trang suy ra sự tồn tại của trình chặn quảng cáo từ kết quả, không phải từ một tín hiệu trực tiếp. Ba kiểm tra phổ biến là: một phần tử mồi mà các danh sách lọc được viết ra để ẩn đi, một yêu cầu mạng tới địa chỉ giống quảng cáo nhưng thất bại, và một biến toàn cục mà một script quảng cáo lẽ ra phải định nghĩa nhưng chưa kịp làm.
- Cùng những kiểm tra đó hoạt động dù trình chặn là tiện ích mở rộng kiểu truyền thống hay một engine quy tắc khai báo. Tiện ích hoạt động bằng script và các engine khai báo như WebKit Content Blockers trên iOS hay
declarativeNetRequestcủa Chrome đều áp dụng cùng các mẫu trong danh sách lọc, nên chúng để lại cùng một dấu vết có thể quan sát trên trang. - Bản thân việc phát hiện chỉ trả về một bit — "có gì đó đã can thiệp" — nhưng việc phần tử mồi nào bị dính có thể thu hẹp phạm vi hơn nữa. Các danh sách lọc khác nhau nhắm vào các tên class và mẫu URL khác nhau, nên việc mồi nào sống sót, mồi nào không, tự nó đã là một tín hiệu nhận diện nhỏ.
- Các kiểm tra dựa trên yêu cầu mạng có thể báo sai dù không hề cài trình chặn quảng cáo nào. Lọc ở cấp DNS, tính năng chống theo dõi có sẵn của trình duyệt hay proxy công ty đều có thể gây ra đúng kết quả "quảng cáo không tải được" — dù không cái nào trong số đó ẩn được phần tử mồi.
- Bài viết này nói về việc phát hiện, không phải về cách né tránh. Không có hướng dẫn nào ở đây về việc giấu trình chặn quảng cáo khỏi một trang web hay vượt qua tường chống-adblock — đó là một chủ đề đối kháng khác mà bài này không đề cập.
Ba kiểu kiểm tra đứng sau hầu hết mọi lần phát hiện trình chặn quảng cáo
Bỏ qua mọi biến thể, gần như mọi kiểm tra trình chặn quảng cáo trên web đều quy về một trong ba kiểu kiểm tra, chạy ngay sau khi trang tải xong.
Một phần tử mồi. Trang tạo ra một <div> (hoặc phần tử tương tự) với tên class và cấu trúc giống hệt một vị trí quảng cáo thật — kiểu như ad-banner, pub_300x250, text-ad, có kích thước và vị trí giống một khối chứa quảng cáo thật. Trang chèn nó vào rồi chờ một chút. Trình chặn quảng cáo hoạt động chủ yếu dựa trên các danh sách lọc (EasyList và những danh sách tương tự) khớp phần tử theo đúng kiểu bộ chọn này, nên một trình chặn thật sự sẽ ẩn hoặc xóa mồi cùng với bất kỳ quảng cáo thật nào khớp cùng mẫu. Sau đó trang kiểm tra xem mồi còn đó không: display có bị đặt thành none không, offsetHeight có về 0 không, hay node đã bị gỡ hoàn toàn khỏi DOM. Chỉ cần một trong các dấu hiệu đó xuất hiện là biết có thứ gì đó đã chặn nó. Công cụ kiểm tra tiện ích và plugin của BrowserInsight chạy đúng kiểu kiểm tra này: nó chèn một div nằm ngoài màn hình mang các class như pub_300x250, text-ad và ad-banner, chờ khoảng 100 mili giây, rồi đọc style đã tính toán và kích thước bố cục của nó.
Lưu ý rằng đây thuần túy là một kiểm tra hiển thị (cosmetic). Mồi được chính script của trang tạo ra ngay trên máy, không hề có yêu cầu mạng nào — chỉ thứ gì áp dụng quy tắc ẩn phần tử bên trong trang mới làm nó biến mất được.
Một yêu cầu mạng bị chặn. Thay vì theo dõi một phần tử, trang gửi một yêu cầu tới URL trông giống lời gọi quảng cáo hoặc theo dõi — một đường dẫn chứa /ads/, một tên host khớp với domain phát quảng cáo đã biết, một script mang tên giống một tag phân tích đã biết. Một trình chặn có quy tắc lọc mạng (không chỉ ẩn về mặt hình ảnh) sẽ chặn yêu cầu trước khi nó rời khỏi trình duyệt, hoặc trình duyệt báo phản hồi thất bại. Script của chính trang nhìn thấy lỗi đó — một fetch bị từ chối, một ảnh kích hoạt onerror thay vì onload — và coi đó là tín hiệu.
Một biến toàn cục bị thiếu. Các script phát quảng cáo thật, một khi tải thành công, thường định nghĩa thứ gì đó ở phạm vi toàn cục — một hàm, một đối tượng cấu hình, một cờ mà mã của chính nhà xuất bản kiểm tra trước khi tiếp tục. Nếu bản thân script quảng cáo bị chặn không tải được, biến toàn cục đó sẽ không bao giờ được định nghĩa. Trang kiểm tra sự tồn tại của nó ngay tại thời điểm thẻ script lẽ ra đã chạy xong; undefined nghĩa là script chưa từng chạy.
Cả ba cách đều có chung một hình dạng: đặt ra một kỳ vọng chỉ đúng khi không có gì can thiệp, rồi kiểm tra xem kỳ vọng đó có đúng không. Không cái nào hỏi trình duyệt một câu hỏi trực tiếp, vì đơn giản là không có câu hỏi nào để hỏi.
Vì sao nó hoạt động giống nhau với mọi loại trình chặn
Sẽ hợp lý nếu cho rằng một tiện ích mở rộng và một trình chặn có sẵn không cần tiện ích nào trông sẽ hoàn toàn khác nhau dưới mắt một bộ phát hiện. Trên thực tế thì không, và lý do là cả hai đang thực thi cùng những quy tắc trong danh sách lọc, chỉ khác cơ chế.
Một tiện ích chặn quảng cáo truyền thống chèn content script và stylesheet để ẩn hoặc xóa các phần tử khớp, đồng thời có thể chặn trực tiếp các yêu cầu mạng. Một engine chặn khai báo (declarative) hoạt động khác ở bên dưới nhưng cho ra cùng một kết quả: trình duyệt được trao trước một danh sách quy tắc đã biên dịch và tự thực thi nó, mà mã của trình chặn không cần soi từng trang. WebKit Content Blockers, ra mắt cho Safari và là nền tảng của mọi ứng dụng chặn nội dung trên iOS, hoạt động theo cách này — ứng dụng cung cấp một danh sách quy tắc JSON, và WebKit áp dụng nó ở cấp engine cho mọi trang được tải sau đó. Các quy tắc này vừa có thể chặn tài nguyên, vừa có thể ẩn phần tử theo bộ chọn CSS (hành động css-display-none), nên chúng kích hoạt được cả kiểm tra mạng lẫn kiểm tra mồi. Nền tảng tiện ích của Chrome cũng đang đi theo hướng tương tự: declarativeNetRequest cho phép một tiện ích trao cho trình duyệt một tập quy tắc tĩnh hoặc động thay vì kiểm tra từng yêu cầu bằng JavaScript, và theo Manifest V3 đây là mô hình Chrome yêu cầu các tiện ích chặn mạng sử dụng. (Việc ẩn phần tử trong trình chặn MV3 vẫn thực hiện qua CSS được chèn vào, nhưng danh sách lọc đứng sau vẫn là một.)
Cơ chế khác nhau — một danh sách quy tắc đã biên dịch do engine thực thi, so với một script theo dõi trang — nhưng kết quả mà một trang có thể quan sát được lại giống nhau ở cả hai trường hợp: một phần tử mồi khớp quy tắc lọc bị ẩn hoặc xóa, một yêu cầu khớp quy tắc lọc không tải được. Một bộ phát hiện được xây quanh kết quả, chứ không phải cơ chế, không cần biết hay quan tâm nó đang đối mặt với loại trình chặn nào. Đó cũng là lý do vì sao một trình chặn quảng cáo di động "chỉ" là một content blocker cho Safari, không thể chạy script hay đọc nội dung trang, vẫn kích hoạt đúng kiểm tra phần tử mồi giống hệt một tiện ích trên desktop.
Nó tiết lộ điều gì
Tự thân một kết quả dương tính từ kiểu kiểm tra này gần như chỉ là một bit: đúng, có thứ gì đó đang lọc trang này, hoặc không. Một bit đó đã hữu ích với chính trang web — nó là công tắc kích hoạt tường chống-adblock, hay banner "vui lòng đưa chúng tôi vào danh sách trắng" — nhưng tự nó không phải tín hiệu nhận diện mạnh, vì quá nhiều khách truy cập cho cùng một câu trả lời.
Điều làm nó trở nên chính xác hơn là chạy nhiều hơn một phần tử mồi cùng lúc, mỗi cái được thiết kế theo quy ước của một danh sách lọc khác nhau. Một bộ phát hiện đặt năm div mồi cùng lúc — một theo mẫu chung của EasyList, một theo quy ước của một danh sách khu vực, một theo quy tắc chỉ có trong danh sách chặn phiền toái (annoyance) khắt khe hơn — và kiểm tra từng cái độc lập thì không chỉ biết "bị chặn: có". Nó còn biết những mẫu nào đã dính, và các gói đăng ký danh sách lọc khác nhau đủ nhiều giữa các người dùng để tổ hợp cụ thể đó thu hẹp đám đông mà bạn hòa lẫn vào. Đó chính là phép toán entropy đứng sau bất kỳ tín hiệu nhận diện nào: một tổ hợp kết quả hiếm gặp mang tính nhận diện cao hơn một tổ hợp phổ biến — đúng như hướng dẫn của chúng tôi về entropy dấu vân tay và tập ẩn danh đã trình bày cho các tín hiệu nói chung. Phát hiện trình chặn quảng cáo chỉ là một ví dụ nhỏ, entropy thấp, của cùng ý tưởng đó — đáng giá vài bit, không phải một mã định danh độc lập.
Cũng cần nói rõ kỹ thuật này không phải là gì. Nó khác với việc phát hiện chính xác bạn cài những tiện ích mở rộng nào — kỹ thuật đó hoạt động bằng cách dò các tệp tài nguyên mà chính tiện ích mở rộng để lộ, hoặc các tác dụng phụ đặc trưng của nó trên trang, một kỹ thuật nhắm mục tiêu chính xác hơn nhiều vào một tiện ích cụ thể. Phát hiện trình chặn quảng cáo không cần biết sản phẩm nào chịu trách nhiệm; nó chỉ cần biết có thứ gì đó đã can thiệp vào cái mồi nó đặt ra.
Báo sai: khi kiểm tra kích hoạt dù không hề có trình chặn nào
Vì kiểu kiểm tra này theo dõi kết quả thay vì hỏi một câu trực tiếp, bất cứ thứ gì tạo ra cùng kết quả cũng kích hoạt nó — và một vài cấu hình hoàn toàn bình thường, không liên quan đến tiện ích mở rộng, lại làm đúng điều đó. Tuy nhiên, cần phân biệt chúng kích hoạt kiểm tra nào: thứ gì hoạt động ở tầng mạng có thể làm kiểm tra yêu cầu bị chặn và kiểm tra biến toàn cục báo động, nhưng không thể đụng tới phần tử mồi mà trang tự tạo ngay trên máy.
- Chặn quảng cáo ở cấp mạng. Một Pi-hole trong mạng nhà, một bộ phân giải DNS có lọc, hay một trình chặn ở cấp router khiến yêu cầu quảng cáo không bao giờ tới được máy chủ quảng cáo — thiết bị không hề cài tiện ích nào, nhưng script quảng cáo vẫn tải thất bại và biến toàn cục của nó không xuất hiện, y như khi bị tiện ích chặn.
- Tính năng chống theo dõi có sẵn của trình duyệt. Enhanced Tracking Protection của Firefox mặc định chặn nội dung theo dõi đã biết trong cửa sổ riêng tư, và ở chế độ Nghiêm ngặt thì chặn trong mọi cửa sổ, không cần tiện ích nào. Nếu "quảng cáo" mà bộ phát hiện tải về nằm trên một domain thuộc danh sách theo dõi nó dùng, yêu cầu đó cũng thất bại.
- Trình duyệt có sẵn trình chặn quảng cáo. Brave Shields, cùng các trình chặn tích hợp trong những trình duyệt như Opera và Vivaldi, tự áp dụng danh sách lọc. Tùy cài đặt, trong đó có thể có cả quy tắc ẩn phần tử — nên chúng có thể kích hoạt cả kiểm tra phần tử mồi dù bạn không cài gì.
- Proxy công ty hoặc trường học. Nhiều mạng được quản lý định tuyến lưu lượng qua một proxy có lọc, loại bỏ luôn các domain quảng cáo và theo dõi như một tác dụng phụ của chính sách nội dung rộng hơn, không liên quan gì đến việc người dùng tự cài đặt gì.
- Bộ phân giải DNS vạch trần trình theo dõi ngụy trang. Một số dịch vụ DNS có lọc còn đi xa hơn, lần theo bản ghi CNAME để nhận ra trình theo dõi dùng CNAME cloaking — trình theo dõi bên thứ ba nấp sau một subdomain trông như của bên thứ nhất. Nhờ vậy, một lời gọi quảng cáo hoặc theo dõi vẫn có thể bị chặn dù URL của nó trông như địa chỉ bên thứ nhất vô hại.
Không trường hợp nào trong số này có tiện ích mở rộng được cài đặt, vậy mà mỗi trường hợp đều có thể khiến trang kết luận "đã phát hiện trình chặn quảng cáo". Một trang web coi tín hiệu này là bằng chứng chắc chắn về một tiện ích đã cài đặt là đang đưa ra suy luận mà dữ liệu không hề chứng minh được — nó chỉ thực sự biết rằng đâu đó giữa trang và máy chủ quảng cáo, có thứ gì đó đã can thiệp.
Điều mà việc phát hiện không nói cho trang web biết
Đáng để nói rõ ranh giới này, vì rất dễ thổi phồng những gì một kiểm tra mồi thành công hay thất bại thực sự chứng minh được. Trang chạy kiểm tra này không biết bạn cài tiện ích nào, nếu có — điều đó cần đến các kỹ thuật dò tiện ích chính xác hơn được nêu trong hướng dẫn về quyền riêng tư của tiện ích mở rộng của chúng tôi. Nó cũng không biết danh tính hay lịch sử duyệt web của bạn. Và, như danh sách báo sai ở trên đã cho thấy, chỉ dựa vào một yêu cầu thất bại thì nó không thể phân biệt một tiện ích mở rộng với việc lọc ở cấp mạng, cài đặt quyền riêng tư nghiêm ngặt của trình duyệt, hay proxy của một mạng được quản lý. Nhiều nhất nó biết được là một số ít bit về việc những mẫu quan sát được nào đã bị can thiệp trong lần tải trang cụ thể đó.
Bài viết này nói về cách suy luận đó được xây dựng và nó có thể chứng minh — hay không thể chứng minh — điều gì, chứ không phải hướng dẫn để né kiểm tra. Cuộc đấu liên tục giữa những người viết danh sách lọc và các nhà cung cấp giải pháp chống-adblock là một chủ đề khác, nằm ngoài phạm vi bài này; không có gì ở trên là công thức để giấu trình chặn quảng cáo khỏi một trang web hay lách qua một tường chống-adblock.
Xem chính cấu hình của bạn tiết lộ điều gì
Công cụ kiểm tra tiện ích và plugin của BrowserInsight chạy một kiểm tra phần tử mồi song song với các kiểm tra tiện ích mở rộng, nhờ đó bạn có thể tự mình thấy điều một trang web nhìn thấy khi kiểm tra trình duyệt của bạn theo cách này. Vì đây là kiểm tra hiển thị, một trình chặn chỉ hoạt động ở tầng mạng như Pi-hole sẽ không hiện ra ở đây. Nếu kết quả khiến bạn bất ngờ — bị chặn dù không cài tiện ích nào, hoặc không bị chặn dù có cài — hãy xem trình duyệt của bạn có trình chặn tích hợp không, hoặc tiện ích có đang tắt tính năng ẩn phần tử hay đưa trang này vào danh sách cho phép không. Để thấy bức tranh lớn hơn về cách một kiểm tra như thế này khớp vào toàn bộ dấu vân tay trình duyệt, hãy xem kiểm tra dấu vân tay — nơi hiển thị phần còn lại những gì một trang có thể quan sát được về cấu hình của bạn.
Câu hỏi thường gặp
Một trang web có thể biết chính xác tôi đang dùng trình chặn quảng cáo nào không?
Không, ít nhất không phải từ các kiểm tra dựa trên kết quả như phần tử mồi hay yêu cầu thất bại. Những kiểm tra đó chỉ xác định rằng có thứ gì đó đã can thiệp vào nội dung hoặc yêu cầu giống quảng cáo — chúng không thể xác định tiện ích cụ thể hay cơ chế chặn nào chịu trách nhiệm. Để chỉ đích danh một tiện ích cụ thể cần một kỹ thuật khác, nhắm mục tiêu chính xác hơn vào dấu vết riêng của tiện ích đó.
Điều này có hoạt động giống nhau trên di động và desktop không?
Có, với các trình chặn khai báo. Một ứng dụng chặn nội dung trên iOS xây trên WebKit Content Blocker API tạo ra kết quả quan sát được giống hệt một tiện ích mở rộng trên desktop — phần tử mồi bị ẩn, yêu cầu quảng cáo thất bại — dù nó không hề có khả năng chạy script trên trang. Bộ phát hiện không cần biết cơ chế cụ thể nào đang chịu trách nhiệm.
Tôi có thể bị phát hiện là dùng trình chặn quảng cáo dù không hề cài đặt cái nào không?
Có. Lọc ở cấp mạng (trình chặn DNS tại nhà, proxy công ty) và tính năng chống theo dõi có sẵn của trình duyệt có thể làm kiểm tra yêu cầu bị chặn hoặc kiểm tra biến toàn cục báo động, còn một trình duyệt có sẵn trình chặn quảng cáo như Brave thì có thể kích hoạt cả kiểm tra phần tử mồi — tất cả đều không cần cài tiện ích mở rộng nào.
Việc bị phát hiện dùng trình chặn quảng cáo có phải rủi ro riêng tư lớn không?
Tự thân nó là một tín hiệu nhỏ — gần với một bit hơn là một dấu vân tay. Nó chỉ trở nên nhận diện rõ hơn khi một trang chạy cùng lúc nhiều phần tử mồi được thiết kế khác nhau và ghi lại chính xác cái nào bị dính, vì mẫu hình đó khác nhau giữa người dùng nhiều hơn hẳn một câu trả lời có/không đơn giản.

