Ubuntu 24.04 : le VPN casse le DNS — réparer les résolveurs et les routes dans le bon ordre (cas #52)

Cet article vous a aidé ?

Vous vous connectez au VPN et tout semble « opérationnel ». Le tunnel est vert. L’icône sourit.
Et puis : rien ne se résout. Les noms internes échouent, les DNS publics peuvent aussi échouer, et votre navigateur fait
l’équivalent corporate de regarder une porte fermée.

C’est le type de panne qui pousse les gens intelligents à faire des choses stupides — comme éditer au hasard /etc/resolv.conf
à 2h du matin. Ne le faites pas. Sur Ubuntu 24.04, le comportement du résolveur est un système en couches (systemd-resolved + NetworkManager + DNS par interface),
et les VPN sont agressifs sur les routes. Corriger le DNS sans corriger les routes, c’est comme remplacer les piles du détecteur de fumée pendant que la cuisine est en feu.

Le modèle mental : ce qui a changé dans Ubuntu 24.04 et pourquoi les VPN le déclenchent

Ubuntu 24.04 « utilise » toujours /etc/resolv.conf, mais de la même manière qu’un magicien utilise un jeu de cartes :
ce n’est pas là où les vraies décisions se prennent. La plupart des installations desktop et beaucoup de serveurs exécutent
systemd-resolved avec un résolveur stub et une configuration DNS par interface.
NetworkManager est généralement le moteur de politique qui alimente systemd-resolved en DNS et domaines.
Les clients VPN (OpenVPN, WireGuard via NetworkManager, agents propriétaires) modifient souvent :

  • les routes (route par défaut, routes de politique, routes split-tunnel)
  • les serveurs DNS (pousser des résolveurs internes, forcer « DNS VPN uniquement »)
  • les domaines de recherche / split DNS (router uniquement corp.example via le DNS du VPN)
  • les règles de pare-feu (certains clients implémentent leur propre kill-switch)

Le piège : le DNS est du trafic réseau. Si votre table de routage envoie les paquets DNS au mauvais endroit,
« réparer le DNS » au niveau du résolveur ne sert à rien. De même, une route correcte avec un résolveur incorrect
fait croire que le VPN est hors ligne alors qu’il ne l’est pas. L’ordre compte donc :
d’abord le routage, puis la sélection du résolveur, ensuite le comportement du split DNS, puis les caches.

Voici le flux de base sur un système Ubuntu 24.04 typique :

  1. glibc appelle la bibliothèque de résolution (souvent via les règles de nsswitch.conf)
  2. les requêtes vont vers le nameserver listé dans /etc/resolv.conf (souvent 127.0.0.53)
  3. systemd-resolved sélectionne les serveurs DNS par lien, par domaine, avec des règles de routage
  4. les paquets sont envoyés en utilisant la table de routage du noyau (ou du routage de politique) via l’interface choisie

Si un VPN « aide » en installant une route par défaut via le tunnel mais oublie de permettre au DNS corporate
d’être joignable par ce tunnel — ou pire, installe des serveurs DNS qui ne sont joignables que sur le LAN local —
vous obtenez le symptôme classique : les IP fonctionnent, les noms non. Ou « les noms publics fonctionnent, les noms internes non ».

Une citation à garder sur un post‑it :
« L’espoir n’est pas une stratégie. » — Gordon R. Dickson. Ce n’est pas une citation SRE, mais elle s’applique parfaitement au débogage DNS.
(Si vous ne pouvez pas le vérifier avec des commandes, c’est de l’espoir.)

Blague n°1 : le DNS est le seul système où « ça marche sur ma machine » peut littéralement signifier « ça marche sur mon résolveur ».

Faits et contexte intéressants (rapide, concret, utile)

  • systemd-resolved est le résolveur par défaut sur Ubuntu depuis des années, mais l’écosystème suppose encore que /etc/resolv.conf est la source d’autorité, ce qui crée des bugs fantômes quand il n’est qu’un stub.
  • Le split DNS est plus ancien que la plupart des ingénieurs ne le pensent : les entreprises faisaient déjà « zones internes sur résolveurs internes » bien avant que les apps VPN modernes n’en fassent une fonctionnalité.
  • NetworkManager peut définir le DNS par connexion et par VPN, et il peut aussi décider si le DNS du VPN remplace ou complète le DNS existant.
  • Les options « push » d’OpenVPN peuvent livrer serveurs DNS et routes aux clients ; si la config du serveur est négligente, chaque client hérite de cette négligence.
  • WireGuard n’a pas de plan de contrôle natif pour le DNS ; le DNS est typiquement configuré par le client (wg-quick, NetworkManager ou scripts), ce qui fait que « le DNS a cassé » signifie souvent « le client n’a pas appliqué le DNS ».
  • 127.0.0.53 n’est pas « le serveur DNS » ; c’est un écouteur local stub pour systemd-resolved. Si vous pointez les applications ailleurs, vous pouvez contourner la logique du split DNS par erreur.
  • Le DNS sur TCP existe pour une raison : grosses réponses, DNSSEC, et certaines combinaisons VPN/pare-feu qui mal gèrent la fragmentation UDP.
  • Les domaines de recherche peuvent être dangereux par accident : ajouter un suffixe de recherche comme corp.example peut faire que des noms courts se résolvent différemment et embrouiller les logs et outils.

Playbook de diagnostic rapide (quoi vérifier en premier/deuxième/troisième)

Première étape : prouver si le problème est de routage ou de résolution

  1. Pouvez-vous atteindre une IP connue via le VPN ?
    Si vous pouvez pinguer ou curl une IP interne mais que les noms internes échouent, vous êtes en zone résolveur.
    Si vous ne pouvez atteindre ni les IP internes, commencez par les routes/pare-feu.
  2. Pouvez-vous atteindre l’IP du ou des serveurs DNS configurés ?
    Si le VPN a poussé 10.0.0.53 mais que vous ne pouvez pas y router, le DNS est condamné quelle que soit la justesse des configurations.

Deuxième étape : inspecter la vue de systemd-resolved, pas vos suppositions

  1. Utilisez resolvectl status pour voir les serveurs DNS et domaines par lien.
    Si votre lien VPN a du DNS mais que la route par défaut pointe encore vers le Wi‑Fi, vous avez peut‑être du split tunnel sans split DNS (ou l’inverse).
  2. Vérifiez si /etc/resolv.conf est un stub pointant vers 127.0.0.53 ou autre chose.
    S’il a été écrasé par un client VPN, vous pouvez contourner la logique par lien de systemd-resolved.

Troisième étape : valider la résolution sous plusieurs angles

  1. Testez avec resolvectl query (passe par systemd-resolved).
  2. Testez avec dig @SERVER (contourne la politique locale ; utile pour vérifier la joignabilité et la justesse du serveur).
  3. Si les résultats diffèrent, vous avez un décalage politique/config plutôt qu’une panne DNS pure.

Quatrième étape : seulement ensuite touchez à la configuration

Ne commencez pas à « réparer » en codant en dur 8.8.8.8 ou en supprimant resolved. C’est ainsi que vous obtenez un DNS public fonctionnel
tandis que les zones internes échouent silencieusement pendant des semaines. Corrigez le routage et la politique du résolveur pour que la machine se comporte correctement avec et sans VPN.

Tâches pratiques : commandes, sorties attendues et décisions

Voici les vérifications que j’exécute réellement sur Ubuntu 24.04 quand un VPN « se connecte » mais que le DNS a l’air décalé.
Chaque tâche inclut : la commande, ce que la sortie signifie généralement, et la décision à prendre.
Faites-les dans l’ordre à moins que vous n’aimiez le débogage chaotique.

Tâche 1 : Confirmer que l’interface VPN existe et est UP

cr0x@server:~$ ip -brief link
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp0s31f6        UP             3c:52:82:ab:cd:ef <BROADCAST,MULTICAST,UP,LOWER_UP>
wg0              UNKNOWN        9a:bc:de:f0:12:34 <POINTOPOINT,NOARP,UP,LOWER_UP>

Signification : wg0 (ou tun0) existe et est UP. S’il manque, vous n’avez pas un problème de DNS ; vous avez un problème VPN.
Décision : Si l’interface n’est pas présente/UP, corrigez d’abord la connectivité/authentification VPN. Arrêtez ici.

Tâche 2 : Inspecter les adresses sur l’interface VPN

cr0x@server:~$ ip addr show dev wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 10.44.0.12/32 scope global wg0
       valid_lft forever preferred_lft forever

Signification : Vous avez une adresse. Un /32 sur WireGuard est courant. Pour OpenVPN, vous pouvez voir /24 ou /20.
Décision : Pas d’adresse signifie que le tunnel n’est pas correctement configuré. Le DNS ne peut pas fonctionner si le VPN n’a pas assigné d’identité réseau.

Tâche 3 : Vérifier la route par défaut et les routes VPN

cr0x@server:~$ ip route
default via 192.168.1.1 dev enp0s31f6 proto dhcp metric 100
10.44.0.0/16 dev wg0 proto kernel scope link src 10.44.0.12
192.168.1.0/24 dev enp0s31f6 proto kernel scope link src 192.168.1.50 metric 100

Signification : La route par défaut est toujours sur le LAN local ; le VPN fournit une route seulement pour 10.44/16 (split tunnel).
Décision : Si le DNS corporate est dans 10.44/16, parfait. Si le VPN a poussé un DNS comme 10.99.0.53 mais qu’il n’y a pas de route vers 10.99/16, vous avez trouvé le bug : routes manquantes.

Tâche 4 : Demandez « comment route‑t‑on vers l’IP du serveur DNS ? »

cr0x@server:~$ ip route get 10.44.0.53
10.44.0.53 dev wg0 src 10.44.0.12 uid 1000
    cache

Signification : Les paquets vers 10.44.0.53 iront via wg0. Super.
Décision : Si ça route via la mauvaise interface (comme le Wi‑Fi), corrigez le routage/politique avant de toucher aux réglages DNS.

Tâche 5 : Vérifier que vous pouvez joindre le serveur DNS (ICMP optionnel ; UDP/53 est l’essentiel)

cr0x@server:~$ nc -uvz -w2 10.44.0.53 53
Connection to 10.44.0.53 53 port [udp/domain] succeeded!

Signification : UDP 53 paraît joignable. Ce n’est pas une garantie parfaite, mais cela suggère fortement que le routage/pare-feu ne bloque pas le DNS basique.
Décision : Si cela échoue, concentrez-vous sur les routes VPN, les règles de pare-feu, ou le serveur DNS qui serait down.

Tâche 6 : Inspecter ce que /etc/resolv.conf est réellement

cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Apr 25 10:12 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

Signification : Résolveur stub en usage ; les applis appellent 127.0.0.53 et systemd-resolved choisit l’amont.
Décision : Si /etc/resolv.conf est un fichier régulier pointant vers un DNS fourni par le VPN, vous avez peut‑être contourné resolved et cassé le split DNS. Décidez si vous voulez ça (probablement non).

Tâche 7 : Vérifier le statut de systemd-resolved et le DNS par lien

cr0x@server:~$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 2 (enp0s31f6)
    Current Scopes: DNS
         Protocols: +DefaultRoute
Current DNS Server: 192.168.1.1
       DNS Servers: 192.168.1.1

Link 4 (wg0)
    Current Scopes: DNS
         Protocols: -DefaultRoute
       DNS Servers: 10.44.0.53
        DNS Domain: ~corp.example

Signification : Mise en place parfaite du split DNS : seul corp.example est envoyé au DNS du VPN (domaine de routage préfixé par ~).
Décision : Si le lien VPN n’a pas de serveurs DNS, NetworkManager ne les a pas appliqués (ou un client a tout écrasé). Corrigez dans le profil NM/VPN.

Tâche 8 : Confirmer la résolution via le chemin systemd-resolved

cr0x@server:~$ resolvectl query app01.corp.example
app01.corp.example: 10.44.20.17                     -- link: wg0

-- Information acquired via protocol DNS in 42.1ms.
-- Data is authenticated: no

Signification : Resolved choisit wg0 et retourne l’enregistrement correct.
Décision : Si cela fonctionne mais que les applications échouent encore, vérifiez nsswitch.conf ou le comportement DNS spécifique à l’appli (certaines applis contournent glibc).

Tâche 9 : Comparer avec un dig direct contre le DNS du VPN

cr0x@server:~$ dig @10.44.0.53 app01.corp.example +time=2 +tries=1

; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @10.44.0.53 app01.corp.example +time=2 +tries=1
; (1 server found)
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48291
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
app01.corp.example.  60 IN A 10.44.20.17

;; Query time: 25 msec
;; SERVER: 10.44.0.53#53(10.44.0.53) (UDP)
;; WHEN: Thu Apr 25 10:26:51 UTC 2025
;; MSG SIZE  rcvd: 62

Signification : Le serveur DNS lui‑même est correct.
Décision : Si dig fonctionne mais que resolvectl échoue, le problème est local (politique/config — domaines, DNS par lien, état de resolved).

Tâche 10 : Vérifier si le VPN a changé la priorité DNS ou la gestion de la route par défaut

cr0x@server:~$ nmcli dev show wg0 | sed -n '1,120p'
GENERAL.DEVICE:                         wg0
GENERAL.TYPE:                           wireguard
GENERAL.STATE:                          100 (connected)
IP4.ADDRESS[1]:                         10.44.0.12/32
IP4.GATEWAY:                            --
IP4.DNS[1]:                             10.44.0.53
IP4.DOMAIN[1]:                          corp.example
IP4.ROUTE[1]:                           dst = 10.44.0.0/16, nh = 0.0.0.0, mt = 0

Signification : NM pense que wg0 a du DNS et une route. Bien.
Décision : Si IP4.DNS manque ici, corrigez le profil de connexion VPN ; ne manipulez pas resolved directement en premier lieu.

Tâche 11 : Vérifier les règles de routage de politique (courant avec kill-switch ou « full tunnel »)

cr0x@server:~$ ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Signification : Pas de règles de politique spéciales. La table de routage simple s’applique.
Décision : Si vous voyez des règles supplémentaires dirigeant le trafic DNS (ou tout le trafic) vers une table séparée, inspectez aussi ces tables. Ne supposez pas que ip route raconte toute l’histoire.

Tâche 12 : Inspecter les règles de pare‑feu pour des blocages DNS (surtout avec kill-switch VPN)

cr0x@server:~$ sudo nft list ruleset | sed -n '1,160p'
table inet filter {
  chain output {
    type filter hook output priority filter; policy accept;
    ip daddr 10.44.0.0/16 udp dport 53 accept
    ip daddr 10.44.0.0/16 tcp dport 53 accept
  }
}

Signification : Le DNS vers l’espace VPN est autorisé. Parfait.
Décision : Si vous voyez une chaîne output par défaut en drop ou des règles qui n’autorisent le trafic que via l’interface tunnel, confirmez que le DNS est inclus. Beaucoup de clients VPN « privacy » bloquent UDP/53 sauf si explicitement autorisé.

Tâche 13 : Vérifier les logs de systemd-resolved quand tout a l’air « configuré mais mort »

cr0x@server:~$ journalctl -u systemd-resolved -n 80 --no-pager
Apr 25 10:24:10 server systemd-resolved[812]: Using degraded feature set UDP instead of UDP+EDNS0 for DNS server 10.44.0.53.
Apr 25 10:24:12 server systemd-resolved[812]: Failed to send hostname reply: Transport endpoint is not connected
Apr 25 10:24:20 server systemd-resolved[812]: Switching to DNS server 10.44.0.53 for link 4.

Signification : Vous pouvez voir des retries, des basculements et des messages « degraded feature set » qui indiquent des problèmes MTU/fragmentation sur le VPN.
Décision : Si vous voyez des timeouts répétés ou des changements fréquents, passez aux vérifications MTU et essayez les requêtes DNS en TCP.

Tâche 14 : Tester le DNS sur TCP (parce que les VPN et le MTU adorent le drame)

cr0x@server:~$ dig @10.44.0.53 app01.corp.example +tcp +time=2 +tries=1

; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @10.44.0.53 app01.corp.example +tcp +time=2 +tries=1
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1136
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
app01.corp.example.  60 IN A 10.44.20.17

;; Query time: 31 msec
;; SERVER: 10.44.0.53#53(10.44.0.53) (TCP)
;; WHEN: Thu Apr 25 10:28:51 UTC 2025
;; MSG SIZE  rcvd: 62

Signification : Le TCP fonctionne. Si l’UDP échoue mais que le TCP réussit, suspectez des problèmes MTU/fragmentation ou des règles de pare-feu ciblant UDP.
Décision : Ajustez le MTU sur le tunnel, corrigez les problèmes de path MTU discovery, ou autorisez les UDP fragmentés. Ne « corrigez » pas en changeant de résolveur public ; cela ne ferait que masquer le problème.

Tâche 15 : Confirmer ce que feront les applications via NSS

cr0x@server:~$ grep -E '^(hosts|resolve)' /etc/nsswitch.conf
hosts:          files mdns4_minimal [NOTFOUND=return] dns

Signification : Ordre standard : files, puis mDNS, puis DNS. Correct.
Décision : Si dns manque ou a été remplacé par quelque chose d’étrange, vous pouvez avoir « resolvectl fonctionne mais getent échoue ». Corrigez l’ordre NSS avant d’accuser le VPN.

Tâche 16 : Tester la résolution comme un outil OS ennuyeux (parce que les navigateurs trompent)

cr0x@server:~$ getent ahosts app01.corp.example
10.44.20.17     STREAM app01.corp.example
10.44.20.17     DGRAM  app01.corp.example
10.44.20.17     RAW    app01.corp.example

Signification : Le chemin résolveur glibc fonctionne.
Décision : Si getent échoue mais que resolvectl query fonctionne, le problème se situe entre glibc et resolved (mode resolv.conf, nsswitch, ou DNS spécifique à l’appli).

Corriger dans le bon ordre : routes → résolveurs → split DNS → cache

Le thème : ne « corrigez » pas le DNS en forçant un seul résolveur global à moins que vous choisissiez délibérément de casser le split DNS.
Votre objectif est la justesse de la politique : les domaines internes se résolvent via le DNS interne quand le VPN est actif ; les domaines publics se résolvent normalement ; VPN déconnecté vous retrouvez le comportement standard.
C’est de la fiabilité, pas de l’héroïsme.

Étape 1 : Corriger le routage vers les serveurs DNS (et les zones internes)

La plupart des échecs DNS liés au VPN ne sont pas du DNS. Ce sont des problèmes de routage. Le VPN pousse une adresse de serveur DNS qui n’est joignable que via le tunnel,
mais le tunnel est mal configuré en split-route. Ou l’inverse : un full-tunnel est installé, mais le pare-feu client bloque le DNS hors tunnel.

Si vous découvrez des routes manquantes, décidez où la correction doit être appliquée :

  • Endroit correct : le profil VPN/la configuration serveur qui pousse les routes. Corrigez là ; tous les clients en profiteront.
  • Solution acceptable : ajouter des routes statiques sur le client quand vous ne pouvez pas contrôler le serveur VPN.
  • Mauvaise idée : basculer vers un résolveur public pour « revenir sur Internet ». Cela masque le routage interne cassé et détruit la résolution des noms internes.

Exemple : ajouter une route temporaire (jusqu’à correction du profil VPN) :

cr0x@server:~$ sudo ip route add 10.99.0.0/16 dev wg0

Signification : Vous avez rendu le réseau du serveur DNS joignable via le tunnel.
Décision : Si cela « corrige le DNS », retournez et implémentez la route dans les paramètres de connexion NetworkManager ou sur le serveur VPN. Ne laissez pas des routes uniques sur des postes comme stratégie permanente.

Étape 2 : S’assurer que systemd-resolved est l’autorité (sauf raison contraire)

Sur Ubuntu 24.04, vous voulez un décideur unique. Si un client VPN remplace /etc/resolv.conf par un fichier statique,
il peut contourner systemd-resolved et casser le split DNS. Restaurez le symlink stub si nécessaire.

cr0x@server:~$ sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Signification : Les applications utilisent le stub local ; resolved peut appliquer le DNS par lien et les domaines de routage.
Décision : Si vous administrez un serveur headless et ne voulez pas systemd-resolved, c’est un autre design. Mais ne mélangez pas les modes à la légère.

Étape 3 : Corriger les paramètres DNS et split DNS du profil VPN dans NetworkManager

Pour les VPN corporate, vous souhaitez généralement du split DNS : les zones internes via le DNS du VPN, le reste via votre résolveur normal.
Sur Ubuntu avec NetworkManager, cela signifie que la connexion VPN doit définir :

  • serveur(s) DNS VPN : résolveurs internes
  • domaines DNS : domaines de routage comme ~corp.example (ou configurés dans NM pour que resolved les récupère)
  • routes appropriées : vers les réseaux internes et les serveurs DNS

Inspectez et ajustez les paramètres de connexion (l’exemple montre des valeurs en lecture ; l’écriture dépend du type de VPN) :

cr0x@server:~$ nmcli -f NAME,TYPE,DEVICE connection show --active
Wired connection 1  ethernet  enp0s31f6
Corp WG            wireguard wg0
cr0x@server:~$ nmcli connection show "Corp WG" | sed -n '1,140p'
connection.id:                          Corp WG
connection.type:                        wireguard
ipv4.method:                            auto
ipv4.dns:                               10.44.0.53
ipv4.dns-search:                        corp.example
ipv4.never-default:                     yes

Signification : ipv4.never-default: yes indique un split tunnel (pas de route par défaut via VPN).
Décision : Si vous avez besoin d’un full tunnel, mettez never-default sur no (et assurez-vous que les routes DNS/pare-feu permettent le serveur DNS !). Si vous avez besoin d’un split tunnel, conservez yes mais assurez-vous que les routes vers les DNS internes et réseaux internes existent.

Étape 4 : Réparer le routage par domaine (la partie subtile que les gens zappent)

Vous pouvez avoir « des serveurs DNS définis » mais toujours envoyer les mauvaises requêtes vers eux.
Avec systemd-resolved, les domaines de routage importent. Un domaine de routage (préfixé par ~ dans la sortie de resolvectl)
indique à resolved quelles requêtes doivent être traitées par quel lien.

Si votre VPN doit gérer uniquement corp.example, définissez cela, pas une liste de recherche globale qui fait passer tout en interne.
Une liste de recherche globale est la raison pour laquelle vous finissez avec printer qui se résout en printer.corp.example alors que vous êtes chez vous,
et soudain votre réseau familial fait partie de l’incident.

Étape 5 : Vider les caches après les changements (mais seulement après)

systemd-resolved met en cache. Les navigateurs mettent en cache. Certaines applis mettent en cache agressivement. Videz le cache approprié au bon moment pour ne pas courir après des fantômes.

cr0x@server:~$ sudo resolvectl flush-caches
cr0x@server:~$ resolvectl statistics
DNSSEC supported by current servers: no
Transactions: 58
Cache hits: 11
Cache misses: 47

Signification : Si vous voyez des hits de cache pour de mauvaises réponses, vider aide, mais ne corrige pas la politique.
Décision : Videz une fois après des changements de configuration, puis retestez. Si vous videz en boucle pendant le débogage, vous perdez le signal.

Étape 6 : Si l’UDP est instable, traitez le MTU comme une priorité

Les VPN modifient le MTU. Le DNS sur UDP peut être impacté par la fragmentation, EDNS0, et les échecs de path MTU discovery.
Si vous voyez resolved dégrader les fonctionnalités ou des timeouts UDP, testez le TCP (Tâche 14).
Ensuite, envisagez de réduire le MTU du tunnel ou de corriger les règles de pare-feu qui jettent les fragments.

Blague n°2 : La manière la plus rapide d’apprendre ce qu’est le MTU est de l’ignorer pendant une semaine puis de le « découvrir » à 3h du matin.

Trois mini-récits d’entreprise tirés des tranchées DNS/VPN

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise de taille moyenne a déployé Ubuntu 24.04 à un groupe d’ingénieurs qui vivaient en mode VPN. La migration « s’est bien passée »
jusqu’à la première semaine où des services internes ont commencé à « flapper ». Le symptôme était étrange : les applications web internes fonctionnaient par IP mais échouaient par nom,
et seulement pour certains utilisateurs, selon où ils se trouvaient.

L’hypothèse était classique : « resolv.conf est la configuration DNS ». Un membre bien intentionné a écrit un script qui réécrivait
/etc/resolv.conf à la connexion VPN pour pointer directement vers le DNS corporate, et le réécrivait à la déconnexion.
Ça fonctionnait dans leurs tests en terminal. Ils ont déclaré victoire et sont retournés déployer des fonctionnalités.

Sur Ubuntu 24.04, ce script contournait la logique par lien et de routage de systemd-resolved.
Les utilisateurs en split tunnel ont commencé à envoyer toutes les requêtes DNS vers les résolveurs corporate — y compris les domaines publics — sur des chemins qui n’étaient pas routés.
Les serveurs DNS corporate n’étaient joignables que via le tunnel, et le script s’exécutait parfois avant l’installation des routes.
Les requêtes DNS n’aboutissaient pas, puis des NXDOMAINs étaient mis en cache, et l’expérience navigateur est devenue aléatoire.

La correction a été ennuyeuse : supprimer le script, restaurer le stub resolver, et corriger le profil VPN pour que NetworkManager fournisse à resolved les bons serveurs et domaines de routage.
L’incident s’est terminé non pas par un hack héroïque, mais par l’humilité d’admettre que le système avait un moteur de politique pour une raison.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Une autre organisation avait une équipe réseau tournée vers la performance. Fatigués des plaintes « DNS lent », ils ont décidé d’optimiser :
pousser un unique serveur DNS « rapide » à tous les clients VPN. Le serveur était un résolveur bien dimensionné proche du concentrateur VPN.
Ils ont aussi raccourci les TTL internes car « ça fait propager les changements plus vite ».

Ça s’est retourné contre eux de deux façons. D’abord, les clients en split tunnel avaient maintenant un résolveur joignable uniquement via le VPN, mais le push du serveur n’a pas garanti
les routes vers ce résolveur dans tous les modes de tunnel. Ensuite, les TTL faibles ont accru le volume de requêtes et rendu perceptible la perte de paquets intermittente sous forme de timeouts visibles par les utilisateurs.
Le résolveur était « rapide » en isolation et fragile dans le réseau réel.

Les ingénieurs ont commencé à coder en dur des résolveurs publics pour « réparer leur Internet », ce qui a créé une nouvelle classe de problèmes :
des domaines internes ont fuité vers des DNS publics (sans gravité la plupart du temps, mais embarrassant), et les noms internes ont cessé de se résoudre complètement.
Le playbook du helpdesk est devenu un champ de conseils contradictoires.

La remédiation finale : restaurer le split DNS (zones internes vers résolveurs internes seulement quand les routes existent),
garder des TTL raisonnables, et ajouter un fallback TCP pour le DNS sur le chemin VPN.
La performance s’est améliorée parce que le système était correct, pas parce que quelqu’un avait déclaré un résolveur « rapide ».

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une entreprise axée sécurité avait l’habitude, peu séduisante sur le papier : chaque changement VPN nécessitait une checklist de tests sur une image Ubuntu propre.
Pas un laptop de développeur. Pas une machine déjà configurée. Une VM jetable représentant la réalité de base.
Ils testaient le routage, le DNS, et un petit ensemble de résolutions de services internes.

Un jour, ils prévoyaient d’ajouter une nouvelle zone DNS interne et de mettre à jour le VPN pour pousser le domaine de routage correspondant.
Pendant la checklist, resolvectl status montrait que le domaine était ajouté comme domaine de recherche au lieu d’un domaine de routage.
Cela signifiait que resolved le traiterait différemment, et les noms courts commenceraient à se résoudre de façon surprenante.
Ce n’était pas encore un incident de sécurité, mais ça sentait le problème.

L’équipe l’a détecté avant le déploiement. Ils ont ajusté la génération de profil NetworkManager pour que le VPN crée un routage par domaine approprié.
Ils ont aussi vérifié que l’IP du serveur DNS était joignable en mode split tunnel en checkant ip route get pendant la connexion.
Cela a évité la vague de tickets « VPN connecté mais DNS mort ».

Pas d’héroïsme. Pas d’éditions à minuit. Juste une checklist qui traitait le DNS et le routage comme des systèmes couplés.
Les meilleures pannes sont celles qui ne vous réveillent pas au milieu de la nuit.

Erreurs courantes (symptômes → cause racine → correction)

1) Symptôme : « Le VPN se connecte, mais les noms internes ne se résolvent pas »

Cause racine : Le serveur DNS du VPN est configuré, mais il n’y a pas de route vers lui (split tunnel sans le sous‑réseau du résolveur).
Correction : Ajouter/réparer les routes vers l’IP du serveur DNS dans le profil VPN ou la configuration push côté serveur. Vérifier avec ip route get DNS_IP.

2) Symptôme : « Le DNS public fonctionne, le DNS interne échoue »

Cause racine : Split DNS non configuré ; les domaines internes ne sont pas envoyés au résolveur VPN (ou domaines de routage manquants).
Correction : Configurer les domaines de routage (ex. ~corp.example) pour le lien VPN dans resolved/NM, et assurer que les serveurs DNS VPN sont définis sur ce lien.

3) Symptôme : « L’interne fonctionne, mais Internet meurt quand le VPN est actif »

Cause racine : Une route full tunnel installée (ou des règles kill-switch) mais le DNS VPN pointe vers des résolveurs internes qui ne résolvent pas les domaines publics, ou l’egress est restreint.
Correction : Décider la politique : full tunnel avec des résolveurs d’entreprise qui résolvent le public, ou split tunnel avec un résolveur non-VPN pour le public. Ne faites pas un compromis à moitié.

4) Symptôme : « resolvectl query fonctionne, mais navigateurs/applis échouent »

Cause racine : L’application contourne le résolveur système (DoH, résolveur personnalisé, DNS de conteneur, ou nameserver codé en dur).
Correction : Confirmer avec getent ahosts et vérifier les paramètres de l’appli. Désactiver temporairement le DoH de l’appli ou l’aligner sur la politique DNS corporate.

5) Symptôme : « dig @DNS fonctionne, mais resolvectl query timeouts »

Cause racine : systemd-resolved utilise des serveurs DNS différents ou une mauvaise sélection de lien à cause de domaines de routage manquants.
Correction : Inspecter resolvectl status et assurer que le lien VPN possède des serveurs DNS et des domaines de routage ~domain.

6) Symptôme : « Le DNS fonctionne un moment, puis casse après mise en veille/reprise »

Cause racine : Le VPN se reconnecte mais les paramètres DNS ne sont pas réappliqués (course entre le VPN up et la mise à jour NM/resolved), ou des routes obsolètes restent.
Correction : Confirmer après reprise avec les tâches 3, 7, 10. Si manquant, corriger les scripts dispatcher ou l’intégration du client VPN ; vider le cache n’est qu’un pansement, pas une solution.

7) Symptôme : « Seules les grosses réponses DNS échouent (certains domaines chargent, d’autres non) »

Cause racine : Problèmes MTU/fragmentation, EDNS0, ou fragments UDP droppés à travers le tunnel.
Correction : Tester le TCP DNS. Ajuster le MTU du tunnel, autoriser les fragments, ou configurer le client/résolveur pour des tailles UDP plus sûres.

8) Symptôme : « NXDOMAIN aléatoire pour des noms internes »

Cause racine : Un mauvais résolveur répond aux requêtes internes (résolveur public ou routeur domestique), parfois dû à un domaine de routage manquant ou une mauvaise priorité DNS.
Correction : Imposer le split DNS : les zones internes routées exclusivement vers les résolveurs internes via le lien VPN.

Listes de contrôle / plan étape par étape

Checklist A : La séquence « il me faut que ça marche maintenant » (10–15 minutes)

  1. Confirmer que l’interface VPN est UP : ip -brief link.
  2. Confirmer que le VPN a une IP : ip addr show dev wg0 ou ip addr show dev tun0.
  3. Vérifier les routes : ip route.
  4. Vérifier la route vers le serveur DNS : ip route get DNS_IP.
  5. Tester la joignabilité du port DNS : nc -uvz DNS_IP 53.
  6. Inspecter l’état du résolveur : resolvectl status.
  7. Interroger un nom interne : resolvectl query host.corp.example.
  8. Comparer avec un dig direct : dig @DNS_IP host.corp.example.
  9. Vider le cache une fois après les changements : sudo resolvectl flush-caches.
  10. Si l’UDP est instable, tester le TCP : dig @DNS_IP host.corp.example +tcp.

Checklist B : Rendre la correction durable (pour ne pas revoir ce ticket)

  1. Arrêter d’éditer manuellement /etc/resolv.conf ; restaurer le symlink stub si nécessaire.
  2. Corriger le profil VPN/la configuration serveur pour pousser les routes incluant le sous‑réseau du serveur DNS et les réseaux internes.
  3. Configurer des domaines de routage split DNS (pas seulement des domaines de recherche) pour les zones internes.
  4. Valider avec resolvectl status que le lien VPN possède ~corp.example.
  5. Confirmer que nmcli dev show montre DNS et domaines sur l’interface VPN.
  6. Auditer les règles de pare‑feu/kill-switch pour DNS en UDP et TCP.
  7. Documenter l’état attendu : quelle interface possède quel domaine et quels serveurs DNS.
  8. Ajouter un test de régression : connecter le VPN sur une image Ubuntu propre et exécuter resolvectl query pour au moins un nom interne et un nom public.

Checklist C : Quand vous suspectez que le client VPN « en fait trop »

  1. Vérifier si /etc/resolv.conf a été remplacé par un fichier régulier.
  2. Vérifier la présence d’entrées ip rule supplémentaires.
  3. Vérifier la sortie nft pour des règles filtrant le UDP/53.
  4. Rechercher plusieurs gestionnaires DNS en cours (client propriétaire + NetworkManager + resolved).
  5. Choisir un gestionnaire comme source de vérité ; désactiver la manipulation DNS des autres si possible.

FAQ

1) Pourquoi le VPN casse le DNS sur Ubuntu 24.04 en particulier ?

Ce n’est pas « spécifique », mais Ubuntu 24.04 rend le phénomène plus visible parce que systemd-resolved et le DNS par lien sont courants.
Les clients VPN qui supposent que /etc/resolv.conf est le seul réglage peuvent entrer en conflit avec la pile réelle de résolveur.

2) Dois‑je désactiver systemd-resolved ?

Généralement non. Resolved gère bien le split DNS quand il reçoit des paramètres par lien corrects. Désactivez‑le seulement si vous avez un plan alternatif clair
(par exemple un résolveur cache local que vous administrez) et que vous comprenez comment les clients VPN vont le mettre à jour.

3) Mon /etc/resolv.conf pointe vers 127.0.0.53. Est‑ce incorrect ?

Non. C’est le stub local. Les vrais serveurs en amont sont visibles dans resolvectl status.
Si vous pointez /etc/resolv.conf directement vers un serveur amont, vous pouvez contourner le split DNS.

4) Que signifie ~corp.example dans resolvectl status ?

Le tilde indique un domaine de routage : les requêtes pour ce domaine vont vers les serveurs DNS de ce lien.
Sans le tilde, c’est plutôt un domaine de recherche, ce qui change la manière dont les noms courts sont étendus.

5) Pourquoi dig fonctionne mais mes applis échouent encore ?

dig @server contourne la politique du résolveur et interroge directement un serveur. Il prouve la joignabilité et la justesse du serveur,
pas que votre OS utilise ce serveur pour ce domaine. Les applis peuvent aussi utiliser DoH ou leur propre pile de résolveur.

6) Pourquoi le DNS fonctionne pour de petits enregistrements mais échoue pour certains domaines ?

Les réponses plus volumineuses (plusieurs A/AAAA, DNSSEC, gros TXT) peuvent rencontrer des problèmes de fragmentation UDP à travers le VPN.
Testez avec dig +tcp. Si le TCP fonctionne mais pas l’UDP, traitez le MTU/fragmentation ou le comportement du pare-feu.

7) Puis‑je simplement ajouter un DNS public comme 1.1.1.1 en fallback ?

Vous pouvez, mais c’est une décision politique avec des conséquences. Cela provoque souvent des fuites de requêtes internes vers des DNS publics ou des échecs imprévisibles,
et cela peut masquer des routes VPN manquantes. Si votre entreprise exige une résolution interne uniquement, ne le faites pas.

8) Comment savoir si le VPN force une route par défaut ?

Vérifiez ip route pour la route par défaut et nmcli connection show pour ipv4.never-default.
Vérifiez aussi ip rule pour le routage de politique qui pourrait remplacer la route par défaut.

9) Pourquoi ça casse seulement après avoir reconnecté le VPN ?

Conditions de course et état obsolète : les routes et domaines DNS peuvent ne pas être complètement supprimés à la déconnexion,
ou ne pas être réappliqués à la reconnexion. Confirmez l’état après reconnexion avec ip route et resolvectl status.

10) Quelle est la manière la plus sûre de valider une correction ?

Validez trois choses : (1) ip route get DNS_IP utilise l’interface attendue, (2) resolvectl status montre le DNS par lien et les domaines de routage corrects,
(3) getent ahosts résout les noms internes et publics comme attendu, VPN actif et inactif.

Conclusion : prochaines étapes pratiques

Quand le VPN casse le DNS sur Ubuntu 24.04, le meilleur mouvement est de respecter l’ordre. D’abord les routes. Ensuite la politique du résolveur. Puis le split DNS. Enfin le cache.
Si vous corrigez dans l’ordre inverse, vous obtiendrez quelque chose qui « marche » jusqu’à ce que ça ne marche plus — généralement quand vous présentez quelque chose, êtes d’astreinte, ou les deux.

Prochaines étapes que vous pouvez faire aujourd’hui :

  1. Exécutez le playbook de diagnostic rapide et capturez les sorties pour ip route et resolvectl status.
  2. Vérifiez la joignabilité du serveur DNS VPN avec ip route get et nc -uvz.
  3. Restaurez le stub /etc/resolv.conf si un client VPN l’a écrasé.
  4. Corrigez le profil VPN/serveur afin que les routes et domaines de routage correspondent aux serveurs DNS poussés.
  5. Ajoutez une checklist de régression sur une image Ubuntu 24.04 propre, car l’état d’hier du laptop n’est pas un environnement de test.

Les pannes DNS sont rarement glamours. Elles sont, en revanche, extrêmement honnêtes : le système fera exactement ce que vos routes et votre politique de résolveur lui disent de faire.
Rendez ces deux éléments corrects, et le reste tendra à se remettre en place.

← Précédent
Attaques de la chaîne d’approvisionnement : quand les pirates ciblent votre fournisseur plutôt que vous
Suivant →
IKEv2/IPsec : Quand c’est un meilleur choix que WireGuard ou OpenVPN

Laisser un commentaire