- Es una PoC que coloca un proxy MITM basado en pfSense entre el Apple TV e internet, descifra HTTPS y luego modifica las respuestas Protobuf que entrega YouTube para evitar que se registren espacios publicitarios en dispositivos Apple
- Los bloqueadores DNS tradicionales y el enrutamiento por VPN chocaban con límites como TTL de DNS, discrepancias de IP, errores 403 y fugas de ASN, porque los anuncios de YouTube y el video principal usan el mismo dominio e infraestructura
- El experimento con Squid se abandonó por problemas de rendimiento y configuración, y luego se cambió a un enfoque con mitmproxy/mitmdump en un jail de FreeBSD para descifrar tráfico TLS y modificar directamente respuestas JSON y Protobuf
- En YouTube web se podían eliminar
adPlacements,playerAdParamsy URLs depageaddel JSON, pero la app de YouTube en iOS guardaba espacios publicitarios e información de rastreo en respuestasapplication/x-protobuf, así que hubo que trabajar con la estructura Protobuf - El método final consiste en una exploración lineal y una modificación de 1 byte: buscar hacia atrás el field tag cerca de la cadena
/pagead/y cambiar etiquetas como50195462atarget_field_tag - 1, logrando rendimiento apto para procesamiento en tiempo real sin decodificar todo
Objetivo y diseño inicial de red
- El objetivo era construir un router basado en FreeBSD y pfSense para bloquear a nivel de toda la red los anuncios pre-roll, mid-roll y end-roll de YouTube en Apple TV y iPhone
- Si se colocaba un proxy man-in-the-middle entre el Apple TV y el internet externo, era posible descifrar el tráfico HTTPS y leer los datos de Protocol Buffers que Google usa para llenar anuncios en YouTube
- Tras varios meses implementando el bloqueo de anuncios en YouTube, comenzó a pagar YouTube Premium, y aclara que “poder hacerlo” y “deber hacerlo” son cosas distintas
- Menciona como razones para bloquear anuncios y rastreo la vigilancia de datos personales, el desperdicio de ancho de banda, el clickbait y el cryptojacking
- Considera que entre el 25% y el 40% del tráfico de red puede ser anuncios, scripts de rastreo,
fingerprint.js,googletagmanager.jsy cargadores de analítica en tiempo real como Hotjar - Explica que JavaScript de cryptominería como CoinHive.js puede sobrecalentar la computadora o explotarla para ganar pequeñas cantidades de dinero
- Considera que entre el 25% y el 40% del tráfico de red puede ser anuncios, scripts de rastreo,
Hardware de pfSense y configuración básica
- Para proteger toda una red SMB, considera que VM, imágenes de Docker y Raspberry Pi no dan el rendimiento suficiente, por lo que se necesita hardware dedicado encargado solo de enrutamiento, descifrado y monitoreo de paquetes
- El hardware de router usado fue una mini PC con conjunto de instrucciones AES-NI, RAM DDR4, SSD mSATA y una memoria USB para flashear pfSense
- Un ejemplo de configuración es una mini PC J4125, 32 GiB de RAM DDR4 y SSD mSATA de 128 GiB
- Considera que 128 GB de almacenamiento bastan para logs, reducir desgaste del SSD, captura de paquetes y edge cache de NPM y Docker
- La imagen de instalación de pfSense pesa unos 360 MB y puede grabarse en una memoria USB con Etcher AppImage
- Después de la configuración inicial, AES-NI aparecía como “Yes (inactive)”, así que se activó manualmente en
System › Advanced › Miscellaneous - Para aprovechar los 32 GiB de RAM, asignó bastante RAM disk a
/vary/tmp, y configuró el SSD de 128 GiB esperando wear-leveling y respaldos horarios del RAM disk - En el Dashboard agregó el widget S.M.A.R.T. para poder detectar fallas del SSD
Bloqueo DNS, segmentación de red y pfBlockerNG
- Antes usaba Pi-hole en una Raspberry Pi como bloqueador de anuncios a nivel DNS, y en pfSense instaló pfBlockerNG-devel para probar bloqueo de anuncios, contenido malicioso y geo-blocking
- Si el servicio pfb_dnsbl no inicia o la pestaña de estado muestra
[ Missing CRON task ], recomienda intentar borrar el archivo vacío/var/run/booting - Aprovechó los 3 puertos Gigabit de la mini PC para crear redes físicas en vez de VLAN y aislar del network principal dispositivos que “llaman a casa”, como Alexa y Apple TV
- Los dispositivos no confiables se colocan en la red privada
172.31.1.0/24 - La LAN confiable se mantiene en
192.168/16 - La LAN física para IoT pasa por el adblocker y busca interceptar consultas DNS hard-coded a
1.1.1.1y9.9.9.9para que YouTube no pueda saltarse el bloqueador DNS
- Los dispositivos no confiables se colocan en la red privada
- Configuró reglas NAT para que todos los clientes detrás de pfSense usen el servidor local de Unbound DNS
- Considera que primero hay que bloquear DNS over TLS para poder interceptar consultas DNS
- Dice que el iPhone puede mostrar una Privacy Warning por bloquear tráfico DNS cifrado, pero que las consultas DNS upstream sí van cifradas hacia Cloudflare
- Recomienda desactivar NAT reflection para que internet externo no pueda acceder al servidor DNS
- Creó un alias de firewall
Non_WANpara redirigir al localhost el puerto 53 de consultas DNS locales en interfaces distintas de WAN - Como YouTube entrega los anuncios y el video principal desde el mismo dominio, era difícil filtrar solo los anuncios con bloqueadores por nombre de dominio como pfBlockerNG o Pi-hole
Experimentos de desvío por VPN y puntos de falla
- También hizo pruebas para engañar al algoritmo publicitario de YouTube y parecer un usuario menos atractivo para anunciantes, en vez de bloquear anuncios directamente
- Quería enrutar por VPN el tráfico de geolocalización de YouTube desde el router pfSense hacia una región con menos audiencia
- Se fijó la meta de que YouTube identificara la cuenta como “hombre de 70 años, residente en Italia”
- En pfSense usó WireGuard en vez de OpenVPN para un experimento base que enviara todo el tráfico del Apple TV por la VPN
- Instaló el paquete WireGuard de FreeBSD y agregó y activó un túnel
- Para la configuración de NordLynx, revisó la private key en una VM Linux con
sudo wg showconf nordlynxy la trasladó a pfSense
- En las pruebas, Google en la laptop aparecía en italiano, y YouTube en el Apple TV también cambió a italiano
- Los anuncios seguían apareciendo en parte, pero según dice eran menos que antes
- Netflix y Amazon Prime presentaron problemas, y parecía que se bloqueaban archivos CSS o fuentes, o que no cargaban las miniaturas
- Advierte que no se debe enviar todo el tráfico del Apple TV por la VPN, y considera que Netflix y Prime detectan muy bien a los proveedores de VPN y el geofencing
- Después configuró reglas de política de firewall para pasar por VPN solo el tráfico de YouTube del Apple TV, apuntando a
www.youtube.com,youtube.com,googlevideo.com,accounts.google.com,googleapis.comygstatic.com- Como resultado, YouTube veía al usuario como si estuviera en Milán, mientras que Netflix y Prime Video lo veían en Canadá
- Los anuncios se redujeron hasta ser muy esporádicos
- Un día después apareció una race condition de DNS
- Por defecto, el alias de hostname de pfSense se resuelve cada 300 segundos
- El TTL de DNS de YouTube puede ser de 1,440 segundos, es decir, 24 minutos
- Si la IP resuelta por Alias Daemon no coincide con la IP real que recibió el cliente, la política puede no tunelizar el tráfico de YouTube
- Algunos videos de YouTube no se reproducían y devolvían
403 Forbidden- Dice que YouTube incrusta la IP del usuario en cada solicitud a
googlevideo.com - Si dominios transformados como
r5---sn-hpa7kn76.googlevideo.comno pasan por el túnel, la solicitud sale con una IP incorrecta y causa el problema - Lo necesario sería tunelizar con comodín
*.googlevideo.com, pero las reglas de NAT y firewall operan con IP, no con hostnames comodín
- Dice que YouTube incrusta la IP del usuario en cada solicitud a
PoC de rastreo de IP basado en consultas DNS
- Se ideó un enfoque de secuestro de consultas DNS de Google Video para enrutar
*.googlevideo.compor la VPN- Consistía en rastrear periódicamente el log de consultas DNS para añadir las consultas
*.googlevideo.coma la lista de alias - Se consideró que, si cada video usaba un dominio único y modificado, este método no funcionaría a menos que se refrescara para cada video
- Consistía en rastrear periódicamente el log de consultas DNS para añadir las consultas
- El nuevo objetivo fue vigilar las consultas DNS con Python 3 y la API REST de pfSense para capturar la IP, retener brevemente la respuesta, añadir la IP a la regla de tunelización VPN y luego liberar la respuesta DNS
- Se instaló la API REST de pfSense y se envió una solicitud GET a
https://pfsense/api/v1/firewall/aliaspara consultar el aliasVPN_domains - Se exploró el módulo de Python de Unbound DNS Resolver y se logró registrar mensajes de consulta DNS
- La versión actual de Python era 3.8
- Se consideró que los ejemplos del módulo Python de Unbound estaban basados en Python 2.4, por lo que podrían requerir
2to3o formateo
- El script PoC extrae las IP de los registros A/AAAA de la respuesta DNS y las añade al alias de pfSense
- Los registros A se procesan con
ipaddress.IPv4Address(d.rr_data[j][2:]).exploded - Los registros AAAA se procesan con
ipaddress.IPv6Address(d.rr_data[j][2:]).exploded - El TTL del alias se configuró en 1 hora y la capacidad en 500
- Los registros A se procesan con
- Al día siguiente, Unbound DNS Resolver sufrió un segfault, y como había que recargar la regla de pfSense cada vez que se añadía una IP, pfSense se volvió muy lento
Cambio de Squid a mitmproxy
- El nuevo objetivo cambió a investigar e instalar un proxy de la familia Squid, crear un certificado de CA falso pero confiable y descifrar el tráfico TLS
- En las pruebas con Squid, se evaluó si el proxy
squid3ofrecido como paquete de pfSense cumplía los requisitos- Se creó una carpeta exclusiva
/squid_cachey se configuró el tamaño de caché en 8GiB - Se esperaba soporte HTTPS transparente
- Se creó una carpeta exclusiva
- Tras configurar Squid y SquidGuard durante un día, se abandonó el intento
- La velocidad era muy lenta
- La configuración de ACL era engorrosa
- Había un problema relacionado con
https://http/* - La actualización de la lista de filtros de URL de SquidGuard tardaba muchísimo
- La UI de Squid era insuficiente
- Después se decidió usar mitmproxy, escrito en Python
- Se eligió mitmproxy en lugar de
SSLSplitpor la extensibilidad mediante hooks de Python y por la UI - La versión de FreeBSD de pfSense era
12.2-Stable, compilación de 64 bits
- Se eligió mitmproxy en lugar de
- En el entorno base de pfSense, los jail estaban deshabilitados, así que se instaló
ezjailmanualmente y se creó un jail paramitmproxy- El jail se creó con
ezjail-admin create mitmproxy 'lo0|127.0.1.1' - Se configuró
allow.raw_sockets=1para el modo de proxy transparente - Se indicó que, si los raw sockets estaban bloqueados, podían aparecer errores como
Transparent mode failureoCannot open connection, no hostname given.
- El jail se creó con
- La ejecución del binario Linux tarball falló en FreeBSD
- Apareció
ELF interpreter /lib64/ld-linux-x86-64.so.2 not found - Tampoco se pudieron encontrar
libdl.so.2,libz.so.1,libpthread.so.0,libc.so.6
- Apareció
- Dentro del jail se ejecutó
pkg install mitmproxy, y la instalación requirió 50 paquetes, 206MiB de espacio adicional y 33MiB de descarga - Para permitir el acceso a MITMProxy desde la LAN, se asignó la IP virtual
127.0.1.1al localhost y se configuró temporalmente una regla NAT para redirigir[Private IPs]:8080a127.0.1.1:8080 - El archivo PEM de la CA generado automáticamente por MITMProxy es
~/.mitmproxy/mitmproxy-ca-cert.pem, y este certificado de CA se instaló en el Trusted Root Store del dispositivo de prueba mitmproxyusaba mucho CPU incluso en estado idle, y se consideró que la generación en tiempo real de certificados TLS por solicitud y el logging excesivo ralentizaban mucho el rendimiento- Se consideró que
mitmdump, al omitir la UI y el logging excesivo, tenía menor carga de CPU
- Se consideró que
Eliminación de anuncios JSON en YouTube web
- Certificate Pinning es una técnica en la que el servidor o el cliente conoce de antemano la huella digital esperada del certificado, por lo que la falsificación de certificados de MITMProxy no funciona
- Los hosts problemáticos se pueden hacer pasar por fuera del proxy con la opción
--ignore-hosts- Como ejemplo, se ignoraron
apple.com:443eicloud.com:443
- Como ejemplo, se ignoraron
- Mientras se accedía a YouTube, los anuncios de la página aparecían en MITMProxy con headers no cifrados, y se evaluó la posibilidad de bloquearlos con regex simples
- Para aplicar el script de bloqueo de anuncios de YouTube, se añadió
--scripts "youtube.py"amitmdump - El filtro smoke-test bloquea solicitudes de anuncios según subcadenas en la URL
youtube.com:/pagead/,/log_event?,/stats/ads,/stats/qoe?,/ptracking?,/generate_204,el=adunit,adformat=,/activeview?google.com,google.ca:/pagead/ggpht.com:.
- Las solicitudes que se intentaban bloquear efectivamente parecían estar bloqueadas tanto en MITMProxy como en el panel Network de DevTools, pero los anuncios seguían apareciendo y a veces se saltaban solos o fallaban al reproducirse
- Después se encontraron muchas URL relacionadas con anuncios dentro del payload JSON
- Incluía las secciones
playerAdsyplaybackTracking youtubeRemarketingUrlconteníahttps://www.youtube.com/pagead/viewthroughconversion/...googleRemarketingUrlconteníahttps://www.google.com/pagead/1p-user-list/...
- Incluía las secciones
- Tras analizar la UI de YouTube y el flujo HTTP, incluyendo cookies y service workers, se afirmó que ya era posible eliminar anuncios pre-roll, post-roll y mid-video
- En esta etapa, ya se podían eliminar anuncios desde el payload JSON de anuncios web de YouTube mediante el router
Problema de Protobuf en YouTube para iOS
- La app de YouTube para iOS mostraba datos muy similares en la versión Protobuf de las mismas llamadas API que la versión web
- En Protobuf, las claves son numéricas y pueden cambiar, así que no se puede usar un enfoque como JSONPath para encontrar la sección de anuncios
- YouTube enviaba en el payload una gran lista de anuncios que se verían después, y cuando esa lista se agotaba, poco después llegaba otra gran lista
- En el payload Protobuf aparecían cadenas como “Telus”, “Samsung TV”, “Boxing Week” y “Buy now”
- El protocolo de YouTube para iOS era distinto del tráfico web
- en la versión web se podían distinguir hasta cierto punto el video del anuncio y el video deseado viendo la URL y el query parameter
range - el protocolo de iOS no usaba ni el query parameter
rangeni el headerRange, sino contadores como&nr=2y&nr=3en los chunks de video - para bloquear anuncios en iOS fue necesario hacer reverse engineering de la respuesta Protobuf
- en la versión web se podían distinguir hasta cierto punto el video del anuncio y el video deseado viendo la URL y el query parameter
- En el mensaje Protobuf decodificado se encontraron los campos
has_unlimited_entitlement: Falseyhas_premium_lite_entitlement: False, pero en vez de alternarlos se volvió a usar heurísticas - Decodificar unos 500 KiB de Protobuf crudo con una implementación pura en Python era muy lento
- en una desktop con i7-6700, el resultado en Python fue de unos 2.06~2.11 segundos
- en un router pfSense, el resultado en Python fue de unos 22.8~24.2 segundos
- en C++ con
protoc --decode_rawfue de unos 0.017~0.022 segundos en desktop y de unos 0.12~0.14 segundos en el router pfSense
Decodificación de Protobuf e intento de extraer el esquema
- Como Python no soportaba decodificación raw de Protobuf, en vez de usar directamente
libprotobuf.sode C++ se eligió comunicarse con el binarioprotocde C++ mediantesubprocess.Popen - Se hizo fuzzing de respuestas de videos publicitarios probando
200vacíos,404,503, cuerpos de respuesta truncados y anulando parcialmente videos de anuncios, pero la app de iOS se ralentizaba, luego se cerraba o se quedaba congelada en la pantalla del anuncio - Bloquear URLs activaba el comportamiento de respuesta de la app, y los chunks de respuesta de video también incluían metadatos de sesión
- blackboxprotobuf para Burp Suite permitía decodificar mensajes wire raw de Protobuf, inyectar contenido y volver a codificarlo para verificar el comportamiento del endpoint Protobuf
- se recomienda usar la versión original para Burp Suite y no el fork de PyPI
- algunos forks tienen problemas de stack overflow o recursión infinita por recursión profunda
- usando bindings de C++ se podía transcodificar un Protobuf raw de unos 500 KiB en apenas unos segundos
- El esquema generado no era perfecto, era grande, estaba profundamente anidado y su pretty-print era lento, pero bastaba para encontrar los detalles del anuncio
- Se probaron PBTK, Apktool, dex2jar y Java Decompiler para intentar extraer archivos
.protoo de esquema reales del APK de YouTube para Android- PBTK solo extrajo un archivo proto de 59 bytes
- había clases Protobuf y getter/setter en Java, pero no se obtuvieron los verdaderos archivos de esquema, así que se abandonó ese camino
Punto de inflexión final: cambiar 1 byte del field tag de Protobuf
- A partir del tráfico de red descifrado y el fuzzing de Protobuf, se observó que los anuncios se registraban en slots de videos específicos
- los tipos de slot incluían pre-roll, mid-roll, end-roll, full-page y ad pods
- si se bloqueaba la URL del anuncio, ocurría un error del tipo “un anuncio inexistente reservó el slot” y la UI entraba en pánico
- Se consideró problemático decodificar, editar y volver a codificar sin el esquema original, porque eso producía una codificación modificada y no se podía saber si se usaba ZigZag, ni tipos numéricos como
int32,int64,sint32/64ovarint, además de que el orden de los campos del objeto normalmente es no determinista - Se encontró una posible vía de evasión en la backward compatibility de Protobuf y en el comportamiento de UnknownFieldSet
- cuando software antiguo lee un mensaje al que se le agregó un campo nuevo, pueden aparecer unknown fields
- si se cambiaba la clave de un campo específico por otro valor, toda la subestructura que contenía anuncios e información de tracking podía quedar en estado unavailable
- Como ejemplo, se propuso la idea de cambiar la field key
49399797a49399796para que esa subestructura de anuncio/tracking se tratara como un unknown field - La field key
49399797no se podía encontrar con una simple búsqueda hexadecimal, y había que considerar la codificación varint/tag- el wire type era
2, lo que significa una string o mensaje anidado delimitado por longitud - la secuencia de bytes del tag para la field key objetivo
49399797eraAA FF B8 BC 01 - al hacer
395198378 >> 3para eliminar los 3 bits del wire type se recuperaba la field key original49399797
- el wire type era
- Se usó una firma clásica de URL publicitaria como
/pagead/dentro de los bytes Protobuf para acotar el rango de búsqueda del campo, y desde esa posición se retrocedía para encontrar el field tag y la field key que había que modificar - En un log de intercepción de ejemplo, en una respuesta
application/x-protobufde 1.87 MiB a una solicitud POST ayoutubei.googleapis.com:443/youtubei/v1/browse?key=..., se encontró la key49399797en la posición4465y la key50195462en la posición4477 - En una smoke test O(n), se escaneó una sola vez un bloque de datos Protobuf de 1.8 MiB sin memoria adicional
- el objetivo se encontró en el byte 30,593 de los 1.8 MiB
- con unos 600 bytes de backtracking se encontró la field key que había que desnaturalizar
- Cuando este método funcionó, ya no fue necesario bloquear URLs con
*.googleadservices.como/pagead/, y esas solicitudes dejaron de generarse desde el principio
Estructura del script add-on de MITMProxy
- El script add-on de MITMProxy se ofrece como una prueba de concepto para bloquear anuncios de YouTube en dispositivos Apple conectados a la red
- El nombre del archivo es
youtube.py - Un ejemplo de ejecución es
mitmdump --listen-port 8080 --listen-host 127.0.0.1 -s "youtube.py" - Los prerrequisitos en FreeBSD son
pkg install protobuf,pkg install py38-pip,pip install jsonpath-ng
- El nombre del archivo es
- El script incluye una función de equidad que permite el 5% de los anuncios para apoyar a los creadores de contenido
in_allowed_ads_window()omite el bloqueo de anuncios si la hora actual está entre el minuto 0 y el minuto 2 de cada hora
YouTubeAdBlockerintercepta dominios relacionados con YouTube y modifica respuestas JSON o Protobuf para eliminar la información de anuncios- La regex de hosts interceptados es
\.youtube\.com|google\.(com|ca)|googleapis\.com|googleadservices\.com|googlevideo\.com - La cadena usada para detectar anuncios en Protobuf es
b"/pagead/" - El límite de búsqueda es
80_000bytes - El tag del campo objetivo es
50195462
- La regex de hosts interceptados es
- La lista de bloqueo en la fase de solicitud incluye
pagead/,log_event?,stats/ads,stats/qoe?,ptracking?,generate_204,error_204,adformat=,activeview?,_ad_,ai?,sw.jsy otros en hosts de YouTube - Los reemplazos JSON para YouTube web eliminan o desactivan campos relacionados con anuncios
yt_adse cambia a"0"adPlacementsse cambia a[]adPlacementRenderer,adPlacementConfig,playerAdParams,gutParamsse cambian a{}adVideoIdse cambia a""showCompanion,showInstream,useGutse cambian aFalse
- El hook
load()desactiva HTTP/2 y estableceanticomp=True,mode="transparent" - El hook
running()actualizaallow_hostspara que la interceptación se aplique solo a dominios relacionados con YouTube - El hook
response()busca/pagead/dentro de los primeros 80,000 bytes del cuerpo de la respuesta cuandocontent-typecontieneprotobuf- Si lo encuentra, crea los bytes del tag objetivo con
TagBytes(self.target_field_tag, WIRETYPE_LENGTH_DELIMITED) - Crea nuevos bytes con los bytes del tag de
target_field_tag - 1 - Busca en reversa antes de la posición de
/pagead/para encontrar el tag objetivo - Reemplaza los bytes en esa posición por los bytes correspondientes a
target_field_tag - 1 - Vuelve a insertar el contenido Protobuf modificado con
flow.response.set_content(bytes(body))
- Si lo encuentra, crea los bytes del tag objetivo con
- Los comentarios del código indican que esta prueba de concepto ya bloquea el 90% de los anuncios, y añaden que en otras secciones también hay otras claves de campo y podría haber varias secciones de anuncios que deban desactivarse
Rendimiento, límites y usuarios objetivo
- La técnica final aprovecha que Protobuf permite campos desconocidos para mantener compatibilidad hacia atrás ante cambios de esquema y la sensibilidad a ediciones de un solo byte de su formato compacto
- Si se cambia 1 byte en un punto crítico para que una sección profundamente anidada parezca pertenecer a una versión futura del esquema, Protobuf la ignorará y podrá eliminar la información de anuncios
- Google devuelve una gran respuesta Protobuf que incluso incluye el layout de la app de iOS, y el payload de ejemplo es de 1.8 MiB
- Para parsear todo el payload haría falta código nativo como C++ o Swift, y se dice que la decodificación en Python es varios órdenes de magnitud más lenta, provocando timeouts de conexión
- El JSON basado en web requiere parsear, editar y volver a serializar todo el payload, pero la técnica con Protobuf solo necesita un escaneo lineal y un retroceso rápido, así que se procesa en microsegundos, lo que la hace apta para bloqueo de anuncios en tiempo real y sin necesidad de una blocklist
- Todas las URL
*.googleadservices.comy/pagead/*en dispositivos Apple provienen del payload Protobuf, así que si desaparecen los datos de anuncios del payload, esas solicitudes también desaparecen automáticamente - La app de YouTube no intenta obtener las URL de anuncios, por lo que se siente más rápida y el contenido se reproduce de inmediato porque el anuncio no se registra en el slot de video
- Este enfoque se presenta como una técnica altamente especializada para bloquear anuncios de YouTube en dispositivos Apple o tráfico de rastreo de Instagram, WhatsApp y Facebook
- Se afirma que la carga de CPU de descifrar y volver a cifrar tráfico HTTPS supera ampliamente el rendimiento de una Raspberry Pi
- Como está dirigido a dueños de dispositivos Apple que no quieren comprometer su sistema operativo, se considera que el público objetivo es aún más limitado
YouTube Premium y experimento sobre el costo de los anuncios
- Se considera incierto si YouTube Premium tiene un precio razonable cuando cuesta CAD $9.99/mes o CAD $11.99/mes, y aproximadamente CAD $13.43/mes con impuestos
- Se realizó un experimento de exposición a anuncios viendo YouTube de forma intermitente durante un día con una laptop limpia y navegación privada
- En el historial de reproducción solo había 10 videos “vistos”
- Mientras veía partes de esos 10 videos, estuvo expuesto a 8 anuncios
- Solo 2 anuncios se podían omitir, y ambos fueron omitidos
- Suponiendo un CPV aproximado de USD $0.15, 8 anuncios al día equivalen a un costo para los anunciantes de
8 x $0.15 = $1.20, y extrapolado a un mes da unos USD $36/mes - También se presenta un cálculo basado en datos de Statista dividiendo el gasto publicitario en EE. UU. entre el total de vistas
- En 2019, los anunciantes de EE. UU. gastaron $15.1 billion en YouTube
- Se dice que los residentes de EE. UU. vieron 916 billion de videos
- El promedio es
$15.1B / 916B = USD $0.0165 per view - En su caso, calcula que eso equivale a unos USD $0.13 por día y unos USD $3.96 al mes en costo para los anunciantes
- Durante el experimento de anuncios tuvo el hardware en silencio y apartó la vista con frecuencia, por lo que considera que el gasto publicitario dirigido a él fue desperdiciado
- Aun así, dice que quiere apoyar a los creadores y que probará la prueba de 3 meses de Premium mientras sigue monitoreando qué rastrea Google sobre él
- Le preocupa que desde el momento en que se presenta un reclamo DMCA, todos los ingresos publicitarios puedan ir al reclamante y no al creador, y añade que no sorprende que muchos creadores se muden a Patreon
Resumen final
- Configuró un router de hardware desde cero y separó la LAN en zonas de confianza y no confiables
- Configuró el bloqueo de anuncios tradicional por DNS
- Añadió un proxy MITM transparente
- Finalmente, dice que logró bloquear anuncios de YouTube con buen rendimiento en dispositivos Apple conectados a la red
- Escribe que, como la parte difícil ya terminó, considerará pagar YouTube Premium, aunque añade que los rastreadores siguen bloqueados con fuerza
1 comentarios
Opiniones en Hacker News
Más que una falla del formato Protobuf, parece que el autor cambió el número de campo por un número grande sin usar
El método consiste en buscar firmas de URL de anuncios como
/pagead/en los bytes de Protobuf para delimitar el rango del campo y, desde ahí, retroceder para encontrar la etiqueta del campo objetivo y la clave del campo para neutralizarlo. Pero esto se acerca más a un comportamiento previsto que a una fallaSi uno ya se toma el trabajo de encontrar la etiqueta, tampoco es mucho trabajo adicional leer la longitud varint que está justo al lado y saltarse esos bytes. Habría que copiar el búfer o desplazar bytes, pero como los
bytesque devuelve la API de mitmproxy son inmutables, el script PoC ya tiene que hacer copiasAntes de cambiar el protocolo hasta el punto de que los anuncios dejen de aparecer por completo en versiones antiguas de la app, Google seguramente distribuiría primero una app nueva; así que con fijación básica de certificados o con una decodificación menos tolerante ante fallas al extraer información de anuncios podrían bloquear este método de inmediato. Si fuera el equipo de YouTube, probablemente vería esto como una falla
bytesson inmutables, pero los objetosbytearrayno lo sonCon un pequeño proxy en C++/Go también se podría hacer lo mismo con mucha menos sobrecarga. Para una tarea tan bien definida, sería más estable y requeriría menos esfuerzo que pelearse con mitmproxy
Si envías todo el tráfico por el proxy, el rendimiento cae incluso usando interceptación de SNI. Con pfSense pasa lo mismo: con un servidor Linux simple y unas reglas sencillas de iptables se puede resolver sin pelear contra las capas de abstracción de pfSense
Basta con escribir en un archivo
.protosolo los campos del proto obtenidos por ingeniería inversa que hagan falta, generar el código automáticamente y cambiar el flag. Es más barato que la implementación en Python y más fácil de actualizar aunque cambie el proto. Ignorar etiquetas de campos desconocidas es una función importante de Protobuf, y permite cambios de esquema compatibles sin romper despliegues existentesEl autor parece haber estado al tanto de gran parte de los comentarios, y el artículo es bastante minucioso. Hizo benchmarks en Python y C++, y la implementación final ni siquiera decodifica Protobuf. También probó varias soluciones mitm, y usa pfSense no como un simple router de seguridad, sino para apuntar solo al tráfico del Apple TV mediante VLAN y VPN
Este comentario se siente demasiado barato y despectivo. El artículo original no es así, así que si vas a decir eso deberías demostrarlo tú mismo para la comunidad
Si pago YouTube Premium, ¿eso apoya a los creadores? Si es así, me pregunto cuánto en comparación con un apoyo directo como Patreon
Lo que una suscripción a YouTube Premium le genera a un creador individual será mínimo, pero sigue siendo mejor que ver videos con bloqueador de anuncios
Como se basa en el tiempo de reproducción y no en impresiones de anuncios, favorece más a los creadores de contenido de formato largo
La cuenta de YouTube de mi novia, curiosamente, no muestra anuncios sin importar en qué dispositivo inicie sesión. Incluye Apple TV, no es Premium y nunca lo fue
Me pregunto si internamente tiene algún flag activado que deshabilita los anuncios
Recién entonces llegó el momento en que entendí por qué la gente se quejaba
Aunque no uso bloqueador de anuncios, con solo iniciar sesión no veo anuncios ni en el sitio web ni en la app móvil. No tengo Twitch Turbo y ya no tengo Amazon Prime. Tampoco tengo otros beneficios de Turbo, así que no es que esté marcado completamente como Turbo
No sé si, cuando antes hacía bug bounty y toqueteaba varias cosas, el perfil de mi cuenta se rompió por casualidad, pero si me dejan conservar este beneficio, puedo dar más información
Lo raro es que recuerdo que una vez, en el hospital, drogado con medicamentos y con dolor, solo quería ver TV, pero los anuncios de Twitch eran tan insoportables que casi tuve un colapso. Luego, uno o dos años después, de pronto me di cuenta de que no había visto anuncios en años
Probablemente exista algún test A/B sin anuncios olvidado hace tiempo y quedó ahí porque no vale la pena limpiarlo. Gracias a eso me beneficié durante años y veo Twitch más que cualquier otra plataforma. Twitch Turbo en el Reino Unido cuesta £12 al mes, unos $15.50, así que está entre los caros a nivel mundial; comparado con los $12/€12 de EE. UU. y Europa, es un precio bastante desfavorable
Fue bastante sorprendente que, si se pone un proxy man-in-the-middle entre el Apple TV e Internet externo, se pueda descifrar el tráfico HTTPS.
Normalmente pensaría que no debería funcionar, y después me volvió a sorprender saber que se puede agregar una CA al almacén de certificados del Apple TV. Fue un artículo muy minucioso que recorre todo el stack.
Por ejemplo, en universidades había que poner la dirección MAC en una lista de permitidos o instalar un certificado para conectar un dispositivo al Wi-Fi.
Pero si hiciera eso, YouTube podría romperse en muchos entornos corporativos, así que no sé si realmente lo harían. Aun así, lamentablemente sería muy fácil bloquearlo.
Intenté implementarlo varias veces en Apple TV, pero no tuve ningún éxito. Parece que YouTube ya incorporó certificate pinning en la app o algo por el estilo. Me pregunto si alguien logró hacerlo funcionar recientemente.
[0] https://frida.re/docs/home/
Me gusta cualquier intento de bloquear en toda la red esos pésimos servicios en línea que nos vemos obligados a usar.
Bloquear anuncios está bien, pero ojalá hubiera formas más fáciles y generalizadas de bloquear en toda la red cosas como YouTube Shorts o Instagram Reels, con su scroll infinito agresivo.
En Instagram solo quiero ver las publicaciones e historias de la gente que sigo, no que me recomienden videos tontos diseñados para robarme la atención. Tal vez esto revele falta de fuerza de voluntad, pero a menudo termino viendo algunos y pierdo 15 minutos de mi vida.
En general, los usuarios de Internet eligieron no querer pagar, así que alguien termina asumiendo el costo. En conjunto, los usuarios de Internet no recompensan a quienes no muestran anuncios. Quieren contenido, pero por lo general lo quieren gratis.
Encontré un script que convierte la página de Instagram en algo más parecido a una etiqueta de imagen para que solo puedas ver fotos: https://greasyfork.org/en/scripts/5014-un-instagram
Por eso, más que falta de fuerza de voluntad, me parece una especie de insensibilización que hemos acumulado, y eso es bastante malo. Son respetables el esfuerzo y la creatividad para volver a que nosotros usemos las plataformas, en vez de que las plataformas nos usen a nosotros.
Hablo con mis hijos regularmente, y ellos también están de acuerdo en que es dañino, pero les resulta demasiado difícil resistirse. Incluso yo a veces me veo arrastrado al doomscrolling.
Donde puedo, configuré filtrado de anuncios con Pi-hole, pero no quiero bloquear YouTube por completo. Aun así, para proteger a mi familia, creo que en adelante tendré que considerarlo seriamente.
La ingeniería es buena, pero da un poco de tristeza que haya que llegar tan lejos para poder usar tu propio hardware o software como si fuera tuyo, aunque sea en cierta medida.
¿YouTube tiene anuncios? No lo sabía porque el navegador los bloquea demasiado bien.
El verdadero problema es que la experiencia en Apple TV es mucho peor que la de un navegador web común. Apple tiene el hardware tan cerrado que termina favoreciendo más los ingresos publicitarios de YouTube que al consumidor final que pagó por el dispositivo.
Lo mismo pasa cuando navego la web desde el iPad fuera de la red Pi-hole de mi casa. No sé cómo la gente aguanta esto todos los días.
El iPad es un dispositivo proporcionado por el trabajo, así que no lo uso mucho para cosas personales, pero cada vez que lo uso me recuerda lo molesto que es.
Curiosamente, antes de recibir el iPad pensaba que solo sería útil para consumir contenido, pero en la práctica resultó muy cómodo para acceder rápidamente de forma remota a recursos de trabajo, mientras que para navegación web general y streaming quedó atrapado en un páramo cubierto de anuncios.
Si necesitas YouTube sin anuncios, puedes usar https://yewtu.be u otra instancia de Invidious https://docs.invidious.io/instances/.
Entre YouTube e Invidious hay una carrera armamentista, y a veces Invidious deja de funcionar, pero el equipo siempre ha encontrado nuevas formas de esquivar a YouTube y entregar videos sin anuncios.