Skip to content

ADR-0005: Extender el patrón tv-gw a móviles familiares — privacy audit personal

Campo Valor
Status Proposed
Date 2026-05-17
Decision by ramon
Reviewers claude (Opus 4.7 1M)
Supersedes
Builds on ADR-0001 lg-tv-monitoring (LXC 110 tv-gw, transparent L3 gateway + Zeek/Loki)

Contexto

El proyecto tv-gw (LXC 110 en pmx-50, 192.168.0.210) lleva 13 dias funcionando como gateway L3 transparente de la LG 43UQ80006LB. Stack: nft routing/masquerade + Zeek 8.0.7 LTS (ssl/dns/conn/http JSON) + Promtail → Loki .208:3101 (labels host=tv-gw, log_type=*) + node_exporter :9100 + dashboard Grafana tv-lg-monitoring + Pi-hole client group tv-lg (75 dominios blocked, regex .avs.amazon.dev + .apl-alexa.com). Resultados Fase 2: solo 12 SNIs distintos en 7d, 174 conexiones, 100% telemetría LG bloqueada.

El usuario quiere replicar el patrón sobre dispositivos móviles familiares identificados en HA:

  • iPhone 16 Pro (Ramon)
  • iPhone (Gloria)
  • iPad mini
  • MacBook Air (Ramon)
  • mac-4415
  • Apple TV (dormitorio, otros)

Objetivo: dashboard "privacy audit semanal" por dispositivo: trackers Meta/Branch/Adjust/Mixpanel/Segment/AppsFlyer/etc, comparativa entre apps (¿qué fuga más, Instagram vs WhatsApp vs Reddit vs apps de banca?), identificar leaks no obvios.

Por que ahora: el pipeline Loki+Zeek+Grafana ya está pagado en complejidad; añadir N hosts más es marginal. El cañonazo iPhone-ads del 9-may (OISD Big + HaGeZi Pro++, +19 entries denylist) ya validó que el iPhone .199 servía como cobaya útil (87% queries bloqueadas tras), pero quedó anónimo en Pi-hole porque sale como cliente .1 (R2 forwarder) — falta granularidad per-device.

Retos técnicos reales (no escondidos)

R1. Forzar a un iPhone a usar gateway alternativo es mucho mas difícil que una TV

La TV LG nos vino regalada: webOS permite configuración manual de gateway en Settings. iOS no expone override de gateway/ruta en UI sin profile MDM. Las opciones:

# Aproximación Friccionalidad Cobertura Sostenibilidad
A Gateway estático configurado a mano en cada device Alta (cada update iOS/macOS lo puede revertir, "Forget WiFi" lo borra) 100% wifi Mala
B Secondary DHCP server (LXC) sirviendo gateway=.210 a MACs específicas Conflict con R2 Movistar (race condition DHCP responses) 100% wifi si gana la carrera Muy mala — R2 Movistar firmware cerrado, no se puede desactivar DHCP propio
C ARP spoofing desde tv-gw para impersonar gateway Invasivo, fragil, detectable, eticamente turbio incluso en LAN propia 100% wifi Mala
D Segundo SSID "Casa-Privacy" en AP nuevo con uplink vía .210 Compra ~50€ (Ubiquiti U6 Lite o similar), devices opt-in al SSID 100% en ese SSID, devices eligen Buena
E WireGuard on-device a LXC 155 + nft rules que enrutan peers vía tv-gw Requiere app WG instalada en cada device + always-on toggle iOS 100% cuando VPN ON, cellular incluido Excelente para Mac/iPad, friccional en iPhones familiares
F Proxy explicito (Squid/mitmproxy con CA personalizada) iOS pide instalar profile (rechazo familiar previsible), Mac OK Solo HTTP/HTTPS, no apps con cert pinning Mala para familia

R2. SNI-only no es DPI, y va a empeorar

Lo que el stack actual ve sin MITM: - SNI en ClientHello TLS — visible hoy para ~95% de apps - DNS (vía Pi-hole) si el device usa .204 como resolver - Conexion 5-tuple + bytes (Zeek conn.log)

Lo que NO ve: - Contenido cifrado (obvio) - ECH (Encrypted Client Hello): Cloudflare lo tiene en GA desde 2024, Apple lo activó parcialmente en iOS 18.x. Zeek 8 detecta presencia (ssl.log campo ech) pero no destino. En 2-3 años, ECH adoption ≥ 50% → SNI inspection se degrada a estadística agregada. - DNS-over-HTTPS / DNS-over-Quic: si Safari/Chrome/apps usan DoH a Cloudflare/Google bypaseando Pi-hole, se evade el filtrado DNS. Mitigación: drop tcp/udp 853 + drop IPs DoH well-known (ya aplicado a la TV). - MASQUE / HTTP/3 sobre QUIC: cada vez mas apps. Zeek 8 lo parsea pero menos info que TLS clasico.

Aceptación honesta: estamos haciendo observación SNI-grade, no DPI. Eso basta para identificar destinos (apps llaman a graph.facebook.com, api2.branch.io, app.adjust.com) pero no qué payload envían.

R3. Cellular fallback es un agujero permanente

Cuando iPhone esta fuera de wifi (o si activamos "Low Data Mode" agresivo en una app), sale por 4G/5G — fuera de nuestro alcance total. Solo capturamos sesiones wifi en casa. Para un audit semanal de hábitos en casa, suficiente. Para tracking completo del device, imposible sin pagar Charles Proxy / mitmproxy en device-by-device manual.

Excepción E: WireGuard on-device fuerza todo el tráfico (incluido cellular) a salir por el túnel → tv-gw. Es la única aproximación que cierra el agujero cellular. Coste: VPN always-on drena batería ~5-10% extra, latencia subida ~20-50ms, y el usuario familia debe consentir un VPN que tu controlas.

R4. Etica familiar y consentimiento

Monitorizar el trafico SNI del iPhone de Gloria (pareja del usuario) sin consentimiento explícito no es aceptable, independientemente de la legalidad técnica (red propia, propiedad sobre la infraestructura). Aunque no veamos contenido, ver "Gloria abrió Tinder a las 23:47" o "Gloria consultó api.clinicaX.es" es una invasión de privacidad inaceptable en una relación.

Plan de consentimiento obligatorio: 1. Explicar a cada miembro familia qué se captura (SNI = "dominio de destino", DNS = "preguntas DNS", NO contenido). 2. Mostrar un ejemplo concreto del dashboard de la TV — ya es publico y no controvertido. 3. Opt-in explícito por device. Documentar en ~/stacks/docs/consent-log-privacy-audit.md (fecha, persona, devices opted-in, alcance). 4. Kill-switch trivial: si alguien pide salir, flush sus logs Loki (logcli delete por label device_owner=gloria) y revert config (quitar del SSID Casa-Privacy, desinstalar WG, revertir gateway). 5. Datos nunca se exponen fuera de la LAN — el dashboard solo via CF Access con monxas.casa domain (politica D6 ADR-0003).

Sub-decisión implícita: si Gloria no consiente, su device queda fuera. No se hace silenciosamente. Punto.

R5. Stage por device, no big-bang

Patrón tv-gw demostró valor de fase 0 passive antes de bloquear. Replicar:

  1. Empezar Mac (MacBook Air de Ramon) primero — control total, no requiere pelea con iOS limitations, sirve como prueba del pipeline multi-host
  2. Luego iPad mini — iOS pero solo del usuario, low risk
  3. iPhone 16 Pro (Ramon) — completo
  4. mac-4415 (otro Mac del entorno) — Si aplica
  5. Apple TV dormitorio — equivalente a la LG, fácil técnicamente
  6. iPhone Gloriasolo tras consent flow + valor demostrado en steps 1-3

Decisión

D1. Stack base híbrido D (segundo SSID) + E (WireGuard opt-in)

No elegir una sola aproximación. Cada device va por el camino de mínima fricción para su perfil:

  • MacBook Air, mac-4415, Apple TV dormitorio: gateway estático en config wifi → tv-gw .210. Macs no se mueven, Apple TV nunca, friccion zero tras setup inicial. (Aproximación A, viable solo para devices estáticos.)
  • iPad mini: WireGuard always-on (Aproximación E) — el iPad sale de casa raramente, always-on funciona bien, y captura cellular si se activa.
  • iPhones (Ramon, Gloria-si-consiente): Aproximación D — segundo SSID "Casa-Privacy" en AP nuevo. Devices se conectan voluntariamente, ningun cambio de config en el device. Esta es la decisión clave que requiere compra HW.

HW propuesto: Ubiquiti U6 Lite (~99€) o TP-Link EAP610 (~70€). PoE preferible, montaje wall/ceiling. Uplink al switch existente, VLAN nativo configurado, gateway DHCP servido por el AP → .210. Pendiente decision finanzas: ~80€ es trivial para el valor.

D2. Reutilizar stack Zeek+Loki+Grafana sin cambios estructurales

El LXC 110 tv-gw se renombra mentalmente a pa-gw (privacy-audit gateway) pero no se mueve ni duplica. Capacidad actual (2 cores, 2GB RAM, 4GB rootfs, ~50 Mbps observed) cubre con holgura 6-8 devices móviles wifi.

Cambios mínimos: - Promtail añade label device_mac y device_owner extrayéndolo de Zeek conn.log id.orig_h mapeado a MAC vía dhcp.log o tabla estática /etc/promtail/device-map.json - Dashboard Grafana nuevo privacy-audit-mobile (uid TBD), template var $device multi-select sobre label device_owner - Pi-hole client groups separados por device (ya soporta — usado para tv-lg)

Hardware upgrade contingente: si CPU del LXC pasa de 60% sostenido, subir a 4 cores. ZFS dataset zfs-ha/subvol-110-disk-0 quota 4GB → 8GB si Zeek genera más logs.

D3. SNI-only, NO MITM con CA personalizada

Descartado MITM por: - iOS requiere instalar profile MDM, fricción inaceptable para familia - Apps modernas con cert pinning (Instagram, WhatsApp, banca, casi cualquier app seria) rompen → expone que estamos haciendo MITM - Mantener CA + keys = superficie de ataque nueva

Aceptamos limitación: vemos con quién habla el device, no qué dice. Para audit de trackers, suficiente — los trackers se identifican por dominio destino (graph.facebook.com, app.adjust.com, *.branch.io, *.mixpanel.com, *.segment.io, *.amplitude.com, etc.).

D4. Bloqueo DoH / DoT / DoQ por defecto

Replicar reglas nft de la TV en pa-gw para todos los devices que pasen por él: - drop tcp/udp 853 (DoT/DoQ) - drop tcp/udp :443 a IPs DoH well-known (1.1.1.1, 1.0.0.1, 8.8.8.8, 8.8.4.4, 9.9.9.9, 149.112.112.112, Mozilla) - DNAT udp/tcp :53 → Pi-hole .204 si daddr != .204

Trade-off conocido: Apple Private Relay (iCloud+) y Firefox-with-DoH-on no funcionarán mientras el device esté en pa-gw. Decisión explícita: el usuario acepta esto en su iPhone. Para devices de familia consentida, banner-grade warning antes del opt-in.

D5. ECH es un riesgo conocido sin mitigación clara

ECH (Encrypted Client Hello) es una limitación arquitectónica creciente. No vamos a bloquearlo (lo cual rompería conectividad a Cloudflare). Aceptamos que en 2-3 años: - SNI visibility caerá progresivamente - El valor del dashboard se reducirá a "ASN/IP-level inspection" + DNS - Posible pivote futuro: complementar con DNS-level deep insight (Pi-hole query log enriquecido con CT/whoami por ASN)

Status quo del proyecto en 2028-2029: revaluar. Si SNI < 50% útil, retire stack o pivote a NetFlow puro.

D6. Consentimiento explícito + kill-switch trivial

Ver R4. Hard requirement antes de tocar cualquier device que no sea propiedad personal del usuario.

~/stacks/docs/consent-log-privacy-audit.md formato:

| Date       | Person | Devices              | Scope             | Revoked |
|------------|--------|----------------------|-------------------|---------|
| 2026-05-XX | ramon  | iPhone 16 Pro, iPad  | SNI+DNS, full     | —       |
| 2026-XX-XX | gloria | iPhone               | SNI+DNS, opt-in   | —       |

Revocation flow: 1. Pi-hole client group remove 2. SSID Casa-Privacy disconnect (cambiar PSK si necesario) 3. logcli delete --query={device_owner=X} --start=<onboard-date> 4. Update consent log con fecha revoked

Plan incremental

Fase 0 — Setup pipeline multi-host (1 día)

  • Tabla device-map.json en pa-gw mapeando MAC → device_owner + device_friendly_name
  • Promtail config extiende labels Zeek con join MAC desde tabla
  • Dashboard privacy-audit-mobile con paneles base: top SNIs by device, top trackers (regex match contra lista pública trackers like *.branch.io, *.adjust.com, *.appsflyer.com, *.mixpanel.com, graph.facebook.com, etc.), bytes-by-app heuristic
  • Lista pública trackers como dashboard template var (Disconnect.me tracking-protection list)

Fase 1 — MacBook Air primero (1 día)

  • Set gateway estático .210, DNS .204 en config wifi
  • Verificar trafico pasa por pa-gw (Zeek conn.log)
  • Detectar SNIs durante 48h en uso normal
  • Dashboard muestra device_owner=ramon-mba

Fase 2 — iPad mini con WireGuard (1 día)

  • WG client en iPad, peer config a LXC 155 wireguard existente
  • nft en LXC 155 force-route peer-ip → pa-gw 210
  • Always-on toggle en iOS Settings → VPN → WG → Connect on Demand
  • Validar trafico capturado incluye cellular cuando iPad sale de casa

Fase 3 — Análisis 7d observe-only (semana)

  • No bloquear nada todavía
  • Generar primer "privacy audit weekly report" en Grafana: top 20 trackers contactados, comparativa por app/device, fugas no esperadas
  • Decidir blocklists basadas en datos reales (no especulación)

Fase 4 — Bloqueo selectivo + iPhone Ramon (1 día)

  • Pi-hole client group mobile-privacy con denylists derivadas de Fase 3
  • Apply a iPhone Ramon (gateway estatico o segundo SSID si AP ya está)
  • Monitor 24h por breakage de apps (esperable: ~5-10% apps gratuitas degradadas)

Fase 5 — HW segundo SSID (compra + 1 día setup) [OPCIONAL]

  • Comprar Ubiquiti U6 Lite o TP-Link EAP610 (~80€)
  • SSID Casa-Privacy con gateway → pa-gw
  • Migrar iPhones a Casa-Privacy
  • Eliminar friccion de gateway estatico
  • Conversación explícita con Gloria sobre alcance
  • Si consent: opt-in iPhone Gloria, log entrada en consent-log
  • Si NO consent: cerrar Fase 6, el iPhone de Gloria NUNCA entra en pa-gw

Fase 7 — Apple TV dormitorio (trivial, 30min)

  • Gateway estatico .210, DNS .204
  • Comparar SNIs vs LG salon (esperable: mismos servicios streaming, sin telemetría LG nativa pero con Apple analytics)

Fase 8 — Runbook + alertas (1 día)

  • Regla Grafana pa-gw-down (replica tv-gw-down)
  • Healthcheck privacy-audit-weekly-report cron Sunday que pinguea HC tras generar PDF/HTML del dashboard
  • Documentación en ~/stacks/docs/runbooks/privacy-audit.md

Alternativas descartadas

A1. Comprar PiRogue / pwnagotchi / sniffer dedicado

Descartado. Stack tv-gw + Zeek ya cubre lo que PiRogue ofrece, sin tener otro dispositivo HW que mantener.

A2. Solo DNS-level analysis vía Pi-hole (sin Zeek/SNI)

Descartado para el objetivo. Pi-hole ve dominios resueltos, pero NO ve apps que usan IPs hardcoded ni DoH escapando. Necesitamos el L3+L4 view del LXC para confirmar destinos reales. Pi-hole es complemento, no sustituto.

A3. NextDNS / ControlD cloud DNS con dashboard

Descartado. Externalizar logs DNS de familia a tercer party va contra el espíritu del audit (estamos auditando privacidad — irónico delegar logs a empresa que vive de ellos). Mantener todo on-prem.

A4. eBPF on-device (macOS) con Network Extension custom

Descartado. Solo Mac, no iOS. Coste de implementación >> beneficio.

A5. Big-bang multi-device sin staging

Descartado. Patrón tv-gw demostró que Fase 0 observe-only es donde aparecen las sorpresas. Replicar.

Consecuencias

Positivas: - Visibilidad inédita de dónde fugan datos los devices de la casa - Material educativo concreto (mostrar a Gloria "mira lo que hace tu Instagram") - Reutilización 90% del stack tv-gw — coste marginal de ingeniería - Hardening Pi-hole: blocklists derivadas de datos reales, no genéricas - Fundamento para futuras decisiones (¿dejar de usar app X que filtra demasiado?)

Negativas / riesgos: - Friccion familia si UX se degrada (apps rotas por blocklists). Mitigación: observe-only 7d antes de bloquear; whitelist trivial. - HW investment 70-99€ si optamos por segundo SSID. Aceptable. - ECH erosionará valor del stack en 2-3 años. Aceptable: el valor hoy sigue siendo alto. - Cellular fallback fuera de alcance excepto para devices con WG always-on. Aceptable: el audit es de hábitos en casa. - Riesgo etico crítico: si se monitoriza a alguien sin consentimiento, daño relacional. Mitigación: D6 hard requirement.

¿Vale la pena igual?

Sí. Defensa: 1. El stack ya existe (pa-gw = tv-gw renombrado). Cada device extra es ~30min setup. 2. La degradación ECH es gradual, no overnight. Tenemos 2-3 años de valor pleno. 3. SNI-only es suficiente para identificar trackers por dominio, que es el 80% del objetivo. 4. Cellular fallback se resuelve con WG para devices propios del usuario. 5. El stack genera conocimiento — la curiosidad/aprendizaje es valor en sí, exactamente como con la TV LG. 6. Como producto secundario: blocklists Pi-hole derivadas de datos reales, no listas genéricas, sirven a TODA la red.

Si en 2028 ECH alcanza 70%+ adoption y el dashboard se vuelve estadística agregada poco útil, retire el stack o pivote. Coste de retirada: borrar LXC, borrar dashboards, borrar reglas Pi-hole. Trivial.

Pendientes inmediatos

  • Conversación con Ramon-solo: ¿avanzamos? (este ADR es esencialmente para él)
  • Renombrar LXC 110 mentalmente a pa-gw o crear LXC 111 separado (decisión: renombrar in-place, no duplicar — TV LG sigue en la misma máquina, comparte stack)
  • Comprar AP secundario (Fase 5) — gating: ¿queremos Casa-Privacy SSID?
  • Redactar consent-log template antes de tocar cualquier device de familia
  • Empezar Fase 0+1 (Mac Air) esta semana si hay luz verde

Referencias

  • ADR-0001 lg-tv-monitoring (autocontenido en /Users/ramonkamibayashicarrera/lg-tv-monitoring/docs/adr/0001-lxc-transparent-gateway-for-lg-tv.md)
  • lg_tv_monitoring.md (memoria persistente)
  • observability_stack.md (Loki/Prometheus/Grafana details)
  • homeassistant_access.md (devices conocidos en HA)
  • Cañonazo iPhone-ads 2026-05-09 (entrada en observability_stack.md Pi-hole admin)
  • ADR-0003 D6 (CF Access pattern, para exponer dashboard externamente si se quiere)