HIOXBuscar/

El túnel de desarrollador del iPhone, desde Linux y sin Xcode

Desde iOS 17 las herramientas de desarrollador del iPhone sólo se alcanzan por un túnel cifrado. Cómo lo armamos en un servidor Linux, también por Wi-Fi, y lo que aprendimos usándolo para diagnosticar una app que se colgaba.

Un iPhone trae adentro las mismas herramientas que usa Apple para que los programadores prueben sus apps: ver en vivo cuánta memoria y cuánta CPU gasta cada proceso, sacarle una «foto» a lo que está ejecutando, capturar la pantalla, levantarle a una app el límite de memoria. Hasta iOS 16 se llegaba a ellas por el mismo canal por el que se hace una copia de seguridad. Desde iOS 17, sólo se llega por un túnel cifrado, y la herramienta oficial para abrirlo es Xcode, que sólo corre en Mac.

Necesitábamos esas herramientas en un servidor Linux, para diagnosticar una app que se colgaba en un iPhone. Esta nota cuenta cómo quedó armado el túnel, también por Wi-Fi, y lo que aprendimos usándolo. No hay datos de ningún teléfono ni de nadie: es el mecanismo, que sirve igual para cualquier iPhone.

El problema: Apple cambió el camino en iOS 17

Hasta iOS 16 la computadora hablaba con el iPhone por TCP, a través de un servicio llamado usbmuxd, con TLS para asegurarse de que sólo conversaran equipos de confianza. Es el camino que usan desde siempre las herramientas libres de libimobiledevice para copias de seguridad, fotos y registros.

En iOS 17 Apple reescribió la parte de desarrollador. Los servicios se publican con un protocolo nuevo, RemoteXPC, y para alcanzarlos hay que abrir antes un túnel cifrado hacia el teléfono: una especie de VPN entre la computadora y el iPhone. Ese túnel se monta sobre una interfaz de red virtual, y crear una interfaz así es algo que en Linux sólo puede hacer un proceso con permisos de administrador. La documentación técnica de pymobiledevice3 sobre RemoteXPC explica el cambio en detalle.

Dos tropiezos aparecieron antes de llegar al túnel, y vale la pena saberlos porque el síntoma no dice la causa:

  • El emparejamiento fallaba. La versión de libimobiledevice que trae empaquetada Ubuntu 24.04 no sabe emparejar un iPhone con iOS 17 o posterior. Hubo que compilarla desde el código fuente.
  • «lockdown error -8» al conectar por cable. El kernel de Linux trae un controlador, ipheth, que toma el iPhone como placa de red para compartir internet y compite con usbmuxd por el mismo dispositivo. Deshabilitándolo, el error desaparece.

La solución: un túnel que se abre solo

La pieza central es pymobiledevice3, una implementación libre, en Python, de los protocolos del iPhone. Entre otras cosas trae tunneld, que hace en Linux el papel que en la Mac cumple el propio sistema: queda corriendo con privilegios, busca los iPhones conectados por cable y por Wi-Fi, y abre el túnel hacia cada uno sin que haya que pedírselo.

  1. Modo de desarrollador en el iPhone. Viene oculto: con el teléfono por cable, pymobiledevice3 amfi reveal-developer-mode hace aparecer la opción en Ajustes › Privacidad y seguridad › Modo de desarrollador. Se activa ahí, el teléfono se reinicia y pide confirmar. Apple lo explica en su página Enabling Developer Mode on a device.
  2. El túnel. sudo pymobiledevice3 remote tunneld lo deja levantado. Es lo único que necesita administrador.
  3. La imagen de desarrollador. Las herramientas no vienen instaladas en el teléfono: se montan como un disco aparte, con pymobiledevice3 mounter auto-mount.
  4. Los comandos. Desde ahí, cualquier comando de desarrollador se manda como usuario común agregándole --tunnel, y viaja por el túnel que ya está abierto.

Por Wi-Fi, sin cable

Para que el teléfono no tenga que estar enchufado al servidor sumamos netmuxd, un programa libre que descubre los iPhones de la red local por mDNS (los anuncios _apple-mobdev2._tcp de los iPhones que tienen activada la sincronización por Wi-Fi) y se los presenta a las demás herramientas como si estuvieran conectados por USB. Basta con decirle a tunneld dónde escucha netmuxd (--usbmux-address, con la dirección y el puerto locales) para que abra el túnel también hacia los teléfonos que están en la red.

El emparejamiento, eso sí, se hace una vez por cable: el iPhone tiene que «confiar» en la computadora antes de dejarse ver por Wi-Fi.

Qué se puede hacer una vez adentro

Para quéComando (con --tunnel)
CPU, memoria y disco de un proceso, en vivodeveloper dvt sysmon process single -f name=<app>
Encontrar el número de proceso de una appdeveloper dvt process-id-for-bundle-id <identificador>
Levantarle a un proceso el límite de memoriadeveloper dvt memlimitoff <pid>
«Foto» de lo que está ejecutando cada hilodeveloper dvt core-profile-session stackshot
Captura de pantalladeveloper dvt screenshot

Sin túnel también quedan a mano dos fuentes que ayudan mucho: los reportes de fallas del teléfono (con libimobiledevice, idevicecrashreport; la opción -k los copia sin borrarlos del iPhone) y el registro del sistema en vivo (idevicesyslog). Los reportes son archivos .ips en formato JSON, y la primera línea dice qué app y qué versión.

Lo que aprendimos usándolo

Lo usamos para un caso concreto: una app que se cerraba sola al poco tiempo de abrirla. La historia completa, con la causa y el arreglo, está en ¿Se congela el WhatsApp cuando lo abrís?. Acá van las lecciones del túnel en sí, que sirven para cualquier app.

  • El motivo del cierre está en el reporte. El código 0x8BADF00D quiere decir que el vigilante del sistema mató la app porque su hilo principal no respondió a tiempo; un reporte cpu_resource_fatal, que la mató por consumo de CPU; un cierre de jetsam, que pasó el límite de memoria que iOS le da a cada app. Saber cuál es cambia la pregunta: de «qué está roto» a «qué está haciendo la app para necesitar tanto».
  • Levantar el límite de memoria vale para ese proceso y nada más. Si la app se cierra y vuelve a abrir, es otro proceso con otro número y el límite vuelve. Lo resolvimos con un pequeño vigilante que se lo vuelve a sacar a cada proceso nuevo mientras dura el diagnóstico.
  • La imagen de desarrollador se desmonta en cada reinicio del teléfono. Hay que volver a montarla, y conviene que lo haga el mismo script que arranca el trabajo. Y el Modo de desarrollador se apaga si el teléfono se restaura.
  • Una app sin símbolos miente en sus reportes. Las apps de terceros se publican sin los nombres de sus funciones, y lo que muestran los reportes es el nombre más cercano que encontró el sistema, no el verdadero. Para comparar dos cuelgues hay que mirar la posición dentro del binario (imageOffset), no el nombre.
  • Las «fotos» se pueden traducir con los propios reportes. Las librerías de Apple viven en un bloque compartido del sistema. Con la dirección base de ese bloque y la lista de imágenes cargadas que trae cualquier reporte .ips de la misma versión de iOS, una dirección cruda de un stackshot se convierte en la librería y la función de Apple que estaba corriendo.
  • Mirar por Wi-Fi le gasta batería al teléfono. Leer el registro del sistema sin parar a través de la red no es gratis para el iPhone. El monitoreo completo quedó para cuando está por cable o cuando hay un problema activo; el resto del tiempo, una mirada breve de vez en cuando.
  • Los reportes no sirven como sensor permanente. Después del reinicio que pide el Modo de desarrollador, los reportes nuevos no aparecieron. Para saber si algo está pasando ahora, el dato bueno es el de sysmon, no la carpeta de reportes.
  • Enchufar el teléfono genera ruido propio. En el escritorio de Linux, gvfs monta el iPhone solo apenas se conecta, y eso llena el registro con actividad de archivos que no tiene nada que ver con la app que se está mirando.
  • Cuidado con pkill -f. Si el patrón que se busca aparece en la propia línea de comando, el comando se mata a sí mismo o a la terminal que lo lanzó. Mejor el número de proceso, o un patrón anclado al principio.

Preguntas frecuentes

¿Hace falta una Mac para usar las herramientas de desarrollador del iPhone?

No. Con pymobiledevice3, que es software libre, se arma el mismo túnel que usa Xcode desde una computadora con Linux. Lo que sí hace falta es activar el Modo de desarrollador en el iPhone y tener permisos de administrador en la computadora.

¿Por qué el túnel necesita permisos de administrador?

Porque crea una interfaz de red virtual en la computadora, y eso en Linux sólo lo puede hacer un proceso con privilegios. El resto de los comandos, los que miden o actúan sobre el teléfono, corren como usuario común a través de ese túnel.

¿Funciona por Wi-Fi o sólo por cable?

Por las dos vías. Por Wi-Fi hace falta que el iPhone ya esté emparejado con la computadora y un programa que lo descubra en la red y lo presente como si estuviera enchufado; en nuestro caso, netmuxd.

Las herramientas de desarrollador sirven para mirar y diagnosticar. Levantarle el límite de memoria a una app es un recurso de diagnóstico, no un ajuste para dejar puesto: cuando termina el trabajo, el Modo de desarrollador se desactiva desde el mismo menú.