Cómo llamar a una API interna desde una aplicación de iPhone por VPN
Clasifique la solicitud que falla por su código NSURLError antes de tocar el túnel y, después, repare exactamente la capa que se rompió.
La API responde en Safari en el mismo teléfono, mientras que la solicitud de la aplicación agota el tiempo. Esa brecha normalmente no es el túnel: una aplicación que llama a un servicio interno hace una solicitud HTTPS normal, y la VPN que ya tiene el dispositivo solo decide si esa solicitud tiene ruta. Escribir un segundo túnel dentro de la aplicación es una decisión de producto, no una reparación para un tiempo de espera. Lo que sigue clasifica el fallo según dónde ocurre, usando la superficie de errores que la aplicación ya tiene.
Empiece por el error, no por el túnel
URLSession informa los fallos de transporte como NSError valores en NSURLErrorDomain, y el código es la evidencia más barata de la que dispone. Antes de cambiar cualquier configuración, registre ese código junto con el nombre de host que falla y el tiempo transcurrido de la tarea. Un tiempo de espera, un fallo de nombre y un fallo de confianza se ven igual en pantalla y exigen tres reparaciones distintas. Clasifique primero y después lea la sección de esa clase.
Las métricas de la tarea responden a la siguiente pregunta, si alguna vez se estableció una conexión, lo que separa una solicitud que nunca tuvo ruta de una a la que el servidor tardó demasiado en responder. Nada de esto necesita cambiar el túnel; necesita que los diagnósticos de la propia solicitud se impriman en algún lugar que pueda leer.
La resolución de nombres falla antes que cualquier otra cosa
Un nombre de oficina corto como api.corp.example suele depender de un dominio de búsqueda que el teléfono no lleva, así que la aplicación resuelve un nombre que solo existe dentro del edificio. NSURLErrorCannotFindHost es la firma. El nombre de host completo debe resolverse mediante el resolver que instale la VPN, y la aplicación debería pedir la forma totalmente cualificada siempre que el dominio de búsqueda no esté garantizado. Cambiar el nombre por una dirección y desactivar las comprobaciones de certificados mueve el fallo en lugar de repararlo.
Un registro DNS privado y un certificado emitido para ese nombre exacto son la pareja admitida. Todo lo demás es un rodeo que llega a los usuarios.
Un tiempo de espera es una cuestión de ruta, no de nombre
NSURLErrorTimedOut significa que el nombre se resolvió y nada respondió, lo que apunta a la ruta, la política de paquetes o el servicio. Cuando el túnel se asigna por aplicación, otra aplicación que llega al mismo servidor no dice nada sobre su compilación, porque ese mapeo no se comparte. Compruebe que el paquete que ejecuta esté dentro de esa asignación y luego compruebe que la ruta del servicio esté permitida para él. Una compilación de desarrollo instalada fuera de la asignación puede quedar completamente fuera del túnel y parecer una API rota.
Una comparación en el navegador muestra que alguna aplicación del dispositivo tiene ruta. Nunca demuestra que la suya la tenga, y por eso las dos pruebas deben ejecutarse por separado.
Los fallos de confianza tienen que ver con el nombre del certificado
NSURLErrorServerCertificateUntrusted junto con el error TLS que hay debajo significa que la cadena o la comprobación de identidad falló. Una CA interna debe ser de confianza en el dispositivo, y un certificado emitido para otro nombre de host sigue estando mal después de cualquier reconfiguración de red. La guía de App Transport Security de Apple sigue aplicándose a estas conexiones que cargan URL, y un túnel alrededor de un servicio HTTP simple no hace que ese servicio sea seguro de extremo a extremo.
Corrija la identidad o el ancla de confianza y mantenga la lista de excepciones vacía. Una excepción general para carga arbitraria oculta el fallo durante el desarrollo y lo deja en su sitio para cada usuario después.
Un rechazo HTTP pertenece a la aplicación, no a la red
Un 401 o 403 tras un handshake completado significa que la solicitud llegó y el servicio la rechazó, así que la pregunta restante es una cuenta, una audiencia de token, un alcance o una clave. Registre el código de estado y el nombre de host, nunca el token de portador ni el cuerpo de la respuesta. En ese punto el túnel hace su trabajo y más cambios de red solo retrasan la reparación real.
La tabla es la clasificación que conviene tener junto al terminal: una fila por cada fallo que la aplicación puede informar de verdad. Imprima el código antes de leerlo, porque la fila que elija decide qué sección trabaja.
| Where it fails | What the app sees | First check |
|---|---|---|
| name resolution | NSURLErrorCannotFindHost (-1003) | resolve the fully qualified name from the device itself |
| no path, or no answer | NSURLErrorTimedOut (-1001) | is this bundle inside the per-app mapping, and is the service path allowed |
| TLS trust | NSURLErrorServerCertificateUntrusted (-1202) | does the certificate name match the host, and is the internal CA trusted |
| service refusal | HTTP 401 or 403 after a completed handshake | account, token audience, scope or key |
Cada fila es más barata de probar que la de abajo, y cada una descarta una capa distinta de la misma solicitud. Baje por la tabla hasta que una fila coincida y luego deje de cambiar la red.