Como desativar as pesquisas AAAA?

35

... para compensar servidores DNS quebrados que estão fora de nosso controle.

Nosso problema: implantamos dispositivos incorporados que coletam dados do sensor em vários sites, principalmente apenas no IPv4. Alguns sites têm redes com manutenção insuficiente, por exemplo, caches DNS e / ou firewalls mal configurados ou quebrados, que ignoram completamente as consultas AAAA ou respondem a elas com respostas quebradas (por exemplo, IP de origem incorreto!). Como fornecedor externo do departamento de instalações, quase não temos influência nos departamentos de TI (às vezes relutantes). As chances de consertar seus servidores / firewalls DNS tão cedo são mínimas.

O efeito em nosso dispositivo é que, a cada gethostbyname (), os processos precisam aguardar o tempo limite das consultas AAAA; nesse momento, alguns processos já atingiram o tempo limite de suas tentativas de conexão.

Estou procurando soluções que sejam ...

  • sistema amplo. Não consigo reconfigurar dezenas de aplicativos individualmente
  • não permanente e configurável. Precisamos (re) habilitar o IPv6 onde / quando ele for corrigido / implementado. Reiniciar está OK.
  • Se uma solução exigir que uma biblioteca principal como o glibc seja substituída, o pacote da biblioteca de substituição deve estar disponível em um repositório conhecido por ser bem mantido (por exemplo, Debian Testing, Ubuntu universe, EPEL). Auto-construção não é uma opção por tantas razões que eu nem sei por onde começar, então simplesmente não as listo ...

A solução mais óbvia seria configurar a biblioteca do resolvedor, por exemplo, via / etc / { resolv , nsswitch , gai } .conf para não consultar registros AAAA. Uma opção resolv.conf no-inet6como sugerida aqui seria exatamente o que estou procurando. Infelizmente não está implementado, pelo menos não em nossos sistemas (libc6-2.13-38 + deb7u4 no Debian 7; libc6-2.19-0ubuntu6.3 no Ubuntu 14.04)

Então como então? Encontramos os seguintes métodos sugeridos no SF e em outros lugares, mas nenhum deles funciona:

  • Desabilitando completamente o IPv6, por exemplo, na lista negra do ipv6 LKM em /etc/modprobe.d/, ou sysctl -w net.ipv6.conf.all.disable_ipv6=1. ( Por curiosidade: por que o resolvedor está pedindo AAAA em que o IPv6 está desativado? )
  • Removendo options inet6do /etc/resolv.conf. Não estava lá em primeiro lugar, inet6é simplesmente ativado por padrão hoje em dia.
  • Configurando options single-requestem /etc/resolv.conf. Isso garante apenas que as consultas A e AAAA sejam feitas seqüencialmente e não em paralelo
  • Mudando precedenceno /etc/gai.conf. Isso não afeta as consultas DNS, apenas como várias respostas são processadas.
  • Usar resolvedores externos (ou executar um daemon de resolução local que contorna os servidores DNS quebrados) ajudaria, mas geralmente não é permitido pelas políticas de firewall da empresa. E isso pode tornar os recursos internos inacessíveis.

Idéias feias alternativas:

  • Execute um cache DNS no host local. Configure-o para encaminhar todas as consultas que não sejam AAAA, mas para responder às consultas AAAA com NOERROR ou NXDOMAIN (dependendo do resultado da consulta A correspondente). Não estou ciente de um cache DNS capaz de fazer isso.
  • Use alguma combinação inteligente de iptables u32 ou o módulo DNS de Ondrej Caletka para corresponder às consultas AAAA, para rejeitá-las pelo icmp (como a lib do resolvedor reagiria a isso?) Ou para redirecioná-las para um servidor DNS local que responda a tudo com um NOERROR vazio.

Observe que existem perguntas semelhantes e relacionadas no SE. Minha pergunta difere na medida em que elabora o problema real que estou tentando resolver, uma vez que lista requisitos explícitos, pois lista negativamente algumas soluções não funcionais frequentemente sugeridas e não é específica para um único aplicativo. Após essa discussão , postei minha pergunta.

Nils Toedtmann
fonte
13
PS: Ao contrário da crença popular aqui no SF, existem algumas boas razões para desativar o IPv6 / AAAA em uma máquina em uma rede somente IPv4, mesmo onde o DNS funciona: Reduza a carga de transmissão; Reduza a carga nos resolvedores de DNS em quase 50%; Reduzir o tempo de inicialização da conexão (significativamente quando os caches do DNS estão atrasados); Siga as práticas recomendadas para desativar os recursos não funcionais para aprimorar a segurança e a estabilidade. É certo que, se eu esquecer de reativar o IPv6 assim que estiver disponível, meu sistema se tornará um reator herdado de IPv4 que impedirá a implementação do IPv6. Deve-se permitir pesar os profissionais listados contra esse golpe.
Nils Toedtmann 01/10/14
Alguma razão para você não executar um resolvedor completo no host local? Dessa forma, você elimina completamente a dependência dos resolvedores de DNS não-confiáveis ​​de outras pessoas.
Sander Steffann
As políticas de firewall da @SanderSteffann Company geralmente não permitem isso. Mas em outros lugares isso é uma opção. Vou adicioná-lo à minha pergunta mais tarde.
Nils Toedtmann 01/10/14
3
@joeqwerty Não estamos assumindo se o IPv6 é ou não suportado no site. No entanto, assumimos que os servidores DNS são compatíveis com os padrões. Além disso, infelizmente alguns departamentos de TI não possuem as habilidades necessárias para configurar sua infraestrutura adequadamente. Desculpe por ser franco sobre isso.
Nils Toedtmann
4
Eu entendo o que você está dizendo. Você precisa fazer sua caixa funcionar na rede deles e não o contrário, e é sobre isso que você está perguntando aqui. Eu fico um pouco irritado quando nós, na área de TI, culpamos nossos clientes e não os respeitamos. Eles são o nosso pão e manteiga. Para o bem ou para o mal, precisamos respeitar isso e respeitá-los. Nossos clientes não são um obstáculo ao nosso negócio, eles são a razão do nosso negócio.
Joeqwerty

Respostas:

9

Pare de usar gethostbyname(). Você deveria estar usando getaddrinfo(), e deveria ter sido por anos agora. A página do manual até avisa sobre isso.

As funções gethostbyname * (), gethostbyaddr * (), herror () e hstrerror () estão obsoletas. Os aplicativos devem usar getaddrinfo (3), getnameinfo (3) e gai_strerror (3).

Aqui está um exemplo de programa rápido em C que demonstra a busca apenas de registros A para um nome e uma captura do Wireshark mostrando que apenas as pesquisas de registro A foram feitas na rede.

Em particular, você precisa conjunto ai_familypara AF_INETse você quiser apenas uma pesquisas recordes feitas. Este programa de amostra imprime apenas os endereços IP retornados. Consulte a getaddrinfo()página do manual para obter um exemplo mais completo de como fazer conexões de saída.

Na captura do Wireshark , 172.25.50.3 é o resolvedor de DNS local; a captura foi feita lá, para que você também veja suas consultas e respostas de saída. Observe que apenas um registro A foi solicitado. Nenhuma pesquisa AAAA foi feita.

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>

int main(void) {
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int s;
    char host[256];

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;

    s = getaddrinfo("www.facebook.com", NULL, &hints, &result);
    if (s != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        exit(EXIT_FAILURE);
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
        printf("%s\n", host);
    }
    freeaddrinfo(result);
}
Michael Hampton
fonte
Interessante! Investigarei quais aplicativos acionam solicitações AAAA. Se é apenas nosso, então eu retransmitirei sua sugestão para nossos desenvolvedores. Mas tenho um forte pressentimento de que muitos softwares empacotados pelo Debian / Ubuntu estão sofrendo com isso, e não vamos corrigi-los.
Nils Toedtmann
Sua aplicação é provavelmente a mais importante. Mesmo se você não conseguir consertar todo o resto, isso pode melhorar a situação.
Michael Hampton
4

Em caso de dúvida, vá para o código fonte! Então, vamos ver ... gethostbyname () parece interessante; que descreve exatamente o que estamos vendo: tente o IPv6 primeiro e depois volte ao IPv4 se você não obtiver a resposta que deseja. O que é essa RES_USE_INET6bandeira? Rastreando de volta, é proveniente de res_setoptions () . É aqui que resolv.confé lido.

E .... esse sou eu sem idéias. Não sei ao certo como RES_USE_INET6está sendo definido, se não estiver resolv.conf.

BMDan
fonte
RES_USE_INET6 pode ser definido via options inet6in resolv.conf. Acho que meu problema é que ele não pode ser desabilitado depois de definido em tempo de compilação, o que todas as principais distribuições parecem fazer atualmente (correto?). Portanto, o pedido de recurso para o options no_inet6que eu mencionei acima.
Nils Toedtmann
1
Infelizmente, como você pode ver no código, não parece haver uma no_inet6opção no res_setoptions(). No entanto, como você pode ver em (não) ip6-dotint, é uma alteração fácil de adicionar. Para testar a teoria de que ele está sendo definido por padrão pela sua distribuição, pegue os arquivos de origem do pacote e o compile uma vez "virgem" (para confirmar que o pacote replica o comportamento) e depois adicione: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },ao options[]array e veja se o O problema desaparece quando você define essa opção resolv.conf.
BMDan
1
Por fim: quanto vale a pena, eu resolveria isso executando um cache DNS no localhost (como você mencionou acima). Seria muito mais fácil manter seu próprio proxy / cache DNS invadido do que manter uma versão invadida de uma biblioteca principal do sistema.
BMDan
3

Você pode usar o BIND como um resolvedor local, ele tem uma opção para filtrar o AAAA:

https://kb.isc.org/article/AA-00576/0/Filter-AAAA-option-in-BIND-9-.html

Robert Kerr
fonte
2
Isso é bastante pesado para um dispositivo incorporado.
Michael Hampton
Obrigado, eu não estava ciente do filtro AAAA do Bind. Como Michael menciona, provavelmente não é uma solução para nós devido à grande presença de Bind. Mas para aqueles que desejam filtrar respostas AAAA em outros cenários, pode ser uma maneira viável. O Ubuntu realmente cria bind com "--enable-filter-aaaa", pelo menos no 14.04. Não tenho certeza sobre o Debian. - Veja também ipamworldwide.blogspot.co.uk/2011/09/…
Nils Toedtmann
1
Estou no 14.04 e parece que esta opção de filtragem não está disponível.
Zitrax 06/04
0

Você tentou configurar o PDNS-recursor, configurá-lo no seu /etc/resolv.conf e negar pesquisas "AAAA" nele? Usando algo comoquery-local-address6=

Glueon
fonte
1
query-local-address6=faz algo diferente (de qual endereço IPv6 o qual enviar consultas - observe que, mesmo com o IPv6 desativado, as solicitações AAAA ainda serão resolvidas via IPv4). Também não consigo identificar nenhuma outra configuração que filtre as consultas AAAA ( doc.powerdns.com/html/built-in-recursor.html ). Sem essa informação, a sua resposta não é muito útil :(
Nils Toedtmann