Como desabilitar as pesquisas AAAA?

33

... para compensar servidores DNS corrompidos que estão fora do nosso controle.

Nosso problema: implantamos dispositivos incorporados que coletam dados do sensor em vários sites, principalmente somente IPv4. Alguns sites têm redes mal conservadas, por ex. cache DNS mal configurado ou de outra forma quebrado e / ou firewalls que ignoram as consultas AAAA ou respondem a elas com respostas quebradas (por exemplo, IP de origem incorreta!). Como um fornecedor externo para o departamento de instalações, não temos quase nenhuma influência sobre os departamentos de TI (algumas vezes relutantes). As chances de eles consertarem seus servidores DNS / firewalls em algum momento são minúsculas.

O efeito em nosso dispositivo é que, com cada gethostbyname (), os processos precisam aguardar até que as consultas AAAA atinjam o tempo limite, quando alguns processos já atingiram as tentativas de conexão.

Estou procurando soluções que sejam ...

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

A solução mais óbvia seria configurar a biblioteca de resolvedor, e. via / etc / { resolver , nsswitch , gai }. conf para não consultar registros AAAA. Uma opção resolv.conf no-inet6 como sugerido aqui seria exatamente Estou à procura de. Infelizmente ele 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? Encontramos os seguintes métodos sugeridos no SF e em outros lugares, mas nenhum deles funciona:

  • Desativando o IPv6 completamente, por exemplo por meio da 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á solicitando AAAA onde o IPv6 está desativado? )
  • Removendo options inet6 do /etc/resolv.conf. Não foi lá, em primeiro lugar, inet6 é simplesmente ativado por padrão nos dias de hoje.
  • Definindo options single-request em /etc/resolv.conf. Isso garante apenas que as consultas A e AAAA sejam feitas sequencialmente, em vez de em paralelo
  • Alterando precedence no /etc/gai.conf. Isso não afeta as consultas do DNS, apenas como várias respostas são processadas.
  • O uso de resolvedores externos (ou a execução de um daemon de resolvedor local que contorne os servidores DNS corrompidos) ajudaria, mas geralmente não é permitido pelas diretivas de firewall da empresa. E isso pode tornar os recursos internos inacessíveis.

Idéias alternativas e feias:

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

Observe que há perguntas relacionadas semelhantes sobre SE. Minha pergunta difere na medida em que elabora o problema real que estou tentando resolver, já que lista requisitos explícitos, já que lista algumas soluções não úteis frequentemente sugeridas, e como não é específico para um único aplicativo. Depois desta discussão , publiquei a minha pergunta.

por Nils Toedtmann 01.10.2014 / 11:03

4 respostas

8

Pare de usar gethostbyname() . Você deveria estar usando getaddrinfo() , e deveria ter sido por anos agora. A página man ainda te avisa disso.

The gethostbyname*(), gethostbyaddr*(), herror(), and hstrerror() functions are obsolete. Applications should use getaddrinfo(3), getnameinfo(3), and gai_strerror(3) instead.

Aqui está um programa de amostra rápido em C que demonstra a procura apenas de registros para um nome, e uma captura Wireshark mostrando que somente Um registro de pesquisas passou pela rede .

Em particular, você precisa definir ai_family a AF_INET se desejar apenas uma pesquisa de registros. Este programa de amostra apenas imprime os endereços IP retornados. Veja a página getaddrinfo() man para um exemplo mais completo de como fazer conexões de saída.

Na captura do Wireshark , o 172.25.50.3 é o resolvedor de DNS local; a captura foi feita lá, então você também vê suas consultas e respostas de saída. Note 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);
}
    
por 25.07.2015 / 19:34
3

Em caso de dúvida, dirija-se ao código-fonte! Então, vamos ver ... gethostbyname () parece interessante; que descreve exatamente o que estamos vendo: tente o IPv6 primeiro e, em seguida, retorne ao IPv4 se você não obtiver uma resposta que goste. O que é isso RES_USE_INET6 flag? Traçando de volta, está vindo de res_setoptions () . É aqui que resolv.conf é lido.

E .... essa sou eu sem idéias. Eu não sei ao certo como é que RES_USE_INET6 está sendo definido se não estiver em resolv.conf .

    
por 02.10.2014 / 22:40
3

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

link

    
por 25.07.2015 / 23:09
0

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

    
por 02.10.2014 / 12:22