as pesquisas de DNS às vezes demoram 5 segundos

10

Eu tenho uma VM rodando o Debian Wheezy no qual algumas pesquisas de nomes de host levam vários segundos para serem concluídas, mesmo que o resolvedor responda imediatamente. Estranhamente, as pesquisas com getaddrinfo() são afetadas, mas gethostbyname() não é.

Eu mudei para os resolvedores do Google para excluir a possibilidade de que os locais sejam quebrados, então meu /etc/resolv.conf se parece com:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

Meu nsswitch.conf tem a linha:

hosts: files dns

e meu /etc/hosts não contém nada incomum.

Se eu tentar telnet webserver 80 , ele fica pendurado por vários segundos antes de obter uma resolução de nome. Um ltrace output [1] mostra que o travamento está em uma chamada getaddrinfo() :

getaddrinfo("ifconfig.me", "telnet", { AI_CANONNAME, 0, SOCK_STREAM, 0, 0, NULL, '
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)
0', NULL }, 0x7fffb4ffc160) = 0 <5.020621>

No entanto, tcpdump revela que o servidor de nomes respondeu imediatamente, e foi apenas na segunda resposta que telnet desbloqueou. As respostas parecem idênticas:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

Eu verifiquei os logs de firewall do host e nada na porta 53 está sendo bloqueado.

O que está causando a primeira resposta de DNS a ser ignorada?

[1] Eu adicionei algumas linhas ao meu ltrace.conf para que eu possa ver dentro do addrinfo struct.

    
por Flup 07.07.2014 / 14:55

2 respostas

8

Isso foi causado por um conjunto de regras excessivamente restritivo em um firewall da Juniper que fica em frente à infraestrutura VMware.

Eu construí um resolvedor de teste para que eu pudesse ver os dois lados da conversa, e o pacote ausente identificado por Kempniu em sua excelente resposta estava de fato sendo lançado em algum lugar ao longo do caminho. Conforme observado nessa resposta, getaddrinfo() sem nenhuma família de endereços especificada aguardará respostas relativas a todas famílias suportadas antes de retornar (ou, no meu caso, expirar).

Meu colega que gerencia a rede observou que

The default behavior on the Juniper firewall is to close a DNS-related session as soon as a DNS reply matching that session is received.

Assim, o firewall estava vendo a resposta do IPv4, observando que ela respondeu à consulta da VM e fechando o caminho de entrada dessa porta. O seguinte pacote de resposta IPv6 foi descartado. Não faço ideia de porque os dois pacotes passaram pela segunda vez, mas a desativação desse recurso no firewall resolveu o problema.

Este é um extrato relacionado do KB do Juniper:

Here's a scenario where DNS Reply packets are dropped:

  1. A session for DNS traffic is created when the first DNS query packet hits the firewall and there is a permitting policy configured. The default timeout is 60 sec.
  2. Immediately before the session is closed, a new DNS query is transmitted, and since it matches an existing session (since source and destination port/IP pair is always the same), it is forwarded by the firewall. Note that the session timeout is not refreshed according to any newly arriving packet.
  3. The created DNS session is aged out when the first DNS query response (reply) hits the device, regardless how much the timeout remains.
  4. When a DNS reply is passed through the firewall, the session is aged out.
  5. All subsequent DNS replies are dropped by the firewall, since no session exists.

Se você está pensando em avaliar esta resposta, por favor também revele a resposta de Kempniu. Sem isso eu ainda estaria se debatendo tentando encontrar algum problema de configuração na VM.

    
por 08.07.2014 / 09:15
12

A primeira resposta de DNS não é ignorada. getaddrinfo() não retornou até receber a resposta à primeira consulta AAAA (ID: 26090). Portanto, o verdadeiro problema aqui é por que sua máquina não recebeu imediatamente a resposta à consulta AAAA, enquanto recebeu a resposta para a consulta A (ID: 54755).

Uma das diferenças entre getaddrinfo() e gethostbyname() é que a primeira suporta IPv4 e IPv6, enquanto a última suporta apenas IPv4. Portanto, quando você chamar getaddrinfo() com ai_family definido como 0 ( AF_UNSPEC ), ele não retornará até obter uma resposta (ou atingir um tempo limite) para ambas consultas A e AAAA o nome de domínio fornecido. gethostbyname() apenas consulta um registro A.

É difícil determinar remotamente o que pode estar causando o seu problema, especialmente quando você cortou a saída tcpdump . Algo pode estar filtrando / eliminando seletivamente o tráfego de DNS entre sua VM e os resolvedores de DNS público do Google. Eu tentei reproduzir o seu problema usando uma VM KVM Debian Wheezy, mas telnet ifconfig.me quase imediatamente imprimiu a linha Trying <IP_address_here>... (o que significa que já resolveu o nome até lá).

    
por 07.07.2014 / 15:58

Tags