La risoluzione del nome host richiede 5 secondi


8

Ho un bind9server DNS master e 2 server slave in esecuzione su IPv4 (Debian Jessie), usando /etc/bind/named.conf:

listen-on-v6 { none; };

Quando provo a connettermi da server diversi, ogni connessione richiede almeno 5 secondi (sto usando le informazioni di temporizzazione di Joseph per il debug):

$ 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

Secondo curl, la ricerca richiede la maggior parte del tempo, tuttavia lo standard nslookupè molto veloce:

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

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

Dopo aver forzato curll'uso di IPv4, migliora molto:

$ 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

Ho disabilitato IPv6 sull'host:

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

sebbene il problema persista. Ho provato a correre straceper vedere qual è la ragione dei timeout:

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)

Non sembra essere un problema di firewall poiché nslookup(o curl -4) utilizza gli stessi server DNS. Qualche idea di cosa potrebbe esserci di sbagliato?

Ecco tcpdumpdall'host 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: nei registri di bind appare spesso questo messaggio:

error sending response: host unreachable

Tuttavia, a ogni query viene infine fornita una risposta (bastano 5 secondi). Tutte le macchine sono server fisici (non è colpa del NAT), è più probabile che i pacchetti vengano bloccati da un router. Ecco una domanda molto probabilmente correlata: le ricerche DNS a volte impiegano 5 secondi .


1
strace -ttrenderebbe la traccia più informativa quando si rintracciano ritardi.
JigglyNaga,

Grazie, non aiuta molto in questo caso. Sembra bloccato in uno sguardo mentre riprova la stessa connessione con un timeout crescente poll(0, 0, 1000) = 0 (Timeout). Sul lato server DNS ricevo frequenti errori error sending response: host unreachableche sembrano bloccati (ma non per nslookup) il pacchetto in uscita .
Tombart,

Risposte:


9

Risposta breve:

Una soluzione alternativa sta forzando il glibcriutilizzo di un socket per la ricerca dei record AAAAe A, aggiungendo una riga a /etc/resolv.conf:

options single-request-reopen

La vera causa di questo problema potrebbe essere:

Risposta lunga:

Programmi come curlo wgetusano la funzione getbdrinfo () di glibc , che cerca di essere compatibile sia con IPv4 che con IPv6 cercando entrambi i record DNS in parallelo. Non restituisce il risultato finché non vengono ricevuti entrambi i record (ci sono diversi problemi relativi a tale comportamento ) - questo spiega quanto stracesopra. Quando IPv4 è forzato, come curl -4internamente, gethostbyname()che richiede Asolo record.

Da tcpdumppossiamo vedere che:

  • -> A? all'inizio vengono inviate due richieste
  • -> AAAA? (richiesta indirizzo IPv6)
  • <- AAAA rispondere
  • -> A? richiedere nuovamente l'indirizzo IPv4
  • <- A ottenuto risposta
  • -> AAAA? richiedere nuovamente IPv6
  • <- AAAA rispondere

Una Arisposta viene eliminata per qualche motivo, questo è questo messaggio di errore:

error sending response: host unreachable

Eppure non mi è chiaro perché sia ​​necessaria una seconda AAAAquery.

Per verificare che stai riscontrando lo stesso problema, puoi aggiornare il timeout in /etc/resolv.conf:

options timeout:3

come descritto qui :

$ 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

Esistono altre due opzioni correlate in man resolv.conf:

richiesta singola (dal momento che glibc 2.10) set RES_SNGLKUP in _res.options. Per impostazione predefinita, glibc esegue ricerche IPv4 e IPv6 in parallelo dalla versione 2.9. Alcuni server DNS dell'appliance non sono in grado di gestire correttamente queste query e di far scadere le richieste. Questa opzione disabilita il comportamento e fa sì che glibc esegua sequenzialmente le richieste IPv6 e IPv4 (a scapito di un rallentamento del processo di risoluzione).

single-request-reopen (da glibc 2.9) Il resolver utilizza lo stesso socket per le richieste A e AAAA. Alcuni componenti hardware restituiscono erroneamente una sola risposta. Quando ciò accade, il sistema client siederà e attenderà la seconda risposta. L'attivazione di questa opzione modifica questo comportamento in modo tale che se due richieste dalla stessa porta non vengono gestite correttamente, chiuderà il socket e ne aprirà uno nuovo prima di inviare la seconda richiesta.

Problemi correlati:


@RuiFRibeiro Basandosi esclusivamente sugli up-volt sembrava che gli utenti trovassero l'altra risposta più utile. Senza offesa.
Tombart,

4

Come dice @Tombart, il ritardo è dovuto all'attesa del timeout di risoluzione IPv6.

Un altro possibile corso di azione è dare la precedenza a IPv4 in /etc/gai.conf

Dai commenti in /etc/gai.conf

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

Dopo la modifica gai.conf, è necessario riavviare qualsiasi app utilizzando la libreria del resolver DNS per rendere effettive le modifiche.

Tieni presente che se stai utilizzando un server BIND senza connettività IPv6, ti consiglio di disabilitare IPv6 namede di prendere dagli indirizzi IPv6 i suggerimenti di root. Ovviamente proverà comunque a risolvere gli indirizzi AAAA.

Quindi per la configurazione BIND,

In / etc / default / bind9, aggiungi -4 per gli indirizzi IPv4:

OPTIONS="-4 -u bind"

e in /etc/bind/db.root, eliminare tutte le righe con le radici DNS AAAA.


2

Ho avuto un problema simile durante l'utilizzo di BIND9. Per risolvere questo problema ho dovuto aggiungere:

filter-aaaa-on-v4 yes;

opzione per il mio named.conf.

( Ulteriori informazioni )

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.