Demandez à une app iOS si le téléphone est sur un VPN : la réponse honnête est qu'elle ne peut pas le savoir au sens où vous l'entendez. Le SDK n'expose aucun indicateur « l'appareil est dans un tunnel », et les interfaces privées qui pourraient s'en approcher sont fermées aux apps publiées. Vous pouvez observer la configuration de votre propre app, l'état qui y est attaché et un ou deux indices indirects venus de la pile réseau. Chacun répond à une question différente, et la plupart des vérifications cassées viennent de ce qu'on prend l'une d'elles pour la réponse entière.

Le mythe de l'indicateur VPN unique

On croit qu'il existe quelque part dans le SDK une propriété qui indique si l'appareil est dans un tunnel, comme un indicateur d'accessibilité indique si un hôte répond. Une telle propriété publique n'existe pas. Et même si elle existait, « un tunnel existe » et « mon trafic l'utilise » sont deux affirmations différentes, et seule la seconde compte pour la plupart des apps.

C'est précisément cet écart qui fait que les bibliothèques vantant un détecteur de VPN en une ligne lisent généralement quelque chose de fragile, comme un nom d'interface ou une clé de proxy, et le présentent comme un verdict.

Chargez les préférences avant de faire confiance à un nil

L'instance partagée du gestionnaire existe dès que vous la demandez, mais sa propriété de protocole reste nil jusqu'à ce que le rappel de chargement soit terminé. Un protocole nil signifie donc « pas encore chargé » au moins aussi souvent que « non installé ». Faites la lecture à l'intérieur du bloc de completion, et décidez seulement ensuite : un objet de protocole qui existe, avec l'indicateur d'activation allumé, voilà à quoi ressemble « installé ».

Un second signal se trouve sur l'objet de connexion : l'état invalide, que le système signale quand cette app n'a aucune configuration installée. Un état invalide accompagné d'un protocole nil après un chargement terminé est une absence réelle, pas une course de timing.

Les changements de connexion arrivent sous forme de notifications

Les gestionnaires passés à load et save rapportent ce qui est arrivé à la configuration, pas ce que fait le tunnel. Attendre que l'un d'eux se déclenche à la connexion est une course qui ne se résout jamais. Surveillez plutôt la notification de changement d'état et lisez la valeur courante de l'objet de connexion quand elle arrive.

Une fois une configuration installée, l'état de connexion parcourt une courte séquence : déconnecté, connexion, connecté, réaffirmation, déconnexion. « Connecté » décrit le tunnel et non le serveur derrière lui, ce n'est donc pas la preuve que le trafic circule. On-demand peut aussi monter un tunnel alors que l'app est suspendue, et la notification arrive alors avant que vous ayez quoi que ce soit à mettre à jour.

L'instantané de proxy limité est un indice, pas un verdict

CFNetwork peut fournir à l'app les réglages de proxy actuels du système, et dans ce résultat se trouve un dictionnaire à portée limitée, indexé par nom d'interface. Voir un nom qui commence par tun, utun, ppp, ipsec ou tap est un indice qu'un tunnel est présent. Cela reste un instantané de ce que cette app peut voir, pas une affirmation sur l'endroit où voyagent les paquets.

Les fournisseurs ne s'accordent pas sur les noms, donc un préfixe absent ne prouve rien, et une interface présente peut exister sans porter de trafic. L'accessibilité est plus faible encore : une requête réussie vers une adresse privée montre que le chemin a fonctionné pour cette requête à cet instant, pas qu'un VPN est installé.

Le simulateur emprunte le Mac, et les autres apps restent invisibles

Le simulateur n'a pas de pile réseau propre ; chaque connexion qu'il établit est celle du Mac. Un VPN exécuté sur le Mac hôte est donc déjà en vigueur pour l'app simulée, et les réglages du simulateur lui-même n'affichent rien. Si le tunnel est monté après le démarrage du simulateur, le redémarrer est généralement plus rapide que déboguer l'app. Un hôte sur un port non standard a besoin de ce port dans l'URL, ou d'une redirection locale comme socat TCP-LISTEN:12345,fork TCP:host:12345.

Les API publiques n'énuméreront pas les profils VPN qui appartiennent à d'autres apps ou à des profils de configuration. Pour une app connue, la sonde de schéma d'URL via canOpenURL est l'astuce portable, et depuis iOS 9 le schéma interrogé doit être déclaré dans votre Info.plist ; omettez-le et l'appel renvoie false. OpenVPN Connect répond sur openvpn://, ce qui en fait un bon exemple et un mauvais détecteur général.

Combinez trois observations et dites ce qu'elles signifient

Empilez trois résultats en pratique : une configuration chargée et activée, un état de connexion qui n'est pas invalide, et une requête vers une adresse accessible uniquement par le tunnel. Chacun trompe à lui seul ; ensemble, ils énoncent ce que l'app peut savoir plutôt que ce que l'utilisateur suppose.

Écrivez le résultat sous forme de trois lignes dans vos diagnostics, pas d'un seul booléen. Quand un utilisateur dit que le VPN est désactivé alors que votre app n'est pas d'accord, les trois lignes montrent quelle observation a divergé, et c'est la différence entre un ticket de support sur lequel vous pouvez agir et un qui se termine par « chez moi ça marche ».

Articles similaires