As pesquisas de DNS às vezes levam 5 segundos

11

Eu tenho uma VM executando o Debian Wheezy na qual algumas pesquisas de nome de host levam alguns segundos para serem concluídas, mesmo que o resolvedor responda imediatamente. Estranhamente, pesquisas com getaddrinfo()são afetadas, mas gethostbyname()não são.

Eu mudei para os resolvedores do Google para excluir a possibilidade de que os locais sejam quebrados, então minha /etc/resolv.confaparência é:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

Meu nsswitch.conftem a linha:

hosts: files dns

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

Se eu tentar telnet webserver 80, ele trava por alguns segundos antes de obter uma resolução de nome. Uma ltracesaída [1] mostra que o travamento está em uma getaddrinfo()chamada:

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

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

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)

Verifiquei os logs do firewall do host e nada na porta 53 está sendo bloqueado.

O que está fazendo com que a primeira resposta DNS seja ignorada?

[1] Adicionei algumas linhas ao meu ltrace.confpara que eu possa ver dentro da addrinfoestrutura.

Flup
fonte
Como é a instalação da NIC da VM? Ponte? NAT?
Slm
É NATted. Não tenho certeza exatamente onde o NAT é aplicado (seja pelo ESX ou mais a montante); Eu posso descobrir se você acha que isso importa.
Flup
Eu suspeitaria que é o NAT + VM que está influenciando isso.
Slm
Poderia ser - veja meus comentários sobre a resposta de Kempniu abaixo.
Flup
Foi em rede, mas não especificamente NAT, causando isso - veja minha resposta abaixo.
Flup

Respostas:

13

A primeira resposta DNS não é ignorada. getaddrinfo()não retornou até receber a resposta para a primeira consulta AAAA (ID: 26090). Portanto, o problema real aqui é o motivo pelo qual sua máquina não recebeu imediatamente a resposta para a consulta AAAA, enquanto recebeu a resposta para a consulta A (ID: 54755).

Uma das diferenças entre getaddrinfo()e gethostbyname()é que o primeiro suporta IPv4 e IPv6, enquanto o último suporta apenas IPv4. Portanto, quando você liga getaddrinfo()com o ai_familyconjunto de 0 ( AF_UNSPEC), ele não retornará até obter uma resposta (ou atingir o tempo limite) para as consultas A e AAAA do nome de domínio fornecido. gethostbyname()apenas consultas para um registro A.

É difícil determinar remotamente o que pode estar causando seu problema, especialmente se você cortou alguma tcpdumpsaída. Algo pode estar filtrando / descartando seletivamente o tráfego DNS entre sua VM e os resolvedores de DNS público do Google. Tentei reproduzir seu problema usando uma VM KVM Debian Wheezy, mas telnet ifconfig.mequase imediatamente imprimi a Trying <IP_address_here>...linha (o que significa que ele já havia resolvido o nome até então).

Kempniu
fonte
Obrigado pela sua resposta detalhada. Não cortei nada do tcpdump, apenas inseri uma linha para deixar claro onde estava a pausa. Você definitivamente me deu algo para continuar; Não percebi a diferença significativa entre as duas chamadas da biblioteca.
Flup
Se não houver mais pacotes relacionados ao DNS em sua máquina, provavelmente algo está filtrando seu tráfego (não necessariamente de propósito). De qualquer forma, se você encontrar uma solução, por favor, compartilhe-a aqui?
Kempniu
1
Eu vou mesmo. Depois de configurar um resolvedor de teste, posso ver conclusivamente que um pacote de resposta - o da minha pergunta - é descartado toda vez. Suspeito que algo na infraestrutura VMware ou próximo a ele esteja fazendo isso, então entrei em contato com meu colega que cuida desse lado. Quando chegar ao fundo, voltarei e adicionarei detalhes. Obrigado novamente!
Flup
Solução adicionada em minha própria resposta. Muito obrigado mais uma vez por sua ajuda.
Flup
9

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

Eu construí um resolvedor de teste para poder ver os dois lados da conversa, e o pacote ausente identificado por Kempniu em sua excelente resposta estava sendo descartado em algum lugar ao longo do caminho. Conforme observado nessa resposta, getaddrinfo()sem uma família de endereços especificada, aguardamos respostas relacionadas a todas as famílias apoiadas antes de retornar (ou, no meu caso, atingir o tempo limite).

Meu colega que administra a rede observou que

O comportamento padrão no firewall do Juniper é fechar uma sessão relacionada ao DNS assim que uma resposta DNS correspondente a essa sessão for recebida.

Portanto, o firewall estava vendo a resposta do IPv4, observando que respondia à consulta da VM e fechando o caminho de entrada para essa porta. O pacote de resposta IPv6 a seguir foi descartado. Não sei por que os dois pacotes passaram pela segunda vez, mas a desativação desse recurso no firewall corrigiu o problema.

Este é um extrato relacionado do Juniper KB:

Aqui está um cenário em que os pacotes de resposta DNS são descartados:

  1. Uma sessão para o tráfego DNS é criada quando o primeiro pacote de consulta DNS atinge o firewall e há uma política de permissão configurada. O tempo limite padrão é 60 segundos.
  2. Imediatamente antes do encerramento da sessão, uma nova consulta DNS é transmitida e, uma vez que corresponde a uma sessão existente (como o par de porta / IP de origem e destino é sempre o mesmo), ela é encaminhada pelo firewall. Observe que o tempo limite da sessão não é atualizado de acordo com nenhum pacote recém-chegado.
  3. A sessão DNS criada está com o tempo esgotado quando a primeira resposta de consulta DNS (resposta) atinge o dispositivo, independentemente do tempo limite restante.
  4. Quando uma resposta DNS é passada pelo firewall, a sessão fica com o prazo de validade vencido.
  5. Todas as respostas DNS subseqüentes são eliminadas pelo firewall, pois não existe sessão.

Se você está pensando em votar esta resposta, por favor, também vote na resposta de Kempniu. Sem ele, eu ainda estaria tentando encontrar algum problema de configuração na VM.

Flup
fonte
1
Nós experimentamos os mesmos sintomas no Debian 8.2. A nossa era devido a uma causa diferente e a "solução" era diferente (do lado do cliente). Eu escrevi no blog sobre o nosso problema específico e o problema mais geral: philippecloutier.com/… Quero agradecer a Flup e Kempniu, pois suas perguntas e respostas me colocaram no caminho certo.
Philippe Cloutier