Profobuf (2022): Giải mã và loại bỏ quảng cáo để chặn quảng cáo YouTube trên Apple TV
(ericdraken.com)- Đây là một PoC đặt proxy MITM dựa trên pfSense giữa Apple TV và Internet để giải mã HTTPS, rồi chỉnh sửa các phản hồi Protobuf do YouTube gửi xuống nhằm ngăn các slot quảng cáo được đăng ký trên thiết bị Apple
- Các trình chặn DNS và định tuyến VPN hiện có vấp phải những giới hạn như DNS TTL, sai lệch IP, lỗi 403 và rò rỉ ASN, do quảng cáo YouTube và video chính dùng cùng domain và hạ tầng
- Thử nghiệm với Squid bị dừng vì vấn đề hiệu năng và cấu hình; sau đó chuyển sang cách dùng mitmproxy/mitmdump trong FreeBSD jail để giải mã lưu lượng TLS và sửa trực tiếp các phản hồi JSON/Protobuf
- YouTube bản web có thể loại bỏ
adPlacements,playerAdParams, URLpageadtrong JSON, v.v., nhưng ứng dụng YouTube trên iOS chứa slot quảng cáo và thông tin theo dõi trong phản hồiapplication/x-protobuf, nên phải xử lý cấu trúc Protobuf - Cách cuối cùng là quét tuyến tính và sửa 1 byte: tìm ngược field tag gần chuỗi
/pagead/, rồi đổi các tag như50195462thànhtarget_field_tag - 1; cách này đủ hiệu năng để xử lý thời gian thực mà không cần giải mã toàn bộ
Mục tiêu và thiết kế mạng ban đầu
- Mục tiêu là tạo một router dựa trên FreeBSD và pfSense để chặn quảng cáo YouTube pre-roll, mid-roll và end-roll trên Apple TV và iPhone ở phạm vi toàn mạng
- Nếu đặt một proxy man-in-the-middle giữa Apple TV và Internet bên ngoài, có thể giải mã lưu lượng HTTPS và đọc dữ liệu Protocol Buffer mà Google dùng để lấp đầy quảng cáo YouTube
- Sau vài tháng triển khai chặn quảng cáo YouTube, tác giả bắt đầu trả tiền cho YouTube Premium và nói rằng “có thể làm” khác với “nên làm”
- Các lý do chặn quảng cáo/theo dõi được nêu gồm theo dõi dữ liệu cá nhân, lãng phí băng thông, clickbait và cryptojacking
- Tác giả cho rằng 25–40% lưu lượng mạng có thể là quảng cáo, script theo dõi, fingerprint.js, googletagmanager.js và các loader phân tích thời gian thực như Hotjar
- Tác giả giải thích rằng JavaScript đào tiền mã hóa như CoinHive.js có thể làm máy tính quá nhiệt hoặc bị lạm dụng để kiếm những khoản tiền nhỏ
Phần cứng pfSense và thiết lập cơ bản
- Để bảo vệ toàn bộ mạng SMB, tác giả cho rằng VM, image Docker hay Raspberry Pi không đủ hiệu năng, nên cần phần cứng chuyên dụng chỉ đảm nhiệm định tuyến gói tin, giải mã và giám sát
- Phần cứng router được dùng gồm mini PC có tập lệnh AES-NI, RAM DDR4, SSD mSATA và USB để flash pfSense
- Cấu hình ví dụ là mini PC J4125, RAM DDR4 32GiB và SSD mSATA 128GiB
- Dung lượng lưu trữ 128GB được xem là đủ cho log, giảm wear của SSD, bắt gói tin và cache biên NPM/Docker
- Image cài đặt pfSense khoảng 360MB và có thể flash vào USB bằng Etcher AppImage
- Sau thiết lập đầu tiên, AES-NI hiển thị là “Yes (inactive)”, nên tác giả bật thủ công trong
System › Advanced › Miscellaneous - Để tận dụng RAM 32GiB, tác giả cấp phát rộng rãi RAM disk cho
/varvà/tmp, đồng thời cấu hình sao lưu RAM disk mỗi giờ với kỳ vọng SSD 128GiB có wear-leveling - Trên Dashboard, tác giả thêm widget S.M.A.R.T. để có thể phát hiện bất thường của SSD
Chặn DNS, tách mạng và pfBlockerNG
- Trước đây tác giả dùng Pi-hole trên Raspberry Pi làm trình chặn quảng cáo ở mức DNS; trên pfSense, tác giả cài pfBlockerNG-devel để thử chặn quảng cáo/nội dung độc hại và geo-blocking
- Nếu dịch vụ pfb_dnsbl không khởi động hoặc tab status hiển thị
[ Missing CRON task ], tác giả khuyên thử xóa file rỗng/var/run/booting - Tận dụng 3 cổng Gigabit của mini PC, tác giả tạo các mạng vật lý thay vì VLAN, và tách các thiết bị “phoning-home” như Alexa và Apple TV khỏi mạng chính
- Thiết bị untrusted được đặt trong mạng riêng
172.31.1.0/24 - LAN trusted được giữ ở
192.168/16 - LAN phần cứng dành cho IoT đi qua adblocker, đồng thời cố chặn YouTube vượt qua trình chặn DNS bằng cách chặn bắt các truy vấn DNS hard-coded như
1.1.1.1và9.9.9.9
- Thiết bị untrusted được đặt trong mạng riêng
- Tác giả cấu hình quy tắc NAT để mọi client phía sau pfSense dùng máy chủ Unbound DNS cục bộ
- Tác giả cho rằng phải chặn DNS over TLS trước thì mới có thể chặn bắt truy vấn DNS
- iPhone có thể hiển thị Privacy Warning về việc chặn lưu lượng DNS được mã hóa, nhưng các yêu cầu DNS upstream được mã hóa tới Cloudflare
- Cần tắt NAT reflection để Internet bên ngoài không thể truy cập máy chủ DNS
- Tác giả tạo firewall alias
Non_WANđể chuyển hướng các truy vấn DNS cục bộ trên cổng 53 từ các interface không phải WAN về localhost - Vì YouTube phân phối quảng cáo và video chính từ cùng domain, rất khó chỉ lọc quảng cáo bằng trình chặn theo tên miền như pfBlockerNG hay Pi-hole
Thử nghiệm né bằng VPN và các điểm thất bại
- Thay vì chặn quảng cáo, tác giả cũng thử đánh lừa thuật toán quảng cáo của YouTube để trông giống một người dùng kém hấp dẫn hơn với nhà quảng cáo
- Tác giả cố định tuyến lưu lượng theo dõi vị trí của YouTube qua VPN tới khu vực có ít người xem bằng router pfSense
- Mục tiêu là để tài khoản YouTube được nhận diện là “nam 70 tuổi, sống tại Italy”
- Trên pfSense, tác giả dùng WireGuard thay vì OpenVPN để thực hiện thử nghiệm cơ sở: đưa toàn bộ lưu lượng Apple TV qua VPN
- Cài gói WireGuard cho FreeBSD rồi thêm và kích hoạt tunnel
- Để cấu hình NordLynx, tác giả kiểm tra private key bằng
sudo wg showconf nordlynxtrên một VM Linux rồi chuyển sang pfSense
- Kết quả thử nghiệm cho thấy Google trên laptop hiển thị bằng tiếng Italy, và YouTube trên Apple TV cũng chuyển sang tiếng Italy
- Quảng cáo vẫn xuất hiện một phần, nhưng được cho là ít hơn trước
- Netflix và Amazon Prime gặp vấn đề; có vẻ các file CSS hoặc font bị chặn, hoặc thumbnail không tải được
- Tác giả cảnh báo không nên đưa toàn bộ lưu lượng Apple TV qua VPN, và cho rằng Netflix và Prime phát hiện tốt VPN provider và geofencing
- Sau đó, để chỉ đưa lưu lượng YouTube của Apple TV qua VPN, tác giả cấu hình firewall policy rule nhắm tới
www.youtube.com,youtube.com,googlevideo.com,accounts.google.com,googleapis.com,gstatic.com, v.v.- Kết quả là YouTube thấy người dùng ở Milan, còn Netflix và Prime Video thấy người dùng ở Canada
- Quảng cáo giảm xuống mức “thưa thớt lắm mới có”
- Một ngày sau, DNS race condition xuất hiện
- Hostname alias của pfSense mặc định được resolve mỗi 300 giây
- DNS TTL của YouTube có thể là 1.440 giây, tức 24 phút
- Nếu IP mà Alias Daemon resolve được khác với IP mà client thực sự nhận, policy có thể không tunnel lưu lượng YouTube
- Một số video YouTube không phát được do
403 Forbidden- YouTube được cho là nhúng IP của người dùng vào từng yêu cầu
googlevideo.com - Nếu một domain biến thể như
r5---sn-hpa7kn76.googlevideo.comkhông được tunnel, yêu cầu sẽ đi ra từ IP sai và gây lỗi - Thứ cần có là tunnel wildcard
*.googlevideo.com, nhưng NAT và firewall rule hoạt động theo IP chứ không theo wildcard hostname
- YouTube được cho là nhúng IP của người dùng vào từng yêu cầu
PoC theo dõi IP dựa trên truy vấn DNS
- Đã nghĩ ra phương thức chiếm quyền truy vấn DNS của Google Video để định tuyến
*.googlevideo.comqua VPN- Cách làm là theo dõi định kỳ log truy vấn DNS và thêm các truy vấn
*.googlevideo.comvào danh sách alias - Nếu mỗi video dùng một domain riêng và đã được biến đổi, thì cách này được cho là sẽ không hoạt động trừ khi làm mới cho từng video
- Cách làm là theo dõi định kỳ log truy vấn DNS và thêm các truy vấn
- Mục tiêu mới là dùng Python 3 và pfSense REST API để giám sát truy vấn DNS, bắt IP, tạm giữ phản hồi, sau đó thêm IP vào quy tắc VPN tunneling rồi release DNS reply
- Đã cài pfSense REST API và gửi yêu cầu GET tới
https://pfsense/api/v1/firewall/aliasđể truy vấn aliasVPN_domains - Đã tìm hiểu module Python của Unbound DNS Resolver và ghi log được DNS-query message
- Phiên bản Python hiện tại là 3.8
- Ví dụ của Unbound Python module dựa trên Python 2.4, nên cho rằng có thể cần
2to3hoặc định dạng lại
- Script PoC trích xuất IP trong A/AAAA record từ DNS response và thêm vào alias của pfSense
- Bản ghi A được xử lý bằng
ipaddress.IPv4Address(d.rr_data[j][2:]).exploded - Bản ghi AAAA được xử lý bằng
ipaddress.IPv6Address(d.rr_data[j][2:]).exploded - TTL của alias được đặt là 1 giờ, capacity là 500
- Bản ghi A được xử lý bằng
- Ngày hôm sau, Unbound DNS Resolver bị segfault, và vì mỗi lần thêm IP đều phải reload rule của pfSense nên pfSense trở nên rất chậm
Chuyển từ Squid sang mitmproxy
- Mục tiêu mới chuyển sang hướng khảo sát và cài đặt proxy họ Squid, tạo chứng chỉ CA giả được tin cậy rồi giải mã TLS traffic
- Trong thử nghiệm Squid, đã kiểm tra liệu proxy
squid3được cung cấp dưới dạng pfSense package có đáp ứng yêu cầu hay không- Tạo thư mục riêng
/squid_cachevà đặt kích thước cache là 8GiB - Kỳ vọng có hỗ trợ Transparent HTTPS
- Tạo thư mục riêng
- Sau một ngày cấu hình Squid và SquidGuard thì đã bỏ cuộc
- Tốc độ rất chậm
- Cấu hình ACL rườm rà
- Có issue liên quan đến
https://http/* - Việc update danh sách filter URL của SquidGuard mất rất nhiều thời gian
- UI của Squid còn thiếu
- Sau đó quyết định dùng mitmproxy được viết bằng Python
- Chọn mitmproxy thay vì
SSLSplitvì khả năng mở rộng bằng Python hook và UI - Phiên bản FreeBSD của pfSense là
12.2-Stable, bản build 64-bit
- Chọn mitmproxy thay vì
- Trong môi trường mặc định của pfSense, jail bị disabled nên đã cài thủ công
ezjailvà tạo jail chomitmproxy- Tạo jail bằng
ezjail-admin create mitmproxy 'lo0|127.0.1.1' - Đặt
allow.raw_sockets=1cho transparent proxy mode - Nếu raw socket bị chặn thì có thể xuất hiện lỗi như
Transparent mode failurehoặcCannot open connection, no hostname given.
- Tạo jail bằng
- Việc chạy Linux tarball binary trên FreeBSD thất bại
- Xuất hiện lỗi
ELF interpreter /lib64/ld-linux-x86-64.so.2 not found - Cũng không tìm thấy
libdl.so.2,libz.so.1,libpthread.so.0,libc.so.6
- Xuất hiện lỗi
- Trong jail, đã chạy
pkg install mitmproxy; quá trình cài đặt yêu cầu 50 package, thêm 206MiB dung lượng và tải xuống 33MiB - Để có thể truy cập MITMProxy từ LAN, đã gắn virtual IP
127.0.1.1vào localhost và tạm thời forward[Private IPs]:8080tới127.0.1.1:8080bằng NAT rule - File CA PEM do MITMProxy tự động tạo là
~/.mitmproxy/mitmproxy-ca-cert.pem, và đã cài CA cert này vào Trusted Root Store của thiết bị thử nghiệm mitmproxydùng nhiều CPU ngay cả khi idle, và cho rằng việc tạo TLS certificate theo thời gian thực cho từng request cùng lượng logging quá mức đã làm tốc độ chậm đi đáng kểmitmdumpđược cho là giảm tải CPU hơn vì bỏ qua UI và logging quá mức
Loại bỏ quảng cáo JSON trên web YouTube
- Certificate Pinning là kỹ thuật trong đó server hoặc client biết trước fingerprint của certificate dự kiến, khiến việc giả mạo certificate của MITMProxy không có tác dụng
- Có thể cho host có vấn đề đi vòng qua proxy bằng tùy chọn
--ignore-hosts- Ví dụ đã ignore
apple.com:443,icloud.com:443
- Ví dụ đã ignore
- Khi truy cập YouTube, page ads xuất hiện trong MITMProxy cùng các header không được mã hóa, và đã xem xét khả năng chặn bằng regex đơn giản
- Để áp dụng script chặn quảng cáo YouTube, đã thêm
--scripts "youtube.py"vàomitmdump - Smoke-test filter chặn request quảng cáo dựa trên substring trong URL
youtube.com:/pagead/,/log_event?,/stats/ads,/stats/qoe?,/ptracking?,/generate_204,el=adunit,adformat=,/activeview?google.com,google.ca:/pagead/ggpht.com:.
- Các request định chặn trông như đã thực sự bị chặn trong MITMProxy và panel Network của DevTools, nhưng ads vẫn xuất hiện, đôi khi ads tự skip hoặc phát thất bại
- Sau đó phát hiện khá nhiều URL liên quan đến quảng cáo bên trong JSON payload
- Bao gồm các phần
playerAdsvàplaybackTracking youtubeRemarketingUrlchứahttps://www.youtube.com/pagead/viewthroughconversion/...googleRemarketingUrlchứahttps://www.google.com/pagead/1p-user-list/...
- Bao gồm các phần
- Sau khi phân tích UI YouTube và HTTP workflow đến cả cookies và service workers, họ nói rằng đã có thể loại bỏ toàn bộ quảng cáo pre-roll, post-roll và mid-video
- Ở giai đoạn này, router đã có thể loại bỏ ads khỏi JSON payload của YouTube web ads
YouTube iOS và vấn đề Protobuf
- Ứng dụng YouTube iOS hiển thị dữ liệu rất giống với phiên bản web trong phiên bản Protobuf của cùng các lệnh gọi API
- Trong Protobuf, key là số và có thể thay đổi, nên không thể dùng cách tìm phần quảng cáo bằng JSONPath
- YouTube gửi trong payload một danh sách lớn các quảng cáo sẽ xem sắp tới, và khi dùng hết danh sách đó thì một danh sách lớn khác sẽ sớm được gửi đến
- Trong payload Protobuf có thể thấy các chuỗi như “Telus,” “Samsung TV,” “Boxing Week,” “Buy now”
- Giao thức YouTube trên iOS khác với traffic web
- Ở phiên bản web, có thể phần nào phân biệt video quảng cáo và video muốn xem bằng cách nhìn vào URL và tham số truy vấn
range - Giao thức iOS không dùng tham số truy vấn
rangecũng như headerRange, mà dùng các bộ đếm như&nr=2,&nr=3trong chunk video - Để chặn quảng cáo trên iOS, cần reverse-engineer response Protobuf
- Ở phiên bản web, có thể phần nào phân biệt video quảng cáo và video muốn xem bằng cách nhìn vào URL và tham số truy vấn
- Trong message Protobuf đã decode, tác giả phát hiện các mục
has_unlimited_entitlement: False,has_premium_lite_entitlement: False, nhưng thay vì toggle chúng thì quay lại dùng heuristics - Decode khoảng 500KiB Protobuf thô bằng pure implementation Python rất chậm
- Trên desktop i7-6700, kết quả Python khoảng 2,06~2,11 giây
- Trên router pfSense, kết quả Python khoảng 22,8~24,2 giây
- C++
protoc --decode_rawtrên desktop khoảng 0,017~0,022 giây, và trên router pfSense khoảng 0,12~0,14 giây
Decode Protobuf và thử trích xuất schema
- Vì Python không hỗ trợ decode Protobuf thô, thay vì dùng trực tiếp C++
libprotobuf.so, tác giả chọn cách giao tiếp với binary C++protocbằngsubprocess.Popen - Khi fuzzing response video quảng cáo, tác giả thử response
200rỗng,404,503, body response bị cắt ngắn, xử lý null một phần video quảng cáo, v.v., nhưng ứng dụng iOS sau khi chậm đi thì crash hoặc kẹt ở màn hình quảng cáo - Chặn URL kích hoạt hành vi phản ứng của ứng dụng, và chunk response video cũng chứa session metadata
- blackboxprotobuf cho Burp Suite cho phép decode raw Protobuf wire message, chèn nội dung rồi encode lại để kiểm tra hành vi của endpoint Protobuf
- Nên dùng bản Burp Suite gốc, không phải fork trên PyPI
- Một số fork gặp vấn đề stack overflow hoặc infinite recursion do đệ quy sâu
- Nếu dùng C++ bindings, có thể transcode khoảng 500KiB Protobuf thô chỉ trong vài giây
- Schema được tạo ra không hoàn hảo, lớn và lồng nhau sâu, việc pretty-print chậm, nhưng đủ để tìm thông tin chi tiết về quảng cáo
- Tác giả thử PBTK, Apktool, dex2jar, Java Decompiler để trích xuất file
.protohoặc schema thực tế từ APK YouTube Android- Thứ PBTK trích xuất được chỉ là một file proto 59 byte
- Trong Java có các class Protobuf và getter/setter, nhưng không lấy được true schema files nên dừng lại
Bước ngoặt cuối cùng: thay đổi 1 byte field tag của Protobuf
- Từ traffic mạng đã giải mã và kết quả fuzzing Protobuf, quảng cáo được quan sát là có cấu trúc đăng ký vào các slot của một video cụ thể
- Các loại slot gồm pre-roll, mid-roll, end-roll, full-page, ad pods
- Nếu chặn URL quảng cáo, lỗi kiểu “một quảng cáo không tồn tại đã giữ chỗ slot” sẽ xảy ra và UI panic
- Nếu decode, chỉnh sửa rồi encode lại khi không có schema gốc, encoding sau chỉnh sửa sẽ khác; vì không biết có dùng ZigZag hay không, cũng như không biết các kiểu số như
int32,int64,sint32/64,varint, và thứ tự field của object thường cũng nondeterministic, nên tác giả xem đây là vấn đề - Tác giả tìm thấy khả năng bypass trong backward compatibility của Protobuf và hành vi UnknownFieldSet
- Khi phần mềm cũ đọc message có field mới được thêm vào, unknown field có thể xuất hiện
- Nếu đổi một field key cụ thể sang giá trị khác, toàn bộ sub-structure chứa thông tin quảng cáo và tracking có thể trở thành trạng thái unavailable
- Ví dụ, tác giả đề xuất ý tưởng đổi field key
49399797thành49399796để biến sub-structure quảng cáo/tracking đó thành như một unknown field - Không thể tìm field key
49399797chỉ bằng tìm kiếm hex đơn giản, mà phải xét varint/tag encoding- Wire type là
2, nghĩa là nested string/message dạng length-delimited - Chuỗi byte tag của target field key
49399797trở thànhAA FF B8 BC 01 - Dịch phải
395198378 >> 3để loại bỏ 3 bit wire type sẽ thu được field key gốc49399797
- Wire type là
- Trong bytes Protobuf, tác giả tìm signature URL quảng cáo cổ điển như
/pagead/để khoanh vùng tìm field, rồi từ vị trí đó lùi lại để tìm field tag và field key cần thay đổi - Trong log intercept ví dụ, ở response
application/x-protobuf1,87MiB của yêu cầu POSTyoutubei.googleapis.com:443/youtubei/v1/browse?key=..., key49399797được tìm thấy tại vị trí4465, key50195462tại vị trí4477 - Trong O(n) smoke test, tác giả scan dữ liệu Protobuf 1,8MiB một lần mà không dùng thêm memory
- Target được tìm thấy ở byte thứ 30.593 trong 1,8MiB
- Dùng backtracking khoảng 600 byte để tìm field key cần denature
- Khi phương pháp này hoạt động, không còn cần chặn các URL chứa
*.googleadservices.comhoặc/pagead/nữa, và những request đó ngay từ đầu đã không còn phát sinh
Cấu trúc script add-on MITMProxy
- Script add-on MITMProxy được cung cấp như một proof of concept để chặn quảng cáo YouTube trên Apple device nối mạng
- Tên file là
youtube.py - Ví dụ chạy:
mitmdump --listen-port 8080 --listen-host 127.0.0.1 -s "youtube.py" - FreeBSD prerequisite là
pkg install protobuf,pkg install py38-pip,pip install jsonpath-ng
- Tên file là
- Script có bao gồm fairness function cho phép 5% quảng cáo nhằm hỗ trợ nhà sáng tạo nội dung
in_allowed_ads_window()bỏ qua việc chặn quảng cáo nếu thời gian hiện tại nằm trong khoảng từ phút 0 đến phút 2 của mỗi giờ
YouTubeAdBlockerintercept các domain liên quan đến YouTube và chỉnh sửa JSON hoặc Protobuf response để loại bỏ thông tin quảng cáo- Regex host mục tiêu intercept là
\.youtube\.com|google\.(com|ca)|googleapis\.com|googleadservices\.com|googlevideo\.com - Chuỗi dùng để phát hiện quảng cáo Protobuf là
b"/pagead/" - Giới hạn tìm kiếm là
80_000byte - Target field tag là
50195462
- Regex host mục tiêu intercept là
- Danh sách chặn ở giai đoạn request bao gồm
pagead/,log_event?,stats/ads,stats/qoe?,ptracking?,generate_204,error_204,adformat=,activeview?,_ad_,ai?,sw.jsv.v. trên host YouTube - JSON replacement cho YouTube web loại bỏ hoặc vô hiệu hóa các field liên quan đến quảng cáo
yt_adđược đổi thành"0"adPlacementsđược đổi thành[]adPlacementRenderer,adPlacementConfig,playerAdParams,gutParamsđược đổi thành{}adVideoIdđược đổi thành""showCompanion,showInstream,useGutđược đổi thànhFalse
- Hook
load()vô hiệu hóa HTTP/2 và đặtanticomp=True,mode="transparent" - Hook
running()cập nhậtallow_hostsđể việc intercept chỉ áp dụng cho các domain liên quan đến YouTube - Hook
response()nếucontent-typecóprotobufthì tìm/pagead/trong 80.000 byte đầu của body response- Nếu tìm thấy, tạo target tag bytes bằng
TagBytes(self.target_field_tag, WIRETYPE_LENGTH_DELIMITED) - Tạo tag bytes của
target_field_tag - 1thành bytes mới - Reverse search phía trước vị trí
/pagead/để tìm target tag - Thay thế bytes tại vị trí đó bằng bytes tương ứng với
target_field_tag - 1 - Đưa nội dung Protobuf đã sửa trở lại bằng
flow.response.set_content(bytes(body))
- Nếu tìm thấy, tạo target tag bytes bằng
- Chú thích trong code cho biết PoC này đã chặn được 90% quảng cáo, đồng thời nói thêm rằng trong các section khác cũng có các field key khác và có thể có nhiều section quảng cáo cần vô hiệu hóa
Hiệu năng, giới hạn và người dùng mục tiêu
- Kỹ thuật cuối cùng tận dụng việc Protobuf cho phép unknown field để backward-compatible với schema change, cùng độ nhạy với chỉnh sửa một byte của compact format
- Nếu đổi 1 byte tại critical spot để khiến một section lồng sâu trông như thuộc về future schema version, Protobuf có thể ignore nó và loại bỏ thông tin quảng cáo
- Google trả về một Protobuf response lớn, bao gồm cả layout app iOS; payload ví dụ là 1,8 MiB
- Để parse toàn bộ payload cần native code như C++/Swift, còn Python decoding được cho là chậm hơn nhiều bậc và gây connection timeout
- JSON nền web phải parse, edit rồi re-serialize toàn bộ payload, nhưng kỹ thuật Protobuf chỉ cần linear scan và backtrack nhanh nên xử lý ở mức microsecond, phù hợp với real-time adblocking và không cần blocklist
- Tất cả URL
*.googleadservices.comvà/pagead/*trên Apple device đều đến từ Protobuf payload; khi ad data biến mất khỏi payload, các request đó cũng tự động biến mất - YouTube app không cố fetch URL quảng cáo nên cảm giác nhanh hơn, và vì quảng cáo không được đăng ký vào video slot nên content phát ngay lập tức
- Cách này được giới thiệu như một highly specialized technique để chặn Apple-device YouTube ads hoặc tracker traffic của Instagram, WhatsApp, Facebook
- Nhu cầu CPU để decrypt/re-encrypt HTTPS traffic được cho là vượt xa đáng kể hiệu năng của Raspberry Pi
- Vì nhắm đến Apple-device owner không muốn compromise OS, nhóm người dùng được xem là hẹp hơn
YouTube Premium và thử nghiệm chi phí quảng cáo
- Tác giả cho rằng chưa chắc YouTube Premium có hợp lý hay không khi giá là CAD $9.99/mo hoặc CAD $11.99/mo, tính thuế khoảng CAD $13.43/mo
- Tác giả thực hiện thử nghiệm mức độ hiển thị quảng cáo bằng một laptop sạch và private browsing, xem YouTube không liên tục trong một ngày
- Theo lịch sử xem, số video đã “xem” chỉ là 10
- Trong lúc xem một phần của 10 video, tác giả thấy 8 quảng cáo
- Chỉ có 2 quảng cáo có thể bỏ qua và cả hai đều được bỏ qua
- Nếu giả định CPV xấp xỉ USD $0.15, 8 quảng cáo mỗi ngày tương đương chi phí nhà quảng cáo
8 x $0.15 = $1.20, ngoại suy theo tháng là khoảng USD $36/mo - Tác giả cũng đưa ra phép tính dựa trên dữ liệu Statista, lấy chi tiêu quảng cáo tại Mỹ chia cho tổng lượt xem
- Năm 2019, nhà quảng cáo Mỹ đã chi $15.1 billion trên YouTube
- Người dân Mỹ được cho là đã xem 916 billion video
- Trung bình là
$15.1B / 916B = USD $0.0165 per view - Với trường hợp của tác giả, con số này tương ứng chi phí nhà quảng cáo khoảng USD $0.13 mỗi ngày, khoảng USD $3.96 mỗi tháng
- Vì trong lúc thử nghiệm quảng cáo tác giả bật tắt tiếng bằng phần cứng và thường xuyên nhìn sang chỗ khác, tác giả cho rằng tiền quảng cáo nhắm vào mình đã bị lãng phí
- Dù vậy, tác giả vẫn muốn hỗ trợ nhà sáng tạo và cho biết sẽ dùng thử 3 tháng Premium trial, đồng thời tiếp tục theo dõi Google đang tracking gì về mình
- Tác giả lo ngại rằng từ thời điểm DMCA claim được tiếp nhận, toàn bộ doanh thu quảng cáo có thể chuyển tới claimant thay vì nhà sáng tạo, và nói thêm rằng việc nhiều nhà sáng tạo chuyển sang Patreon không có gì đáng ngạc nhiên
Tổng kết cuối cùng
- Thiết lập hardware router từ đầu và tách LAN thành trusted/untrusted zone
- Thiết lập chặn quảng cáo DNS truyền thống
- Thêm transparent MITM proxy
- Cuối cùng, tác giả cho biết đã có thể chặn quảng cáo YouTube với hiệu năng tốt trên các thiết bị Apple nối mạng
- Tác giả viết rằng vì phần khó đã xong nên sẽ cân nhắc trả tiền YouTube Premium, nhưng nói thêm rằng tracker vẫn sẽ bị chặn mạnh tay
1 bình luận
Ý kiến trên Hacker News
Có vẻ không hẳn là khiếm khuyết của định dạng Protobuf, mà là tác giả đã đổi số field sang một số lớn chưa dùng
Cách làm là tìm chữ ký URL quảng cáo như
/pagead/trong các byte Protobuf để xác định phạm vi field, rồi đi lùi lại từ đó để tìm tag field mục tiêu và key field nhằm vô hiệu hóa nó; việc này gần với hành vi có chủ đích hơn là một lỗ hổngNếu đã bỏ công đến mức tìm tag, thì việc đọc độ dài varint ngay bên cạnh và bỏ qua các byte tương ứng cũng không phải là thêm nhiều việc. Có thể sẽ phải sao chép buffer hoặc dịch chuyển byte, nhưng script PoC cũng đã phải sao chép rồi vì
bytesmà API mitmproxy trả về là bất biếnGoogle hẳn sẽ phát hành ứng dụng mới trước khi thay đổi giao thức đến mức làm toàn bộ quảng cáo không hiển thị trên các phiên bản ứng dụng cũ, nên chỉ cần pin chứng chỉ cơ bản hoặc giải mã ít khoan dung hơn khi không trích xuất được thông tin quảng cáo là có thể chặn ngay cách này. Nếu là đội YouTube, tôi nghĩ họ sẽ xem phần này là lỗi
byteslà bất biến, nhưng đối tượngbytearraythì khôngMột proxy C++/Go nhỏ cũng có thể làm cùng việc với overhead thấp hơn nhiều. Những tác vụ được định nghĩa rõ như thế này sẽ ổn định hơn và đỡ mất công hơn so với vật lộn với mitmproxy
Nếu đưa toàn bộ lưu lượng qua proxy thì hiệu năng sẽ giảm, ngay cả khi dùng chặn bắt SNI. pfSense cũng tương tự; một máy chủ Linux đơn giản cùng vài quy tắc iptables đơn giản là có thể xử lý mà không phải đánh vật với các lớp trừu tượng của pfSense
Chỉ cần viết vào file
.protođúng phần cần thiết trong các proto field đã reverse-engineer, tự động sinh code rồi đổi flag là được. Cách này rẻ hơn bản triển khai Python và cũng dễ cập nhật hơn khi proto thay đổi. Bỏ qua các tag field không xác định là một tính năng quan trọng của Protobuf, cho phép thay đổi schema tương thích mà không phá vỡ các bản đã triển khaiCó vẻ tác giả đã nhận thức được phần lớn những điểm trong bình luận, và bài viết cũng khá kỹ lưỡng. Họ đã benchmark bằng Python và C++, còn bản triển khai cuối thậm chí không giải mã Protobuf. Họ cũng đã thử nhiều giải pháp mitm, và dùng pfSense không phải như một router bảo mật đơn giản mà để nhắm riêng lưu lượng Apple TV bằng VLAN và VPN
Bình luận này nghe quá rẻ tiền và hạ thấp người khác. Bài gốc thì không như vậy, nên nếu muốn nói thế, bạn nên tự chứng minh cho cộng đồng thấy
Nếu trả tiền YouTube Premium thì có hỗ trợ creator không? Nếu có thì tôi tò mò mức độ ra sao so với tài trợ trực tiếp kiểu Patreon
Khoản doanh thu mà một gói YouTube Premium đem lại cho từng creator có thể rất nhỏ, nhưng vẫn tốt hơn việc xem video trong khi chặn quảng cáo
Vì tính theo thời lượng xem chứ không phải lượt hiển thị quảng cáo, các creator làm nội dung dài sẽ có lợi hơn
Tài khoản YouTube của bạn gái tôi kỳ lạ là đăng nhập trên thiết bị nào cũng không có quảng cáo. Kể cả Apple TV, không phải Premium và cũng chưa từng là Premium
Tôi tò mò không biết nội bộ có flag nào được đặt khiến quảng cáo bị tắt không
Đến lúc đó tôi mới có khoảnh khắc hiểu ra vì sao mọi người phàn nàn
Dù không dùng trình chặn quảng cáo, chỉ cần đăng nhập là tôi không thấy quảng cáo ở cả website lẫn ứng dụng di động. Tôi không có Twitch Turbo và cũng không còn Amazon Prime. Tôi cũng không có các quyền lợi Turbo khác, nên không phải tài khoản bị gắn hoàn toàn là Turbo
Không rõ có phải do hồi trước làm bug bounty, tôi nghịch đủ thứ rồi vô tình làm hỏng hồ sơ tài khoản hay không, nhưng nếu họ để tôi giữ quyền lợi này thì tôi cũng có thể cung cấp thêm thông tin chi tiết
Điều lạ là tôi nhớ hồi trước ở bệnh viện, đang phê thuốc và đau đớn chỉ muốn xem TV, nhưng quảng cáo Twitch quá kinh khủng khiến tôi gần như suy sụp. Rồi 1–2 năm sau, chợt nhận ra mình đã không thấy quảng cáo suốt nhiều năm
Có lẽ đang tồn tại một A/B test không quảng cáo đã bị lãng quên từ lâu, và không đáng công dọn dẹp nên vẫn còn. Nhờ vậy tôi đã hưởng lợi nhiều năm và xem Twitch nhiều hơn bất kỳ nền tảng nào khác. Twitch Turbo ở Anh là £12/tháng, khoảng $15,50, thuộc loại đắt trên toàn cầu, và so với mức $12/€12 ở Mỹ và châu Âu thì là một mức giá khá thiệt
Việc có thể giải mã lưu lượng HTTPS bằng cách đặt một proxy trung gian giữa Apple TV và Internet bên ngoài khá đáng ngạc nhiên
Tôi cứ nghĩ bình thường nó không nên hoạt động, rồi sau đó lại ngạc nhiên theo một cách khác khi biết có thể thêm CA vào kho chứng chỉ của Apple TV. Đây là một bài viết rất chặt chẽ, lướt qua toàn bộ stack
Ví dụ ở trường đại học, để kết nối thiết bị vào Wi-Fi thì phải đưa địa chỉ MAC vào danh sách cho phép hoặc cài chứng chỉ
Tuy nhiên nếu làm vậy, YouTube có thể bị hỏng trong nhiều môi trường doanh nghiệp nên không rõ họ có thực sự làm không. Dù vậy, đáng tiếc là việc chặn rất dễ
Tôi đã thử triển khai vài lần trên Apple TV nhưng hoàn toàn không thành công. Có vẻ YouTube giờ đã đưa certificate pinning vào ứng dụng hoặc gì đó tương tự. Tôi tò mò không biết gần đây có ai làm cho cách này chạy được không
[0] https://frida.re/docs/home/
Tôi thích mọi nỗ lực chặn trên toàn mạng các dịch vụ online tệ hại mà ta bị ép phải dùng
Chặn quảng cáo cũng tốt, nhưng tôi ước có cách dễ hơn và nhiều hơn để chặn trên toàn mạng các dạng cuộn vô hạn hung hãn như YouTube Shorts hay Instagram Reels
Trên Instagram, tôi chỉ muốn xem bài đăng và story của những người mình theo dõi, chứ không muốn bị gợi ý mấy video ngớ ngẩn được thiết kế để cướp sự chú ý. Có thể điều này cho thấy tôi thiếu ý chí, nhưng tôi thường xuyên xem vài cái rồi mất 15 phút cuộc đời
Người dùng Internet nhìn chung đã chọn hướng không muốn trả tiền, nên sẽ có ai đó phải gánh chi phí. Nhìn tổng thể, người dùng Internet không thưởng cho phía không hiển thị quảng cáo. Họ muốn nội dung, nhưng đa phần muốn miễn phí
Tôi tìm thấy một script biến trang Instagram gần như thành các thẻ ảnh, để chỉ xem ảnh: https://greasyfork.org/en/scripts/5014-un-instagram
Vì vậy có vẻ không hẳn là thiếu ý chí, mà giống sự chai lì mà chúng ta đã tích lũy hơn, và điều đó khá tệ. Nỗ lực và sự sáng tạo nhằm đưa mọi thứ trở lại trạng thái chúng ta dùng nền tảng, thay vì nền tảng bắt chúng ta dùng nó, là đáng tôn trọng
Tôi thường xuyên nói chuyện với bọn trẻ, chúng cũng đồng ý rằng điều đó có hại nhưng lại quá khó để chống lại. Ngay cả tôi đôi khi cũng bị kéo vào doomscrolling
Ở những nơi có thể, tôi đã thiết lập lọc quảng cáo bằng Pi-hole, nhưng không muốn chặn toàn bộ YouTube. Dù vậy, để bảo vệ gia đình, có lẽ về sau tôi sẽ phải nghiêm túc cân nhắc
Phần kỹ thuật thì hay, nhưng hơi buồn khi phải đi xa đến mức này chỉ để có cảm giác mình sở hữu phần nào phần cứng hay phần mềm của chính mình
YouTube có quảng cáo à? Trình duyệt chặn tốt quá nên tôi không biết
Vấn đề thật sự là trải nghiệm Apple TV tệ hơn nhiều so với trải nghiệm trình duyệt web thông thường. Apple khóa phần cứng quá chặt, khiến cấu trúc này có lợi cho doanh thu quảng cáo của YouTube hơn là cho người tiêu dùng cuối đã bỏ tiền mua thiết bị
Khi dùng iPad lướt web bên ngoài mạng Pi-hole ở nhà cũng vậy. Tôi không hiểu mọi người chịu đựng chuyện này hằng ngày như thế nào
iPad là thiết bị công ty cấp nên tôi không dùng cho mục đích cá nhân thường xuyên, nhưng mỗi lần dùng lại được nhắc nhớ nó khó chịu đến mức nào
Kỳ lạ là trước khi nhận iPad, tôi cứ nghĩ nó chỉ hữu ích để tiêu thụ nội dung, nhưng thực tế nó rất tiện để truy cập nhanh từ xa vào tài nguyên công việc, còn với duyệt web thông thường và streaming media thì nó lại là một thiết bị bị kẹt trong vùng đất hoang phủ đầy quảng cáo
Nếu cần YouTube không quảng cáo, có thể dùng https://yewtu.be hoặc một instance Invidious khác https://docs.invidious.io/instances/
Giữa YouTube và Invidious có một cuộc chạy đua vũ trang, và đôi khi Invidious không hoạt động, nhưng đội ngũ luôn tìm được cách mới để vượt qua YouTube và truyền video không quảng cáo