Wie deaktiviere ich AAAA-Lookups?

35

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

Unser Problem: Wir setzen eingebettete Geräte ein, die Sensordaten an verschiedenen, meist nur IPv4-fähigen Standorten erfassen. Einige Sites haben schlecht gewartete Netzwerke, z. B. falsch konfigurierte oder anderweitig defekte DNS-Caches und / oder Firewalls, die AAAA-Abfragen entweder vollständig ignorieren oder mit defekten Antworten antworten (z. B. falsche Quell-IP!). Als externer Zulieferer der Facility-Abteilung haben wir nahezu keinen Einfluss auf die (teilweise widerstrebenden) IT-Abteilungen. Die Wahrscheinlichkeit, dass sie bald ihre DNS-Server / Firewalls reparieren, ist gering.

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

Ich suche nach Lösungen, die ...

  • systemweit. Ich kann Dutzende von Anwendungen nicht einzeln konfigurieren
  • nicht permanent und konfigurierbar. Wir müssen IPv6 (wieder) aktivieren, wo / wann es repariert / eingeführt wird. Neustart ist OK.
  • Wenn eine Lösung das Ersetzen einer Kernbibliothek wie glibc erfordert, sollte das Ersatzbibliothekspaket in einem bekanntermaßen gut gewarteten Repository verfügbar sein (z. B. Debian Testing, Ubuntu-Universum, EPEL). Selfbuilding ist aus so vielen Gründen keine Option, dass ich gar nicht weiß, wo ich anfangen soll, also liste ich sie überhaupt nicht auf ...

Die naheliegendste Lösung wäre, die Resolver-Bibliothek zB über / etc / { resolv , nsswitch , gai } .conf so zu konfigurieren, dass AAAA-Datensätze nicht abgefragt werden. Eine resolv.conf-Option, no-inet6wie hier vorgeschlagen , wäre genau das , wonach 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 also? Man findet die folgenden Methoden vorgeschlagen auf SF und anderswo, aber nicht von ihnen funktionieren:

  • Vollständiges Deaktivieren von IPv6, z. B. durch Sperren 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 options inet6aus /etc/resolv.conf. Es war gar nicht da, inet6ist heutzutage einfach standardmäßig aktiviert.
  • Einstellung options single-requestin /etc/resolv.conf. Dies stellt nur sicher, dass die A- und AAAA-Abfragen nacheinander und nicht parallel ausgeführt werden
  • Änderung precedencein /etc/gai.conf. Dies betrifft nicht die DNS-Abfragen, sondern nur die Art und Weise, wie mehrere Antworten verarbeitet werden.
  • Die Verwendung externer Resolver (oder die Ausführung eines lokalen Resolver-Daemons, der die defekten DNS-Server umgeht) würde helfen, wird jedoch in der Regel von den Firewall-Richtlinien des Unternehmens nicht zugelassen. Und es kann interne Ressourcen unzugänglich machen.

Alternative hässliche Ideen:

  • Führen Sie auf localhost einen DNS-Cache aus. Konfigurieren Sie es, um alle Nicht-AAAA-Abfragen weiterzuleiten, aber um auf AAAA-Abfragen mit NOERROR oder NXDOMAIN zu antworten (abhängig vom Ergebnis der entsprechenden A-Abfrage). Mir ist jedoch kein DNS-Cache bekannt, der dies ermöglicht.
  • Verwenden Sie einige clevere iptables u32-Übereinstimmungen oder das iptables-DNS-Modul von Ondrej Caletka , um AAAA-Abfragen abzugleichen, um sie entweder per ICMP abzulehnen (wie würde die Resolver-Bibliothek darauf reagieren?) Oder um sie an einen lokalen DNS-Server weiterzuleiten, der darauf antwortet alles mit einem leeren NOERROR.

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

Nils Toedtmann
quelle
13
PS: Entgegen der landläufigen Meinung zu SF gibt es einige gute Gründe, IPv6 / AAAA auf einem Computer in einem IPv4-Netzwerk zu deaktivieren, auch wenn DNS funktioniert: Reduzieren Sie die Übertragungslast; Reduzieren Sie die Belastung von DNS-Resolvern um fast 50%. Reduzieren Sie die Startzeiten für die Verbindung (deutlich, wenn DNS-Caches verzögert sind). Befolgen Sie die bewährten Methoden zum Deaktivieren nicht funktionsfähiger Funktionen, um die Sicherheit und Stabilität zu verbessern. Zugegeben, wenn ich vergesse, IPv6 wieder zu aktivieren, sobald es verfügbar ist, wird mein System zu einem IPv4-Vorgänger, der den IPv6-Rollout behindert. Man sollte die aufgeführten Profis gegen diese Nachteile abwägen dürfen.
Nils Toedtmann
Gibt es einen Grund, warum Sie auf localhost keinen vollständigen Resolver ausführen? Auf diese Weise beseitigen Sie die Abhängigkeit von (scheinbar) unzuverlässigen DNS-Resolvern anderer Personen.
Sander Steffann
Die Firewall-Richtlinien von @SanderSteffann Company lassen dies normalerweise nicht zu. Aber anderswo ist das eine Option. Ich werde es später zu meiner Frage hinzufügen.
Nils Toedtmann
3
@joeqwerty Wir gehen nicht davon aus, ob IPv6 vor Ort unterstützt wird oder nicht. Wir gehen jedoch davon aus, dass DNS-Server standardkonform sind. Einige IT-Abteilungen verfügen leider nicht über die erforderlichen Fähigkeiten, um ihre Infrastruktur ordnungsgemäß zu konfigurieren. Tut mir leid, dass ich so unverblümt bin.
Nils Toedtmann
4
Ich verstehe was du sagst. Sie müssen dafür sorgen, dass Ihre Box in ihrem Netzwerk funktioniert, nicht umgekehrt, und darum geht es hier. Ich ärgere mich nur ein wenig, wenn wir im IT-Bereich unseren Kunden die Schuld geben und sie nicht respektieren. Sie sind unser Brot und Butter. Für gut oder schlecht müssen wir das respektieren und sie respektieren. Unsere Kunden sind kein Hindernis für unser Geschäft, sie sind der Grund für unser Geschäft.
Joeqwerty

Antworten:

9

Hör auf zu benutzen gethostbyname(). Sie sollten getaddrinfo()stattdessen verwenden, und das schon seit Jahren. Die Manpage warnt Sie sogar davor.

Die Funktionen gethostbyname * (), gethostbyaddr * (), herror () und hstrerror () sind veraltet. Anwendungen sollten stattdessen getaddrinfo (3), getnameinfo (3) und gai_strerror (3) verwenden.

Hier ist ein kurzes Beispielprogramm in C, in dem gezeigt wird, wie nur A-Datensätze nach einem Namen durchsucht werden, und eine Wireshark-Erfassung, aus der hervorgeht, dass nur A- Datensätze im Netzwerk gesucht wurden .

Insbesondere müssen Sie auf festlegen ai_family, AF_INETwenn nur A-Datensatz-Lookups durchgeführt werden sollen. Dieses Beispielprogramm druckt nur die zurückgegebenen IP-Adressen. In der getaddrinfo()Manpage finden Sie ein umfassenderes Beispiel für das Herstellen ausgehender Verbindungen.

In der Wireshark-Erfassung 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 nie 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);
}
Michael Hampton
quelle
Interessant! Ich werde untersuchen, welche Anwendungen AAAA-Anfragen auslösen. Wenn es nur uns gehört, werde ich Ihren Vorschlag an unsere Entwickler weiterleiten. Aber ich habe die starke Vermutung, dass eine Menge Debian / Ubuntu-Software darunter leidet, und wir werden diese nicht patchen.
Nils Toedtmann
Ihre Bewerbung ist wahrscheinlich die wichtigste. Auch wenn Sie nicht alles andere beheben können, kann dies die Situation verbessern.
Michael Hampton
4

Wenn Sie Zweifel haben, gehen Sie zum Quellcode! Also mal sehen ... gethostbyname () sieht interessant aus; Das beschreibt genau, 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 diese RES_USE_INET6Flagge? Wenn Sie es zurückverfolgen, kommt es von res_setoptions () . Hier resolv.confwird eingelesen.

Und ... das sind mir keine Ideen. Ich bin völlig unklar, wie es ist, dass eingestellt RES_USE_INET6wird, wenn nicht in resolv.conf.

BMDan
quelle
RES_USE_INET6 kann über options inet6in gesetzt werden resolv.conf. Ich vermute, mein Problem ist, dass es nicht mehr rückgängig gemacht werden kann, wenn es zur Kompilierungszeit gesetzt wurde. Dies scheinen heutzutage alle wichtigen Distributionen zu tun (richtig?). Daher options no_inet6habe ich den oben erwähnten Feature-Request dazu .
Nils Toedtmann
1
Wie Sie dem Code entnehmen können, scheint es in leider keine no_inet6Option zu geben res_setoptions(). Wie Sie jedoch an (no-) sehen können ip6-dotint, ist es einfach, eine Änderung hinzuzufügen. Um die Theorie zu testen , dass sie von Ihrem Distro Satz von Standard - Sein, würde ich die Paketquelldateien packen und kompilieren sie einmal „virgin“ (zu bestätigen , dass das Paket das Verhalten repliziert) und fügen Sie dann: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },auf dem options[]Array und sehen , ob die Das Problem verschwindet, wenn Sie diese Option aktivieren resolv.conf.
BMDan
1
Und zu guter Letzt: Ich würde dieses Problem lösen, indem ich auf localhost einen DNS-Cache starte (wie Sie weiter oben sehen). Es wäre viel einfacher, einen eigenen, gehackten DNS-Proxy / Cache zu verwalten, als eine gehackte Version einer Kernsystembibliothek.
BMDan
3

Sie können 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

Robert Kerr
quelle
2
Das ist ziemlich schwer für ein Embedded-Gerät.
Michael Hampton
Vielen Dank, ich kannte Binds AAAA-Filter nicht. Wie Michael erwähnt, ist es wahrscheinlich keine Lösung für uns, da Bind eine große Stellfläche hat. Aber für diejenigen, die AAAA-Antworten in anderen Szenarien herausfiltern möchten, ist dies möglicherweise eine praktikable Möglichkeit. Ubuntu-Builds binden tatsächlich mit "--enable-filter-aaaa", zumindest am 14.04. Ich bin mir nicht sicher über Debian. - Siehe auch ipamworldwide.blogspot.co.uk/2011/09/…
Nils Toedtmann
1
Ich bin am 14.04 und es scheint nicht, dass diese Filteroption verfügbar ist.
Zitrax
0

Haben Sie versucht, PDNS-recursor einzurichten, in Ihrer /etc/resolv.conf einzustellen und "AAAA" -Nachschläge zu verweigern? Verwenden Sie so etwas wiequery-local-address6=

Kleber
quelle
1
query-local-address6=macht etwas anderes (welche IPv6-Adresse zum Senden von Abfragen verwendet wird - beachten Sie, dass AAAA-Anforderungen auch bei deaktiviertem IPv6 weiterhin über IPv4 aufgelöst werden). Außerdem kann ich keine andere Einstellung identifizieren, die AAAA-Abfragen filtern würde ( doc.powerdns.com/html/built-in-recursor.html ). Ohne diese Informationen ist Ihre Antwort nicht sehr hilfreich :(
Nils Toedtmann