La résolution du nom d'hôte prend 5 secondes


8

J'ai un bind9serveur DNS maître et 2 serveurs esclaves fonctionnant sur IPv4 (Debian Jessie), utilisant /etc/bind/named.conf:

listen-on-v6 { none; };

Lorsque j'essaie de me connecter à partir de différents serveurs, chaque connexion prend au moins 5 secondes (j'utilise les informations de synchronisation de Joseph pour le débogage):

$ curl -w "@curl-format.txt" -o /dev/null -s https://example.com
            time_namelookup:  5.512
               time_connect:  5.512
            time_appconnect:  5.529
           time_pretransfer:  5.529
              time_redirect:  0.000
         time_starttransfer:  5.531
                            ----------
                 time_total:  5.531

Selon curl, la recherche prend la plupart du temps, mais la norme nslookupest très rapide:

$ time nslookup example.com > /dev/null 2>&1

real    0m0.018s
user    0m0.016s
sys     0m0.000s

Après avoir forcé curlà utiliser IPv4, cela va beaucoup mieux:

$ curl -4 -w "@curl-format.txt" -o /dev/null -s https://example.com

            time_namelookup:  0.004
               time_connect:  0.005
            time_appconnect:  0.020
           time_pretransfer:  0.020
              time_redirect:  0.000
         time_starttransfer:  0.022
                            ----------
                 time_total:  0.022

J'ai désactivé IPv6 sur l'hôte:

echo 1 > /proc/sys/net/ipv6/conf/eth0/disable_ipv6

bien que le problème persiste. J'ai essayé de courir stracepour voir quelle est la raison des temps morts:

write(2, "*", 1*)                        = 1
write(2, " ", 1 )                        = 1
write(2, "Hostname was NOT found in DNS ca"..., 36Hostname was NOT found in DNS cache
) = 36
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 4
close(4)                                = 0
mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f220bcf8000
mprotect(0x7f220bcf8000, 4096, PROT_NONE) = 0
clone(child_stack=0x7f220c4f7fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f220c4f89d0, tls=0x7f220c4f8700, child_tidptr=0x7f220c4f89d0) = 2004
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 4)                           = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 8)                           = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 16)                          = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 32)                          = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 64)                          = 0 (Timeout)

Il ne semble pas y avoir de problème de pare-feu car nslookup(ou curl -4) utilise les mêmes serveurs DNS. Une idée de ce qui pourrait être faux?

Voici tcpdumpde l'hôte tcpdump -vvv -s 0 -l -n port 53:

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:14:52.542526 IP (tos 0x0, ttl 64, id 35839, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x96c7!] 39535+ A? example.com. (35)
20:14:52.542540 IP (tos 0x0, ttl 64, id 35840, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x6289!] 45997+ AAAA? example.com. (35)
20:14:52.543281 IP (tos 0x0, ttl 61, id 63674, offset 0, flags [none], proto UDP (17), length 158)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 45997* q: AAAA? example.com. 1/1/0 example.com. [1h] CNAME s01.example.com. ns: example.com. [10m] SOA ns01.example.com. ns51.domaincontrol.com. 2016062008 28800 7200 1209600 600 (130)
20:14:57.547439 IP (tos 0x0, ttl 64, id 36868, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x96c7!] 39535+ A? example.com. (35)
20:14:57.548188 IP (tos 0x0, ttl 61, id 64567, offset 0, flags [none], proto UDP (17), length 184)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 39535* q: A? example.com. 2/2/2 example.com. [1h] CNAME s01.example.com., s01.example.com. [1h] A 136.243.154.168 ns: example.com. [30m] NS ns01.example.com., example.com. [30m] NS ns02.example.com. ar: ns01.example.com. [1h] A 136.243.154.168, ns02.example.com. [1h] A 192.168.1.2 (156)
20:14:57.548250 IP (tos 0x0, ttl 64, id 36869, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x6289!] 45997+ AAAA? example.com. (35)
20:14:57.548934 IP (tos 0x0, ttl 61, id 64568, offset 0, flags [none], proto UDP (17), length 158)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 45997* q: AAAA? example.com. 1/1/0 example.com. [1h] CNAME s01.example.com. ns: example.com. [10m] SOA ns01.example.com. ns51.domaincontrol.com. 2016062008 28800 7200 1209600 600 (130)

EDIT: Dans les journaux de liaison apparaît fréquemment ce message:

error sending response: host unreachable

Cependant, chaque requête reçoit finalement une réponse (cela ne prend que 5 secondes). Toutes les machines sont des serveurs physiques (ce n'est pas la faute du NAT), il est plus probable que les paquets soient bloqués par un routeur. Voici une question connexe très probable: les recherches DNS prennent parfois 5 secondes .


1
strace -ttrendrait la trace plus informative lors du suivi des retards.
JigglyNaga

Merci, cela n'aide pas beaucoup dans ce cas. Il semble être bloqué dans un look tout en réessayant la même connexion avec un délai d'attente croissant poll(0, 0, 1000) = 0 (Timeout). Du côté du serveur DNS, je reçois des erreurs fréquentes error sending response: host unreachablequi semblent que le paquet sortant est bloqué (mais pas pour nslookup).
Tombart

Cela semble similaire
Jeff Schaller

Réponses:


9

Réponse courte:

Une solution de contournement oblige glibcà réutiliser un socket pour rechercher les enregistrements AAAAet A, en ajoutant une ligne à /etc/resolv.conf:

options single-request-reopen

La véritable cause de ce problème pourrait être:

Longue réponse:

Des programmes comme curlou wgetutilisent la fonction getaddrinfo () de la glibc , qui essaie d'être compatible avec IPv4 et IPv6 en recherchant les deux enregistrements DNS en parallèle. Il ne renvoie aucun résultat tant que les deux enregistrements n'ont pas été reçus (il y a plusieurs problèmes liés à un tel comportement ) - cela explique ce qui straceprécède. Lorsque IPv4 est forcé, comme en curl -4interne gethostbyname()qui interroge Auniquement l'enregistrement.

De tcpdumpnous pouvons voir que:

  • -> A? deux demandes sont envoyées au début
  • -> AAAA? (demande d'adresse IPv6)
  • <- AAAA répondre
  • -> A? nouvelle demande d'adresse IPv4
  • <- A a obtenu une réponse
  • -> AAAA? demander à nouveau IPv6
  • <- AAAA répondre

Une Aréponse est supprimée pour une raison quelconque, c'est ce message d'erreur:

error sending response: host unreachable

Pourtant, je ne comprends pas pourquoi il y a un besoin de deuxième AAAArequête.

Pour vérifier que vous rencontrez le même problème, vous pouvez mettre à jour le délai d'expiration dans /etc/resolv.conf:

options timeout:3

comme décrit ici :

$ curl -w "@curl-format.txt" -o /dev/null -s https://example.com

            time_namelookup:  3.511
               time_connect:  3.511
            time_appconnect:  3.528
           time_pretransfer:  3.528
              time_redirect:  0.000
         time_starttransfer:  3.531
                            ----------
                 time_total:  3.531

Il existe deux autres options connexes dans man resolv.conf:

simple demande (depuis la glibc 2.10) ensembles RES_SNGLKUP dans _res.options. Par défaut, glibc effectue des recherches IPv4 et IPv6 en parallèle depuis la version 2.9. Certains serveurs DNS d'appliance ne peuvent pas gérer correctement ces requêtes et font expirer les requêtes. Cette option désactive le comportement et oblige la glibc à exécuter les requêtes IPv6 et IPv4 séquentiellement (au prix d'un certain ralentissement du processus de résolution).

single-request-reopen (depuis la glibc 2.9) Le résolveur utilise le même socket pour les requêtes A et AAAA. Certains matériels renvoient par erreur une seule réponse. Lorsque cela se produit, le système client s'assoit et attend la deuxième réponse. L'activation de cette option modifie ce comportement de sorte que si deux demandes provenant du même port ne sont pas traitées correctement, il fermera le socket et en ouvrira un nouveau avant d'envoyer la deuxième demande.

Problèmes liés:


@RuiFRibeiro Uniquement sur la base des up-voltes, il semble que les utilisateurs ont trouvé l'autre réponse plus utile. Aucune infraction signifiait.
Tombart

4

Comme le dit @Tombart, le retard est dû à l'attente du délai d'expiration de la résolution IPv6.

Un autre plan d'action possible est de donner la priorité à IPv4 dans /etc/gai.conf

À partir des commentaires dans /etc/gai.conf

#   For sites which prefer IPv4 connections change the last line to
#
precedence ::ffff:0:0/96  100

Après la modification gai.conf, vous devez redémarrer toute application à l'aide de la bibliothèque de résolution DNS pour que la modification prenne effet.

N'oubliez pas que si vous utilisez un serveur BIND sans connectivité IPv6, je vous conseille de désactiver IPv6 namedet de prendre des adresses IPv6 à partir des indices racine. De toute évidence, il essaiera toujours de résoudre les adresses AAAA.

Donc, pour la configuration BIND,

Dans / etc / default / bind9, ajoutez -4 pour les adresses IPv4:

OPTIONS="-4 -u bind"

et dans /etc/bind/db.root, supprimez toutes les lignes avec des racines DNS AAAA.


2

J'ai eu un problème similaire lors de l'utilisation de BIND9. Pour résoudre ce problème, je devais ajouter:

filter-aaaa-on-v4 yes;

option à mon named.conf.

( Plus d'informations )

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.