Les recherches DNS prennent parfois 5 secondes

11

J'ai une machine virtuelle exécutant Debian Wheezy sur laquelle certaines recherches de nom d'hôte prennent plusieurs secondes, même si le résolveur répond immédiatement. Étrangement, les recherches avec getaddrinfo()sont affectées, mais ce gethostbyname()n'est pas le cas.

Je suis passé aux résolveurs Google pour exclure la possibilité que les résolveurs locaux soient cassés, donc mon /etc/resolv.confapparence ressemble à:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

Mon nsswitch.confa la ligne:

hosts: files dns

et mon /etc/hostsne contient rien d'inhabituel.

Si j'essaye telnet webserver 80, il se bloque pendant plusieurs secondes avant d'obtenir une résolution de nom. Une ltracesortie [1] montre que le blocage est en cours d' getaddrinfo()appel:

getaddrinfo("ifconfig.me", "telnet", { AI_CANONNAME, 0, SOCK_STREAM, 0, 0, NULL, '\000', NULL }, 0x7fffb4ffc160) = 0 <5.020621>

Cependant, tcpdumprévèle que le serveur de noms a répondu immédiatement, et ce n'est que sur la deuxième réponse qui a telnetdébloqué. Les réponses semblent identiques:

05:52:58.609731 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:52:58.609786 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:52:58.612188 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)

[...five second pause...]

05:53:03.613811 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:53:03.616424 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)
05:53:03.616547 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:53:03.618907 IP 8.8.4.4.53 > 192.168.1.75.43017: 26090 0/1/0 (76)

J'ai vérifié les journaux du pare-feu de l'hôte et rien sur le port 53 n'est bloqué.

Qu'est-ce qui fait que la première réponse DNS est ignorée?

[1] J'ai ajouté quelques lignes à mon ltrace.confafin que je puisse voir l'intérieur de la addrinfostructure.

Flup
la source
Comment est la configuration NIC de la VM? Ponté? NAT?
slm
C'est NATted. Je ne sais pas exactement où le NAT est appliqué (que ce soit par ESX ou plus en amont); Je peux savoir si vous pensez que cela pourrait être important.
Flup
Je soupçonne que c'est la NAT + VM qui influence cela.
slm
Peut-être bien - voir mes commentaires sur la réponse de Kempniu ci-dessous.
Flup
C'était réseau, mais pas spécifiquement NAT causant cela - voir ma réponse ci-dessous.
Flup

Réponses:

13

La première réponse DNS n'est pas ignorée. getaddrinfo()n'est retourné qu'après avoir reçu la réponse à la première requête AAAA (ID: 26090). Donc, le vrai problème ici est pourquoi votre machine n'a pas immédiatement reçu la réponse à la requête AAAA, alors qu'elle a reçu la réponse pour la requête A (ID: 54755).

L'une des différences entre getaddrinfo()et gethostbyname()est que le premier prend en charge IPv4 et IPv6, tandis que le dernier ne prend en charge que IPv4. Ainsi, lorsque vous appelez getaddrinfo()avec ai_familyset à 0 ( AF_UNSPEC), il ne reviendra pas tant qu'il n'aura pas de réponse (ou atteindra un délai) pour les requêtes A et AAAA pour le nom de domaine fourni. gethostbyname()recherche uniquement un enregistrement A.

Il est difficile de déterminer à distance ce qui peut être à l'origine de votre problème, en particulier si vous avez coupé certaines tcpdumpsorties. Quelque chose pourrait filtrer / supprimer sélectivement le trafic DNS entre votre machine virtuelle et les résolveurs DNS publics de Google. J'ai essayé de reproduire votre problème en utilisant une machine virtuelle Debian Wheezy KVM, mais j'ai telnet ifconfig.mepresque immédiatement imprimé la Trying <IP_address_here>...ligne (ce qui signifie qu'il a déjà résolu le nom d'ici là).

Kempniu
la source
Merci pour votre réponse détaillée. Je n'ai rien coupé du tcpdump, j'ai seulement inséré une ligne pour préciser où était la pause. Vous m'avez certainement donné quelque chose pour continuer cependant; Je n'ai pas réalisé la différence significative entre les deux appels de bibliothèque.
Flup
Si plus aucun paquet lié au DNS n'atteint votre machine, quelque chose filtre probablement son trafic (pas nécessairement exprès). Quoi qu'il en soit, si vous trouvez une solution, pourriez-vous la partager ici?
Kempniu
1
Je le ferai en effet. Après avoir mis en place un résolveur de test, je peux voir de manière concluante qu'un paquet de réponse - celui de ma question - est supprimé à chaque fois. Je soupçonne que quelque chose dans ou près de l'infrastructure VMware le fait, j'ai donc contacté mon homologue qui s'occupe de ce côté-là. Quand j'arriverai au fond, je reviendrai et ajouterai des détails. Merci encore!
Flup
Solution ajoutée dans ma propre réponse. Merci encore une fois pour votre aide.
Flup
9

Cela était dû à un ensemble de règles trop restrictif sur un pare-feu Juniper qui se trouve en face de l'infrastructure VMware.

J'ai construit un résolveur de test pour que je puisse voir les deux côtés de la conversation, et le paquet manquant identifié par Kempniu dans son excellente réponse était en effet abandonné quelque part en cours de route. Comme indiqué dans cette réponse, getaddrinfo()sans adresse spécifiée, la famille attendra les réponses concernant toutes les familles prises en charge avant de revenir (ou, dans mon cas, expirer).

Mon collègue qui dirige le réseau a noté que

Le comportement par défaut sur le pare-feu Juniper consiste à fermer une session liée au DNS dès qu'une réponse DNS correspondant à cette session est reçue.

Le pare-feu voyait donc la réponse IPv4, notant qu'il répondait à la requête de la machine virtuelle et fermant le chemin entrant pour ce port. Le paquet de réponse IPv6 suivant a donc été supprimé. Je ne sais pas pourquoi les deux paquets ont réussi la deuxième fois, mais la désactivation de cette fonctionnalité sur le pare-feu a résolu le problème.

Il s'agit d'un extrait connexe de la base de connaissances Juniper:

Voici un scénario où les paquets de réponse DNS sont supprimés:

  1. Une session pour le trafic DNS est créée lorsque le premier paquet de requêtes DNS atteint le pare-feu et qu'une stratégie d'autorisation est configurée. Le délai d'expiration par défaut est de 60 secondes.
  2. Immédiatement avant la fermeture de la session, une nouvelle requête DNS est transmise et, puisqu'elle correspond à une session existante (puisque la paire source / destination port / IP est toujours la même), elle est transmise par le pare-feu. Notez que le délai d'expiration de la session n'est pas actualisé en fonction de tout nouveau paquet arrivant.
  3. La session DNS créée est périmée lorsque la première réponse (réponse) à la requête DNS frappe le périphérique, quel que soit le délai restant.
  4. Lorsqu'une réponse DNS est transmise via le pare-feu, la session est périmée.
  5. Toutes les réponses DNS suivantes sont supprimées par le pare-feu, car aucune session n'existe.

Si vous songez à voter pour cette réponse, veuillez également voter pour la réponse de Kempniu. Sans cela, je serais toujours en train d'essayer de trouver un problème de configuration sur la machine virtuelle.

Flup
la source
1
Nous avons rencontré les mêmes symptômes sur Debian 8.2. La nôtre était due à une cause différente et la «solution» était différente (côté client). J'ai blogué sur notre problème spécifique et le problème plus général: philippecloutier.com/… Je tiens à remercier Flup et Kempniu, car vos questions et réponses me mettent sur la bonne voie.
Philippe Cloutier