Enrutamiento VPN en Android: reglas de política antes de la tabla main
Android elige una tabla de enrutamiento con reglas de uid y de marca antes de cualquier búsqueda de destino, así que una ruta añadida a main puede no consultarse nunca.
Una ruta añadida a la tabla main en Android se ve correcta en cualquier listado y aun así no transporta el tráfico. La razón es que la tabla main es una opción entre varias y no se consulta primero. El servicio de red de Android construye reglas de política que seleccionan una tabla de enrutamiento usando información que la dirección de destino no contiene — el uid de la aplicación, una marca en el paquete, la interfaz por la que llegó — y la búsqueda de destino ocurre después, dentro de la tabla que hayan elegido esas reglas.
Tres decisiones en un orden fijo
Un paquete de salida toma tres decisiones separadas. Primero, una regla de política decide qué tabla de enrutamiento se aplica. Segundo, una ruta dentro de esa tabla decide el siguiente salto y la interfaz de salida. Tercero, los ganchos de netfilter deciden si el paquete sobrevive, se modifica o se redirige.
El orden importa porque cada etapa solo puede responder a su propia pregunta. Una regla de cortafuegos que acepta un paquete no selecciona una tabla, y una ruta añadida a una tabla que ninguna regla selecciona es inerte. Buena parte de la confusión con las VPN de Android viene de corregir una de las tres y no observar ningún cambio, porque el fallo estaba en otra.
| Stage | Selector | What it cannot decide |
|---|---|---|
| Policy rule | uid range, mark, incoming interface | Which route exists inside the table |
| Route lookup | Destination prefix, longest match | Whether the packet is allowed out |
| Netfilter hook | Chain position, match conditions | Which table was selected |
Las marcas son un campo empaquetado, no una etiqueta propia
Android empaqueta varios hechos en el mismo valor de marca: qué red se seleccionó, si una aplicación eligió una red de forma explícita, si un socket está protegido frente a la VPN y bits relacionados con permisos. La cabecera fwmark de AOSP define ese diseño para el árbol actual, y el diseño es un detalle interno de la plataforma que cambia entre versiones.
Por eso escribir un valor de marca completo con iptables -j MARK --set-mark es peligroso en Android. No añade una etiqueta; sustituye la selección de red que el sistema ya hizo. El paquete pasa entonces a coincidir con reglas distintas, lo que puede parecer que la VPN empezó a funcionar o que una aplicación no relacionada perdió la conectividad, según qué bits se hayan sobrescrito.
Si tienes que tocar marcas, lee primero el valor actual y usa una máscara para que solo se modifiquen los bits que entiendes:
ip rule show
ip route show table all | head -40
ip route get 10.20.4.11Una marca de conexión es un objeto separado de una marca de paquete, y ninguna de las dos es una ruta. Restaurar la marca en los paquetes de respuesta es un paso distinto de seleccionar una tabla a la salida, por eso las correcciones unidireccionales producen conexiones que se abren y luego se cuelgan.
Quién es dueño de las reglas y las tablas
El servicio de red de Android, netd, crea las reglas y las tablas por red. El AOSP RouteController es donde se ensamblan esas reglas para VPN, redes físicas y rangos de uid, y su ciclo de vida está atado a eventos de red y no a un archivo de configuración.
Se siguen dos consecuencias. Primera, las prioridades y los números de tabla que encuentras en un teléfono son interioridades de la compilación, no una interfaz: números de aspecto idéntico en otra versión de Android pueden significar algo completamente distinto. Segunda, el estado se reconstruye cuando cambian las redes, así que una regla insertada hoy desde un shell root puede haber desaparecido tras el siguiente cambio de Wi-Fi.
Esa desaparición se reporta a menudo como que el sistema ignora una ruta. Lo que ocurrió en realidad es que la regla que seleccionaba la tabla ya no existe, y la ruta dentro de la tabla ahora es inalcanzable desde la perspectiva del paquete. Revisa la lista de reglas, no la de rutas, cuando una configuración que funcionaba deja de hacerlo tras una reconexión.
Las preguntas sobre el orden de los ganchos no tienen respuesta universal
La pregunta de si iptables se ejecuta antes del enrutamiento de la VPN no se puede responder sin nombrar la ruta del paquete. Un paquete generado localmente atraviesa el gancho output, donde un cambio de marca dispara una comprobación de reenrutamiento — una segunda búsqueda, no una edición retroactiva de la primera. Un paquete que llega de un cliente en tethering atraviesa la ruta prerouting y se reenvía en su lugar, y las cadenas que lo ven son otras.
Así, la misma regla puede ser efectiva para el tráfico de una aplicación e invisible para el tráfico en tethering, y un contador que se queda en cero te dice qué camino tomó el paquete, no si la regla es incorrecta. Usa contadores para establecer la ruta antes de cambiar cualquier condición de coincidencia.
Esta es también la etapa en la que un error de enrutamiento por política se vuelve difícil de ver. Enrutar hacia una tabla que existe pero no contiene el destino produce un red inalcanzable que parece un descarte del cortafuegos, mientras que un descarte del cortafuegos produce un tiempo de espera que parece un agujero negro de enrutamiento.
Diagnostica dentro del sistema o déjalo en paz
Para una revisión autorizada, establece cuatro hechos antes de tocar nada: el uid y el perfil de la aplicación, la red que Android seleccionó para ella, si la VPN incluye esa aplicación y si el problema existe para ambas familias de direcciones. Una exclusión por aplicación explica muchísimos informes de VPN que no funciona sin ningún fallo de enrutamiento.
Después lee las reglas, máscaras y tablas que están realmente en vigor, y mantén un cambio de red dentro de la ventana de observación. Si el comportamiento cambia a lo largo de una reconexión, estás viendo un ciclo de vida gestionado, no una ruta ausente.
Para requisitos ordinarios, usa los controles soportados: inclusión y exclusión por aplicación en la aplicación VPN, y la selección de red propia de la plataforma para todo lo que necesite una ruta concreta. Si una integración privilegiada tiene que cooperar de verdad con la maquinaria de enrutamiento, apunta a la implementación de la versión exacta de Android que soportas y mantén su ciclo de vida a través del componente que la posee. Vaciar cadenas de la plataforma o insertar una regla de alta prioridad convierte un diagnóstico en un segundo gestor de red, y el teléfono se comportará en consecuencia.