Comment les règles de domaine d’Apple VPN On Demand déclenchent un tunnel
Une règle de domaine décide seulement quand le tunnel s’ouvre. Comment fonctionne la sonde DNS connect-if-needed, pourquoi les routes choisissent encore le trafic et comment tester le profil.
Le tunnel s’ouvre lorsque vous demandez un nom interne et reste fermé lorsque l’application suivante en a tout autant besoin. Ce n’est pas un bug de l’application ; c’est la forme d’une règle de domaine. La configuration on-demand d’Apple décrit les conditions d’établissement d’une connexion, et la forme domaine de ces conditions interroge le résolveur du système avant qu’un seul paquet ne bouge. Deux questions sont constamment confondues : quand le tunnel doit monter, et ce que le tunnel transporte une fois qu’il existe. La première est un déclencheur, la seconde une politique de routes et de résolveur, et un profil règle généralement les deux dans la même payload, ce qui explique qu’une règle de domaine correcte puisse quand même vous laisser sur le mauvais réseau.
Le déclencheur et la sélection du trafic sont sur des couches différentes
Une règle on-demand vit dans le dictionnaire on-demand d’une payload VPN : une liste ordonnée de règles, chacune avec une action et un ensemble de conditions de correspondance. Le système les évalue lorsque la connectivité change ou lorsque quelque chose tente d’atteindre le réseau, et l’action décide si le tunnel est monté, évalué, déconnecté ou ignoré. Tout cela se passe dans la couche réseau de la plateforme, avant que votre application n’ait une socket.
Ce qui suit est un groupe distinct de clés : les réglages IPv4 et IPv6 du tunnel, ses routes incluses et exclues, les adresses de ses serveurs DNS et, sur iOS et iPadOS, le mappage par application qui décide quelles applications peuvent utiliser le tunnel. Un profil peut associer un déclencheur large à une route étroite, ou un déclencheur étroit à une route par défaut. Ne lisez qu’une moitié et l’autre ressemblera à un dysfonctionnement.
Je garde un profil de laboratoire qui se connecte dès que quelque chose sous un domaine interne est demandé, mais ne route qu’un /16 dans le tunnel. Il fait exactement ce que dit sa payload, et c’est aussi le genre de profil qui génère des tickets : les gens supposent qu’un tunnel connecté signifie que leur trafic est dedans.
Ce qu’une règle de domaine demande vraiment au résolveur
La forme domaine de la règle, souvent appelée connect-if-needed, n’inspecte pas les payloads des paquets et ne surveille pas les URL. Lorsqu’un nom est résolu, le système le compare aux domaines de la règle et, en cas de correspondance, demande si ce nom peut être résolu via les serveurs DNS fournis par le tunnel. Si le résolveur du tunnel répond, le nom compte comme interne et la connexion démarre. Si le résolveur local répond à la place, le nom est traité comme externe et aucun tunnel n’apparaît. La vue d’ensemble du déploiement d’Apple décrit cela comme une détection réseau suivie d’une évaluation de connexion.
Deux conséquences en découlent. Le profil doit nommer des serveurs DNS à l’intérieur du tunnel ; une règle de domaine sans résolveur de tunnel n’a rien à comparer, donc l’évaluation ne peut pas produire la correspondance attendue. Et la requête doit atteindre le résolveur du système. Une application ou un navigateur qui exécute son propre DNS chiffré, une extension qui répond localement ou une connexion à une adresse littérale ne produisent jamais la résolution de nom que la règle attendait. L’un des après-midi les plus longs que j’aie passés s’est terminé quand j’ai découvert que le client devant le tunnel utilisait DNS over HTTPS.
La mise en cache supprime aussi le déclencheur. Un nom déjà en cache peut être résolu sans la sonde qui aurait lancé le tunnel, si bien qu’une règle qui fonctionnait hier échoue après un redémarrage, ou après que le tunnel est resté monté un moment. Sur macOS, sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder réinitialise l’état ; sur iOS, activer puis désactiver le mode avion ou redémarrer l’appareil vous donne une table rase comparable.
Portée de correspondance : noms, applications et réseaux
La correspondance de domaine est un type parmi d’autres. Une règle peut aussi correspondre au type d’interface (Wi-Fi, cellulaire, Ethernet) et à un SSID précis, et les entrées par application ou par domaine Safari lient un tunnel à un flux de travail. Ce lien explique l’expérience étrange où une seule application se comporte différemment de tout le reste : les autres applications sont hors de la portée du tunnel, elles continuent donc d’utiliser le chemin local même lorsque l’icône du tunnel indique connecté.
L’ordre compte plus qu’on ne l’attend. Les règles sont évaluées dans l’ordre et la première qui correspond fournit l’action, donc une règle large de connexion-sur-n’importe-quel-Wi-Fi placée au-dessus d’une règle de domaine étroite gagnera silencieusement et rendra la règle de domaine intestable. Avant de réécrire la liste des domaines, confirmez qu’aucune règle antérieure n’a déjà correspondu.
C’est aussi pourquoi always-on n’est pas simplement une règle on-demand plus stricte. L’application d’always-on est un mode de déploiement distinct avec ses propres exigences de supervision et de gestion ; il maintient un tunnel ouvert au lieu de réagir à un nom. Si ce qu’il vous faut est un tunnel qui ne tombe jamais, une règle de domaine est le mauvais outil.
Modes de défaillance qui imitent une règle cassée
La plupart des signalements de règle de domaine qui ne fonctionne pas tombent dans l’un de cinq endroits, et seul le dernier est le texte de la règle.
| What you see | Layer | First check |
|---|---|---|
| Tunnel comes up, internal site still fails | route or resolver after connect | netstat -rn, scutil --dns |
| Tunnel never comes up for that name | trigger path | fresh lookup, cache flush, private DNS |
| Tunnel comes up for every app | scope, or an earlier rule | rule order, per-app mapping |
| Tunnel drops and will not return on the same Wi-Fi | interface or SSID match, admission | captive portal, SSID string, auth prompt |
| Tunnel returns after you disconnect it | profile ownership | profiles show |
Les portails captifs méritent leur propre ligne, car le Wi-Fi d’hôtel et d’aéroport intercepte précisément la requête dont dépend la règle. Tant que le portail n’admet pas l’appareil, le serveur DNS du tunnel est injoignable, la sonde échoue et la panne ressemble à un domaine mal orthographié. L’authentification est l’autre cas silencieux : la règle peut se déclencher, le tunnel peut commencer à se connecter et la connexion meurt sur un certificat expiré ou sur une invite qui apparaît sur un autre écran.
IPv6 crée une variante facile à mal diagnostiquer. Un nom ayant les deux familles d’adresses peut être résolu d’abord depuis un enregistrement AAAA, alors que la liste de routes du tunnel ne porte que IPv4. Un navigateur réussit, un autre échoue, et la liste des domaines est parfaitement innocente.
Testez avec une vraie requête, dans cet ordre
Lisez la politique avant de deviner. Sur macOS, sudo profiles show -type configuration imprime les profils installés, y compris la payload VPN, scutil --nc list affiche l’état du service et scutil --nc show <service> imprime le dictionnaire on-demand utilisé par le système. Sur un iPhone ou un iPad supervisé, la même payload arrive de la console de gestion ou d’un rapport MDM. Les journaux réseau sont disponibles avec log stream --predicate 'subsystem == "com.apple.networkextension"' sur macOS, et via la console de l’appareil lorsque le téléphone est connecté.
Testez ensuite avec un nom d’hôte qui n’a pas été interrogé plus tôt dans la session. Choisissez un nom dans la zone DNS du tunnel dont vous savez qu’il se résout en interne, demandez-le une fois et regardez si le tunnel apparaît. Exécutez la même requête deux fois : la seconde tentative exerce le chemin du cache, et la différence entre les deux vous dit si le déclencheur est la résolution ou le routage.
Une fois le tunnel monté, vérifiez les deux couches séparément. netstat -rn -f inet et netstat -rn -f inet6 montrent où pointe chaque préfixe, scutil --dns montre l’ordre des résolveurs et quelle interface possède chaque résolveur, et nettop -m route montre quelle interface a transporté les octets. Si le tunnel est monté et le résolveur correct mais que la ressource échoue encore, arrêtez de modifier la règle ; vérifiez l’autorisation côté serveur et la route de retour.
Quand la règle appartient à quelqu’un d’autre
Si le tunnel réapparaît après que vous l’avez déconnecté, la règle appartient généralement à un profil plutôt qu’à une application : une configuration poussée par MDM, un profil personnel oublié ou un profil installé par un autre client. sudo profiles show -type configuration plus une recherche des clés on-demand permettra de la cerner, et le chemin de suppression est le profil, pas l’interrupteur de la barre de menus. Supprimer l’entrée de service ou l’application laisse la règle derrière, et l’installation suivante en hérite de nouveau.
Un seul test tranche la propriété : déconnectez, attendez, redemandez le nom interne. Si le tunnel revient, le déclencheur fonctionne comme prévu et la question ouverte est de savoir qui le gère et si cette portée est celle que vous voulez.
Avant de signaler cela comme un bug, passez par les mêmes cinq vérifications : adresses de résolveur du tunnel présentes dans la payload, nom qui n’était pas en cache, aucune règle antérieure déjà correspondante, chemin AAAA couvert par la liste de routes, et application dans la portée du tunnel. Quand les cinq tiennent, la règle fait son travail et la faute est plus loin sur le chemin.