Comment détecter un tunnel VPN actif depuis le code sur n’importe quelle plateforme
Le tunnel existe-t-il, cette destination passe-t-elle par lui, ou l’extrémité distante répond-elle ? Ce sont trois vérifications différentes et trois signaux différents.
« Le VPN est-il actif ? » est en réalité trois questions dans une seule phrase. Laquelle votre code doit poser est la première décision, et c’est celle que la plupart des implémentations sautent. Un tunnel existe-t-il sur cet appareil, le trafic vers cette destination sort-il par lui, ou l’extrémité distante répond-elle avec l’identité que vous attendez. Choisissez la propriété, puis le signal qui la mesure, et dites enfin dans le journal lequel vous avez réellement mesuré.
Trois propriétés, trois signaux
Compressées sur une ligne chacune, les trois questions ont trois réponses différentes. Le tableau ci-dessous est la décision elle-même, pas son résumé.
| Property | Signal that answers it | What it still leaves open |
|---|---|---|
| Existence | The platform's own connection state: RAS on Windows, NetworkManager on D-Bus on Linux, scutil on macOS | Tunnels of a type the platform does not manage, which includes most third-party clients |
| Path | A route lookup for the one destination, or a scoped proxy or interface key that names the tunnel | Whether the far end is the peer you trust |
| Identity | An authenticated response from the far end, or a source-address policy applied on the server | Which local interface carried the packets |
Lisez la dernière ligne lentement. Un hôte privé qui répond prouve que quelque chose a répondu, pas que la réponse est passée par le tunnel, et il ne dit rien sur qui se trouve à l’autre bout. Si la propriété dont vous avez besoin est le chemin, mesurez le chemin.
Existence : l’état propre de la plateforme
Windows répond à cela pour les profils natifs via l’API Remote Access Service. RasEnumConnections énumère ce qui est connecté, RasGetConnectStatus rapporte l’état d’une entrée et RasGetLinkStatistics ajoute la vitesse, les compteurs d’octets et l’âge de la connexion. Les limites sont le point : OpenVPN, WireGuard et les clients d’éditeurs n’enregistrent jamais de connexion RAS, si bien qu’un tunnel sain de ce type affiche une liste vide et qu’un code naïf le signale comme coupé.
Les bureaux Linux exposent la même propriété via NetworkManager sur D-Bus, où PropertiesChanged sur l’objet de connexion VPN transforme la vérification en événement et où la propriété State rapporte quand le lien atteint l’état connecté. Depuis un shell, nmcli connection show --active lit les mêmes informations, et c’est ce que vous voulez pendant le débogage. macOS conserve cette liste dans le cadre System Configuration, avec scutil comme vue en ligne de commande. Toutes trois décrivent une connexion gérée par la plateforme, et toutes trois se taisent pour un tunnel qu’elle ne gère pas.
Chemin : où va réellement le paquet
La correspondance de noms est le raccourci auquel tout le monde recourt d’abord : énumérez les interfaces, testez la chaîne contre tun, tap, ppp ou ipsec, et prenez une correspondance pour une preuve. C’est une heuristique, et l’ensemble des interfaces peut sembler identique, que quelque chose le traverse ou non. Les anciennes versions d’iOS répondaient ainsi et les suivantes ont arrêté, parce que les interfaces visibles ne distinguaient plus les deux états.
Ce qui l’a remplacé là-bas, c’est le dictionnaire de proxy du système. Tant qu’un VPN est connecté, l’appel des réglages de proxy renvoie des clés limitées aux interfaces liées au tunnel, et sans rien de connecté le dictionnaire revient vide. C’est une affirmation plus faible qu’il n’y paraît, car elle enregistre la croyance du système qu’un tunnel existe, et non quelle destination l’utilise.
Android a sa propre version du piège : la diffusion vpn.connectivity atteint les récepteurs déclarés dans le manifeste sur certaines versions et les récepteurs enregistrés à l’exécution sur d’autres. Traitez-la comme un meilleur effort et gardez une sonde directe derrière elle.
Quand c’est la destination qui compte, interrogez la table de routage plutôt que la liste des adaptateurs. Les heuristiques de passerelle par défaut se cassent sur les machines à plusieurs réseaux et sur les tunnels qui installent leur propre passerelle.
Identité : sonder l’extrémité distante
Une boucle qui envoie une écho ICMP à l’extrémité distante toutes les quelques secondes est la vérification la moins chère de ce genre, et elle échoue dans une direction utile. Visez une adresse qui n’existe qu’à l’intérieur du réseau privé, car une adresse publique répond par n’importe quelle liaison montante qui fonctionne et ne prouve rien. Là où ICMP est filtré, une courte connexion TCP au port du service fait le même travail.
Une vérification côté serveur dispose d’exactement un signal : l’adresse source de la connexion. Tenir l’inventaire des plages est un travail d’entretien, et il ne peut pas séparer un tunnel de tout autre réseau qui utilise par hasard le même bloc.
Une politique grossière peut vivre avec cela. L’identité ne le peut pas, alors authentifiez le client au lieu de faire confiance à l’endroit d’où ses paquets semblent venir.
Journalisez la catégorie, pas le verdict
Gardez les catégories de panne séparées dans le journal : aucune interface du tout, interface présente mais destination injoignable, destination joignable mais authentification refusée. Ce sont trois propriétaires différents, et chacun ouvre une enquête différente.
Les réduire à un seul « VPN en panne » envoie le rapport à une équipe qui ne peut pas le réparer. La catégorie est la sortie utile ; le verdict est ce qui la rend fausse.