¿Cómo deshabilitar las búsquedas AAAA?

35

... para compensar los servidores DNS rotos que están fuera de nuestro control.

Nuestro problema: implementamos dispositivos integrados que recopilan datos de sensores en varios sitios, principalmente IPv4. Algunos sitios tienen redes mal mantenidas, por ejemplo, cachés DNS o firewalls mal configurados o rotos que ignoran las consultas AAAA por completo o responden a ellas con respuestas rotas (¡por ejemplo, IP de fuente incorrecta!). Como proveedor externo del departamento de instalaciones, casi no tenemos influencia en los departamentos de TI (a veces reacios). Las posibilidades de que arreglen sus servidores / firewalls DNS en el corto plazo son mínimas.

El efecto en nuestro dispositivo es que con cada gethostbyname (), los procesos tienen que esperar hasta que se agote el tiempo de espera de las consultas AAAA, momento en el que algunos procesos ya han agotado por completo sus intentos de conexión.

Estoy buscando soluciones que sean ...

  • todo el sistema No puedo reconfigurar docenas de aplicaciones individualmente
  • no permanente y configurable. Necesitamos (re) habilitar IPv6 donde / cuando se arregla / implementa. Reiniciar está bien.
  • Si una solución requiere que se reemplace una biblioteca central como glibc, el paquete de la biblioteca de reemplazo debe estar disponible en un repositorio conocido por estar bien mantenido (por ejemplo, Debian Testing, Ubuntu universe, EPEL). La autoconstrucción no es una opción por tantas razones que ni siquiera sé por dónde empezar, así que simplemente no las enumero en absoluto ...

La solución más obvia sería configurar la biblioteca de resolución, por ejemplo, a través de / etc / { resolv , nsswitch , gai } .conf para no consultar registros AAAA. Una opción resolv.conf no-inet6como se sugiere aquí sería exactamente lo que estoy buscando. Desafortunadamente no está implementado, al menos no en nuestros sistemas (libc6-2.13-38 + deb7u4 en Debian 7; libc6-2.19-0ubuntu6.3 en Ubuntu 14.04)

Entonces, ¿cómo entonces? Uno encuentra los siguientes métodos sugeridos en SF y en otros lugares, pero ninguno de ellos funciona:

  • Deshabilitar por completo IPv6, por ejemplo, mediante la inclusión en la lista negra del Lvm ipv6 en /etc/modprobe.d/, o sysctl -w net.ipv6.conf.all.disable_ipv6=1. ( Por curiosidad: ¿por qué el solucionador solicita AAAA cuando IPv6 está desactivado? )
  • Eliminando options inet6de /etc/resolv.conf. En primer lugar, no estaba allí, inet6simplemente está habilitado de forma predeterminada en estos días.
  • Configuración options single-requesten /etc/resolv.conf. Esto solo asegura que las consultas A y AAAA se realicen secuencialmente en lugar de en paralelo.
  • Cambiando precedenceen /etc/gai.conf. Eso no afecta las consultas DNS, solo cómo se procesan las respuestas múltiples.
  • El uso de solucionadores externos (o la ejecución de un demonio de resolución local que eluda los servidores DNS dañados) ayudaría, pero generalmente no está permitido por las políticas de firewall de la compañía. Y puede hacer que los recursos internos sean inaccesibles.

Ideas feas alternativas:

  • Ejecute un caché DNS en localhost. Configúrelo para reenviar todas las consultas que no sean AAAA, pero para responder a las consultas AAAA con NOERROR o NXDOMAIN (dependiendo del resultado de la consulta A correspondiente). Sin embargo, no conozco un caché DNS capaz de hacer esto.
  • Utilice alguna coincidencia inteligente de iptables u32, o el módulo DNS de iptables de Ondrej Caletka para que coincida con las consultas AAAA, a fin de rechazarlas por icmp (¿cómo reaccionaría el lib de resolución a eso?), O redirigirlas a un servidor DNS local que responda a todo con un NOERROR vacío.

Tenga en cuenta que hay preguntas similares relacionadas con SE. Mi pregunta difiere en la medida en que elabora el problema real que estoy tratando de resolver, ya que enumera los requisitos explícitos, ya que incluye en la lista negra algunas soluciones no operativas sugeridas a menudo, y como no es específico de una sola aplicación. Después de esta discusión , publiqué mi pregunta.

Nils Toedtmann
fuente
13
PD: Contrariamente a la creencia popular aquí en SF, hay algunas buenas razones para deshabilitar IPv6 / AAAA en una máquina en una red solo IPv4, incluso donde DNS funciona: reducir la carga de transmisión; Reduzca la carga en los solucionadores de DNS en casi un 50%; Reduzca los tiempos de inicio de la conexión (significativamente donde los cachés de DNS son retrasados) Siga las mejores prácticas para deshabilitar las funciones no funcionales para mejorar la seguridad y la estabilidad. Es cierto que si olvido volver a habilitar IPv6 una vez que esté disponible, entonces mi sistema se convierte en un lastre heredado IPv4 que impide el despliegue de IPv6. Debería permitirse sopesar los pros enumerados contra esta estafa.
Nils Toedtmann
¿Alguna razón por la que no ejecutas un resolutor completo en localhost? De esa forma, eliminas la dependencia de los solucionadores de DNS de otras personas (aparentemente) poco confiables.
Sander Steffann
Las políticas de firewall de @SanderSteffann Company generalmente no lo permiten. Pero en otra parte eso es una opción. Lo agregaré a mi pregunta más tarde.
Nils Toedtmann
3
@joeqwerty No estamos haciendo suposiciones sobre si IPv6 es compatible o no en el sitio. Sin embargo, suponemos que los servidores DNS son compatibles con el estándar. Además, algunos departamentos de TI lamentablemente hacerlo carecen de los conocimientos necesarios para configurar correctamente su infraestructura. Perdón por ser franco al respecto.
Nils Toedtmann
44
Entiendo lo que dices. Debe hacer que su caja funcione en su red, no al revés, y eso es lo que está preguntando aquí. Simplemente me molesto un poco cuando en el campo de TI culpamos a nuestros clientes y no los respetamos. Son nuestro pan y mantequilla. Para bien o para mal, debemos respetar eso y respetarlos. Nuestros clientes no son un obstáculo para nuestro negocio, son la razón de nuestro negocio.
joeqwerty

Respuestas:

9

Deja de usar gethostbyname(). Debería usarlo en su getaddrinfo()lugar, y debería haberlo hecho durante años. La página del manual incluso te advierte de esto.

Las funciones gethostbyname * (), gethostbyaddr * (), herror () y hstrerror () están obsoletas. Las aplicaciones deben usar getaddrinfo (3), getnameinfo (3) y gai_strerror (3) en su lugar.

Aquí hay un programa de muestra rápida en C que muestra cómo buscar solo registros A para un nombre, y una captura de Wireshark que muestra que solo las búsquedas de registros A pasaron por la red.

En particular, es necesario conjunto ai_familyde AF_INETsi sólo desea una búsquedas de registros realizados. Este programa de muestra solo imprime las direcciones IP devueltas. Consulte la getaddrinfo()página del manual para obtener un ejemplo más completo de cómo hacer conexiones salientes.

En la captura de Wireshark , 172.25.50.3 es el solucionador de DNS local; la captura se realizó allí, por lo que también verá sus consultas y respuestas salientes. Tenga en cuenta que solo se solicitó un registro A. No se realizó ninguna búsqueda AAAA.

#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
fuente
¡Interesante! Investigaré qué aplicaciones generan solicitudes AAAA. Si es solo nuestro, entonces transmitiré su sugerencia a nuestros desarrolladores. Pero tengo el presentimiento de que gran parte del software empaquetado de Debian / Ubuntu está sufriendo esto, y no vamos a parchearlos.
Nils Toedtmann
Su aplicación es probablemente la más importante. Incluso si no puede arreglar todo lo demás, puede mejorar la situación.
Michael Hampton
4

En caso de duda, dirígete al código fuente. Entonces, veamos ... gethostbyname () parece interesante; eso describe exactamente lo que estamos viendo: primero intente con IPv6, luego recurra a IPv4 si no obtiene la respuesta que desea. ¿Qué es esta RES_USE_INET6bandera? Al rastrearlo, proviene de res_setoptions () . Aquí es donde resolv.confse lee.

Y ... ese soy yo sin ideas. No estoy completamente claro cómo se está RES_USE_INET6configurando si no está dentro resolv.conf.

BMDan
fuente
RES_USE_INET6 se puede configurar a través de options inet6in resolv.conf. Supongo que mi problema es que no se puede desarmar una vez que se configuró en tiempo de compilación, lo que todas las principales distribuciones parecen hacer en estos días (¿correcto?). Por lo tanto, la solicitud de características options no_inet6que mencioné anteriormente.
Nils Toedtmann
1
Desafortunadamente, como puede ver en el código, no parece haber un no_inet6 opción en res_setoptions(). Sin embargo, como puede ver en (no) ip6-dotint, es un cambio fácil de agregar. Para probar la teoría de que su distribución está configurada de manera predeterminada, tomaría los archivos fuente del paquete y lo compilaría una vez "virgen" (para confirmar que el paquete replica el comportamiento) y luego agregaría: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },a la options[]matriz y ver si El problema desaparece cuando configura esa opción resolv.conf.
BMDan
1
Por último: para lo que vale, resolvería esto ejecutando un caché DNS en localhost (como referencia, más arriba). Sería mucho más fácil mantener su propio proxy / caché de DNS pirateado de lo que sería mantener una versión pirateada de una biblioteca de sistema central.
BMDan
3

Puede usar BIND como un solucionador local, tiene una opción para filtrar AAAA:

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

Robert Kerr
fuente
2
Eso es bastante pesado para un dispositivo integrado.
Michael Hampton
Gracias, no estaba al tanto del filtro AAAA de Bind. Como Michael menciona, probablemente no sea una solución para nosotros debido a la gran huella de Bind. Pero para aquellos que desean filtrar las respuestas AAAA en otros escenarios, podría ser una forma viable. Ubuntu realmente construye enlaces con "--enable-filter-aaaa", al menos en 14.04. No estoy seguro acerca de Debian. - Ver también ipamworldwide.blogspot.co.uk/2011/09/…
Nils Toedtmann
1
Estoy en 14.04 y no parece que esta opción de filtrado esté disponible.
Zitrax
0

¿Intentó configurar PDNS-recursor, configurarlo en su /etc/resolv.conf y negar las búsquedas "AAAA" en él? Usando algo comoquery-local-address6=

Glueon
fuente
1
query-local-address6=hace algo diferente (desde qué dirección IPv6 enviar consultas; tenga en cuenta que incluso con IPv6 deshabilitado, las solicitudes AAAA se resolverán a través de IPv4). Además, no puedo identificar ninguna otra configuración que filtre las consultas AAAA ( doc.powerdns.com/html/built-in-recursor.html ). Sin esa información, su respuesta no es muy útil :(
Nils Toedtmann