Назад | Перейти на главную страницу

Как отключить поиск AAAA?

... чтобы компенсировать неисправность DNS-серверов, находящихся вне нашего контроля.

Наша проблема: мы развертываем встроенные устройства, которые собирают данные датчиков на различных сайтах, в основном поддерживающих только IPv4. Некоторые сайты имеют плохо обслуживаемые сети, например неправильно настроенные или иным образом сломанные кеши DNS и / или брандмауэры, которые либо полностью игнорируют запросы AAAA, либо отвечают на них неверными ответами (например, неправильный IP-адрес источника!). Как внешний поставщик для отдела оборудования, мы практически не имеем влияния на ИТ-отделы (иногда неохотно). Шансы на то, что они исправят свои DNS-серверы / брандмауэры в ближайшее время, ничтожны.

Эффект на нашем устройстве заключается в том, что с каждым gethostbyname () процессы должны ждать, пока не истечет время ожидания запросов AAAA, и в этот момент некоторые процессы уже полностью отключили свои попытки подключения.

Я ищу решения, которые ...

Наиболее очевидным решением было бы настроить библиотеку преобразователя, например. через / etc / {разрешить,nsswitch,гаи} .conf, чтобы не запрашивать записи AAAA. Параметр resolv.conf no-inet6 как было предложено Вот было бы именно то, что я ищу. К сожалению, это не реализовано, по крайней мере, в наших системах (libc6-2.13-38 + deb7u4 в Debian 7; libc6-2.19-0ubuntu6.3 в Ubuntu 14.04)

Так как же тогда? Можно найти следующие методы, предложенные в SF и других источниках, но ни один из них не работает:

Альтернативные уродливые идеи:


Обратите внимание, что есть похожие вопросы по SE. Мой вопрос отличается постольку, поскольку он описывает реальную проблему, которую я пытаюсь решить, поскольку в нем перечислены явные требования, поскольку он заносит в черный список некоторые часто предлагаемые неработающие решения и поскольку он не относится к одному приложению. Следующий это обсуждение, Я разместил свой вопрос.

Прекратить использовать gethostbyname(). Вы должны использовать getaddrinfo() вместо этого, и должно было быть в течение многих лет. Страница руководства даже предупреждает вас об этом.

Функции gethostbyname * (), gethostbyaddr * (), herror () и hstrerror () устарели. Вместо этого приложения должны использовать getaddrinfo (3), getnameinfo (3) и gai_strerror (3).

Вот небольшой пример программы на C, демонстрирующий поиск только Записи для имени и снимок Wireshark, показывающий, что только Поиск записей прошел по сети.

В частности, вам нужно установить ai_family к AF_INET если вам нужен только поиск A-записи. Этот пример программы печатает только возвращенные IP-адреса. Увидеть getaddrinfo() справочную страницу для более полного примера того, как устанавливать исходящие соединения.

в Wireshark захват, 172.25.50.3 - локальный преобразователь DNS; захват был сделан там, поэтому вы также видите его исходящие запросы и ответы. Обратите внимание, что только Запрошена запись A. Поиск 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);
}

В случае сомнений обращайтесь к исходному коду! Итак, посмотрим ... gethostbyname () выглядит интересно; это точно описывает то, что мы наблюдаем: сначала попробуйте IPv6, а затем вернитесь к IPv4, если вы не получите ответа, который вам нравится. Что это RES_USE_INET6 флаг? Отслеживая его, он исходит от res_setoptions (). Это где resolv.conf читается в.

И .... это у меня нет идей. Я совершенно не понимаю, как это RES_USE_INET6 устанавливается, если не в resolv.conf.

Вы можете использовать BIND как локальный преобразователь, у него есть возможность фильтровать AAAA:

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

Вы пытались установить PDNS-рекурсор, установить его в /etc/resolv.conf и запретить в нем поиск "AAAA"? Используя что-то вроде query-local-address6=