Resolver el nombre de host lleva 5 segundos


8

Tengo un bind9servidor DNS maestro y 2 servidores esclavos que se ejecutan en IPv4 (Debian Jessie), usando /etc/bind/named.conf:

listen-on-v6 { none; };

Cuando intento conectarme desde diferentes servidores, cada conexión toma al menos 5 segundos (estoy usando la información de sincronización de Joseph para la depuración):

$ 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

Según curl, la búsqueda lleva la mayor parte del tiempo, sin embargo, el estándar nslookupes muy rápido:

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

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

Después de forzar curla usar IPv4, se pone mucho mejor:

$ 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

He deshabilitado IPv6 en el host:

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

aunque el problema persiste. He intentado correr stracepara ver cuál es la razón de los tiempos de espera:

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)

No parece ser un problema de firewall ya que nslookup(o curl -4) está utilizando los mismos servidores DNS. ¿Alguna idea de lo que podría estar mal?

Aquí está tcpdumpdel anfitrión 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)

EDITAR: En los registros de enlace aparece con frecuencia este mensaje:

error sending response: host unreachable

Sin embargo, cada consulta finalmente se responde (solo toma 5 segundos). Todas las máquinas son servidores físicos (no es culpa de NAT), es más probable que un enrutador bloquee los paquetes. Aquí hay una pregunta relacionada muy probable: las búsquedas de DNS a veces tardan 5 segundos .


1
strace -ttharía que la traza sea más informativa al rastrear retrasos.
JigglyNaga

Gracias, no ayuda mucho en este caso. Parece estar atascado en una mirada mientras vuelve a intentar la misma conexión con un tiempo de espera creciente poll(0, 0, 1000) = 0 (Timeout). En el lado del servidor DNS, recibo errores frecuentes error sending response: host unreachableque parecen que el paquete saliente está bloqueado (pero no para nslookup).
Tombart

Respuestas:


9

Respuesta corta:

Una solución alternativa está obligando glibca reutilizar un socket para buscar los registros AAAAy A, agregando una línea a /etc/resolv.conf:

options single-request-reopen

La verdadera causa de este problema podría ser:

Respuesta larga:

Programas como curlo wgetusan la función getaddrinfo () de glibc , que trata de ser compatible con IPv4 e IPv6 al buscar ambos registros DNS en paralelo. No devuelve el resultado hasta que se reciben ambos registros (hay varios problemas relacionados con dicho comportamiento ), esto explica lo straceanterior. Cuando se fuerza IPv4, como curl -4internamente, gethostbyname()qué consultas Asolo para registro.

De tcpdumppodemos ver que:

  • -> A? se envían dos solicitudes al principio
  • -> AAAA? (solicitando dirección IPv6)
  • <- AAAA respuesta
  • -> A? solicitando nuevamente la dirección IPv4
  • <- A obtuve respuesta
  • -> AAAA? solicitando IPv6 nuevamente
  • <- AAAA respuesta

Una Arespuesta se descarta por alguna razón, ese es este mensaje de error:

error sending response: host unreachable

Sin embargo, no está claro para mí por qué hay una segunda AAAAconsulta.

Para verificar que tiene el mismo problema, puede actualizar el tiempo de espera en /etc/resolv.conf:

options timeout:3

como se describe aquí :

$ 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

Hay otras dos opciones relacionadas en man resolv.conf:

de solicitud única (desde glibc 2,10) conjuntos RES_SNGLKUP en _res.options. Por defecto, glibc realiza búsquedas de IPv4 e IPv6 en paralelo desde la versión 2.9. Algunos servidores DNS de dispositivos no pueden manejar estas consultas correctamente y agotar el tiempo de espera de las solicitudes. Esta opción deshabilita el comportamiento y hace que glibc realice las solicitudes de IPv6 e IPv4 secuencialmente (a costa de una cierta desaceleración del proceso de resolución).

single-request-reopen (desde glibc 2.9) El resolutor utiliza el mismo socket para las solicitudes A y AAAA. Algunos hardware envían por error solo una respuesta. Cuando eso suceda, el sistema cliente se sentará y esperará la segunda respuesta. Activar esta opción cambia este comportamiento de modo que si dos solicitudes del mismo puerto no se manejan correctamente, cerrará el socket y abrirá uno nuevo antes de enviar la segunda solicitud.

Asuntos relacionados:


@RuiFRibeiro Basado exclusivamente en las actualizaciones, parecía que los usuarios encontraban la otra respuesta más útil. Sin ofender.
Tombart

4

Como dice @Tombart, el retraso se debe a la espera del tiempo de espera de resolución IPv6.

Otro posible curso de acción es dar prioridad a IPv4 en /etc/gai.conf

De los comentarios en /etc/gai.conf

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

Después de cambiar gai.conf, debe reiniciar cualquier aplicación que use la biblioteca de resolución de DNS para que el cambio surta efecto.

Tenga en cuenta que si está utilizando un servidor BIND sin conectividad IPv6, le recomiendo deshabilitar IPv6 namedy tomar de la raíz las direcciones IPv6. Obviamente, aún intentará resolver las direcciones AAAA.

Entonces, para la configuración BIND,

En / etc / default / bind9, agregue -4 para las direcciones IPv4:

OPTIONS="-4 -u bind"

y en /etc/bind/db.root, eliminar todas las líneas con raíces DNS AAAA.


2

Tuve un problema similar al usar BIND9. Para solucionar esto, necesitaba agregar:

filter-aaaa-on-v4 yes;

opción a mi named.conf.

( Más información )

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.