fragen stichworte

Wie kann man AAAA-Lookups deaktivieren?

... um defekte DNS-Server zu kompensieren, die außerhalb unserer Kontrolle liegen.

Unser Problem: Wir implementieren eingebettete Geräte, die Sensordaten an verschiedenen, meist nur IPv4-Standorten sammeln. Einige Standorte verfügen über schlecht gewartete Netzwerke, z. falsch konfigurierte oder anderweitig defekte DNS-Caches und/oder Firewalls, die AAAA-Abfragen entweder vollständig ignorieren oder mit defekten Antworten darauf antworten (z. B. falsche Quell-IP!). Als externer Lieferant der Anlagenabteilung haben wir so gut wie keinen Einfluss auf die (manchmal zögerlichen) IT-Abteilungen. Die Wahrscheinlichkeit, dass sie ihre DNS-Server/Firewalls in absehbarer Zeit reparieren, ist gering.

Der Effekt auf unserem Gerät ist, dass die Prozesse mit jedem gethostbyname () warten müssen, bis die AAAA-Abfragen das Zeitlimit überschreiten. Zu diesem Zeitpunkt haben einige Prozesse ihre Verbindungsversuche bereits vollständig abgebrochen.

Ich suche nach Lösungen, die ...

sind
  • systemweit. Ich kann Dutzende von Anwendungen nicht einzeln neu konfigurieren.
  • nicht permanent und konfigurierbar. Wir müssen IPv6 (wieder) aktivieren, wo/wann es behoben/ausgerollt wird. Neustart ist in Ordnung.
  • Wenn für eine Lösung eine Kernbibliothek wie glibc ersetzt werden muss, sollte das Ersatzbibliothekpaket aus einem bekanntermaßen zu verwaltenden Repository (z. B. Debian Testing, Ubuntu-Universum, EPEL) verfügbar sein. Selbstaufbau ist aus so vielen Gründen keine Option, dass ich nicht einmal weiß, wo ich anfangen soll, also liste ich sie überhaupt nicht auf ...

Die naheliegendste Lösung wäre die Konfiguration der Resolver-Bibliothek, z. über/etc/{resolv, nsswitch, gai} .conf, um AAAA-Datensätze nicht abzufragen. Eine resolv.conf-Option no-inet6 wie vorgeschlagen hier wäre genau was ich suche. Leider ist es nicht implementiert, zumindest nicht auf unseren Systemen (libc6-2.13-38 + deb7u4 unter Debian 7; libc6-2.19-0ubuntu6.3 unter Ubuntu 14.04)

Wie dann? Man findet die folgenden auf SF und anderswo vorgeschlagenen Methoden, aber keine davon funktioniert:

  • Deaktivieren von IPv6 insgesamt, z. durch Blacklisting des IPv6-LKM in/etc/modprobe.d/oder sysctl -w net.ipv6.conf.all.disable_ipv6=1. (Aus Neugier: Warum fragt der Resolver nach AAAA, wenn IPv6 deaktiviert ist?)
  • Entfernen von options inet6 aus der Datei/etc/resolv.conf Es war überhaupt nicht da, inet6 ist heutzutage einfach standardmäßig aktiviert.
  • Einstellung von options single-request in/etc/resolv.conf Dies stellt nur sicher, dass die A- und AAAA-Abfragen sequentiell und nicht parallel ausgeführt werden
  • Ändern von precedence in/etc/gai.conf Dies wirkt sich nicht auf die DNS-Abfragen aus, sondern nur darauf, wie mehrere Antworten verarbeitet werden.
  • Die Verwendung externer Auflöser (oder Ausführen eines lokalen Auflösungsdämons, der die defekten DNS-Server umgeht) würde helfen, wird jedoch normalerweise von den Firewall-Richtlinien des Unternehmens nicht unterstützt. Und es kann interne Ressourcen unzugänglich machen.

Alternative hässliche Ideen:

  • Führen Sie einen DNS-Cache für localhost aus. Konfigurieren Sie es, um alle Nicht-AAAA-Abfragen weiterzuleiten, aber auf AAAA-Abfragen entweder mit NOERROR oder NXDOMAIN zu antworten (abhängig vom Ergebnis der entsprechenden A-Abfrage). Mir ist jedoch kein DNS-Cache bekannt, der dazu in der Lage ist.
  • Verwenden Sie einige clevere iptables u32-Übereinstimmungen oder das iptables-DNS-Modul von Ondrej Caletka, um AAAA-Abfragen zuzuordnen, um sie entweder von icmp zurückzuweisen (wie würde die Resolver-Bibliothek darauf reagieren?) oder umzuleiten Sie an einen lokalen DNS-Server, der mit einem leeren NOERROR auf alles reagiert.

Beachten Sie, dass es ähnliche, verwandte Fragen zu SE gibt. Meine Frage unterscheidet sich insofern, als sie das eigentliche Problem ausarbeitet, das ich zu lösen versuche, da sie explizite Anforderungen aufführt, da einige häufig vorgeschlagene, nicht funktionierende Lösungen auf die schwarze Liste gesetzt werden und dies nicht für eine einzelne Anwendung spezifisch ist. Nach dieser Diskussion habe ich meine Frage gepostet.

antworten

Stoppen Sie die Verwendung von gethostbyname(). Sie sollten stattdessen getaddrinfo() verwenden, und dies schon seit Jahren. Die Manpage warnt Sie sogar davor.

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

Hier ist ein schnelles Beispielprogramm in C, in dem das Nachschlagen von nur A-Datensätzen nach einem Namen und ein Wireshark-Capture veranschaulicht werden, das zeigt, dass nur Datensatz-Suchvorgänge über das Netzwerk gingen .

Insbesondere müssen Sie ai_family auf AF_INET setzen, wenn Sie nur eine Datensatzsuche durchführen möchten. Dieses Beispielprogramm druckt nur die zurückgegebenen IP-Adressen. Ein ausführlicheres Beispiel zum Herstellen abgehender Verbindungen finden Sie auf der Manpage getaddrinfo().

Im Wireshark-Capture ist 172.25.50.3 der lokale DNS-Resolver. Das Capture wurde dort aufgenommen, sodass Sie auch die ausgehenden Abfragen und Antworten sehen. Beachten Sie, dass nur ein A-Datensatz angefordert wurde. Es wurde niemals eine AAAA-Suche durchgeführt.

#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);
}

Gehen Sie im Zweifelsfall zum Quellcode! Also, mal sehen ... gethostbyname () sieht interessant aus; Das beschreibt genau das, was wir sehen: versuchen Sie zuerst IPv6, und greifen Sie dann auf IPv4 zurück, wenn Sie keine Antwort erhalten, die Ihnen gefällt. Was ist das für eine RES_USE_INET6 Flagge? Wenn Sie es zurückverfolgen, kommt es von res_setoptions (). Hier wird resolv.conf eingelesen.

Und .... das bin ich aus Ideen. Mir ist völlig unklar, wie RES_USE_INET6 eingestellt wird, wenn nicht resolv.conf.

Sie könnten BIND als lokalen Resolver verwenden, es gibt eine Option zum Filtern von AAAA:

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

Haben Sie versucht, PDNS-recursor einzurichten, setzen Sie es in Ihrer/etc/resolv.conf und leugnen "AAAA" Lookups in ihm? Etwas wie query-local-address6=

verwenden