La VPN está activa, la interfaz web privada responde por IPv6 desde un portátil, y el teléfono Android sigue abriendo la misma página por IPv4 o se niega a cargarla. El registro AAAA existe. El túnel informa de una dirección IPv6. Nada en el cliente parece estar mal. Cuatro decisiones separadas determinan el resultado: qué resolutor respondió, qué declaró VpnService a Android, qué familia de direcciones estaba dispuesto a probar el navegador y si un paquete puede completar el viaje de ida y vuelta. Abórdelas en ese orden en lugar de añadir una ruta por defecto y esperar que el síntoma se mueva.

Paso 1: demuestre qué resolutor respondió a la consulta AAAA

Android no tiene una única ruta DNS. Una VPN puede empujar un servidor DNS para su red, el sistema puede usar Private DNS para los nombres de host que considera cualificados, y Chrome puede ejecutar su propio resolutor cifrado desde chrome://settings/security. En un teléfono donde el túnel empuja 10.61.0.1 pero Private DNS apunta a un proveedor público, el nombre dentro de su zona privada no lo resuelve la máquina que posee la zona. El navegador obtiene una respuesta de un resolutor sin autoridad sobre ese nombre y la trata como ausente, y el texto del error nunca menciona DNS.

Pregunte directamente al resolutor del túnel antes de cambiar cualquier otra cosa. Los dos primeros comandos muestran qué servidores DNS ha asociado Android a la red activa y si Private DNS está en modo automático o estricto; el tercero se ejecuta desde cualquier cliente dentro del túnel, no desde el teléfono.

adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1

Paso 2: lea qué declaró realmente VpnService

El lado de Android es explícito y no inferido. Un VpnService.Builder añade direcciones con addAddress, rutas con addRoute, servidores DNS con addDnsServer, y puede restringir todo el túnel a una sola familia de direcciones con allowFamily. Un constructor que llamó a allowFamily(AF_INET) y después añadió una ruta IPv6 ha dicho al sistema dos cosas contradictorias, y la restricción de familia es lo que conserva el sistema. Una ruta que cubre fd00:61::/64 combinada con una dirección de interfaz en otro prefijo falla por una razón similar: la dirección existe, pero no está on-link para esa ruta.

Lea la declaración en lugar de confiar en el interruptor de la aplicación. dumpsys netd imprime las direcciones y rutas asociadas a la interfaz tun, y el LinkProperties por red dentro de dumpsys connectivity muestra la lista DNS junto a las familias que la red declara.

adb shell ip -6 addr show tun0
adb shell ip -6 route show table all | grep tun0
adb shell dumpsys connectivity | grep -E "LinkAddresses|Routes"

Si la interfaz tun tiene una dirección IPv6 pero ninguna ruta coincide con el prefijo del servicio, la entrega de IPv6 ya está rota antes de que intervenga un navegador. Es un fallo distinto al de un navegador que se niega a probar, y necesita una corrección distinta.

Paso 3: el navegador decide si probar IPv6

Chromium no utiliza todos los registros AAAA que recibe. Su resolutor de hosts lleva comprobaciones de alcanzabilidad de IPv6 y filtrado de candidatos que pueden descartar o bajar la prioridad de IPv6 cuando se juzga que la red no puede transportarlo, y el código fuente del resolutor muestra esa sonda junto con las condiciones que la rodean. La lógica depende de la versión y de los indicadores, y es exactamente por eso que dos teléfonos en el mismo túnel pueden comportarse de forma distinta. Una vez que existen candidatos, Happy Eyeballs hace competir a las familias por cada conexión, así que una ruta IPv6 que responde despacio todavía puede perder frente a IPv4 que responde rápido.

Observe la decisión en lugar de inferirla. Una sesión grabada con chrome://net-export y reproducida en el visor de netlog muestra cada resolución y la familia elegida; chrome://net-internals/#dns muestra los resultados en caché. Una resolución que devuelve solo registros A para un nombre que tiene AAAA en su propio resolutor apunta directamente a esta etapa.

Paso 4: verifique que un paquete puede completar el viaje de ida y vuelta

La selección de dirección no es entrega. Android mantiene tablas de enrutamiento y reglas de política por red que eligen una tabla por fwmark, así que una ruta visible en la tabla principal no es automáticamente la ruta que usa un socket. Leer las reglas y pedir al núcleo que resuelva un destino para una dirección de origen separa las dos cosas.

adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10

La salida de route get es la que responde a la pregunta. Si nombra tun0 y los paquetes siguen muriendo, pase a la MTU del túnel y al reenvío IPv6 de la puerta de enlace en lugar de volver al teléfono.

Por qué añadir ::/0 suele empeorarlo

Añadir ::/0 cambia la pretensión del túnel de un prefijo a todos los destinos IPv6. En el teléfono eso puede satisfacer una sonda de alcanzabilidad, porque una dirección de prueba fuera de su prefijo ahora parece enrutable. No crea capacidad IPv6 ascendente en la puerta de enlace, y muchas puertas de enlace domésticas no tienen ningún enlace ascendente IPv6 que funcione. El resultado es un agujero negro para IPv6 público: nombres que antes caían a IPv4 ahora se cuelgan, y la página privada puede parecer mejor solo porque la sonda mide algo distinto.

También hay un coste de política. Con ::/0 en el túnel, todo el tráfico IPv6 sale por la VPN, incluido el tráfico que el propietario de la red nunca aceptó transportar. Trátelo como una decisión de despliegue con un propietario con nombre, no como un paso de depuración que se toma a la 1 de la madrugada.

El orden de trabajo que termina con esto

Confirme que la respuesta AAAA viene del resolutor que posee la zona, lea el estado de VpnService y netd para la interfaz tun, capture un rastro net-export para ver si Chromium descartó el candidato, y después pruebe el viaje de ida y vuelta con ip -6 route get. Corrija la capa que realmente falló y deje la política de división tranquila. Si los nombres privados necesitan respuestas distintas de los públicos, para eso existe el split tunneling.

Anote la compilación del teléfono, la versión del navegador y el resolutor que consultó. Esos tres hechos convierten "IPv6 is broken" en algo que la siguiente persona puede reproducir.

Artículos relacionados