Frage Wie deaktiviert man AAAA Lookups?


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

Unser Problem: Wir setzen eingebettete Geräte ein, die Sensordaten auf verschiedenen, meist reinen IPv4-Sites sammeln. Einige Sites haben schlecht gewartete Netzwerke, z.B. falsch konfigurierte oder anderweitig beschädigte DNS-Caches und / oder Firewalls, die AAAA-Abfragen entweder vollständig ignorieren oder mit gebrochenen Antworten darauf antworten (z. B. falsche Quell-IP!). Als externer Lieferant der Facility-Abteilung haben wir so gut wie keinen Einfluss auf die (manchmal widerwilligen) IT-Abteilungen. Die Chancen, dass sie ihre DNS-Server / Firewalls in absehbarer Zeit reparieren, sind winzig.

Der Effekt auf unserem Gerät ist, dass mit jedem gethostbyname () die Prozesse warten müssen, bis die AAAA-Zeitüberschreitung abfragt, und zu diesem Zeitpunkt haben einige Prozesse ihre Verbindungsversuche bereits beendet.

Ich suche nach Lösungen, die ...

  • systemweit. Ich kann Dutzende von Anwendungen nicht einzeln rekonfigurieren
  • nicht permanent und konfigurierbar. Wir müssen IPv6 (wieder) aktivieren, wo / wann es behoben / ausgerollt wird. Neustart ist OK.
  • Wenn eine Lösung erfordert, dass eine Kernbibliothek wie glibc ersetzt wird, sollte das Ersatzbibliothekspaket von einem als gut zu wartenden Repository verfügbar sein (z. B. Debian Testing, Ubuntu-Universum, EPEL). Selbstbildung 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 offensichtlichste Lösung wäre, die Resolver-Bibliothek z.B. über / etc / {Auflösung,nsswitch,Gai} .conf, um AAAA-Datensätze nicht abzufragen. Eine resolv.conf-Option no-inet6 wie vorgeschlagen Hier wäre genau 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)

Also wie? Man findet die folgenden Methoden, die auf SF und anderswo vorgeschlagen wurden, aber keiner von ihnen funktioniert:

  • Deaktivieren von IPv6 insgesamt, z.B. indem Sie das ipv6-LKM in /etc/modprobe.d/ auf die schwarze Liste setzen, oder sysctl -w net.ipv6.conf.all.disable_ipv6=1. (Aus Neugier: Warum fragt der Resolver nach AAAA, wo IPv6 deaktiviert ist?)
  • Entfernen options inet6 aus /etc/resolv.conf. Es war nicht dort an erster Stelle, inet6 ist in diesen Tagen standardmäßig aktiviert.
  • Rahmen options single-request in /etc/resolv.conf. Dies stellt nur sicher, dass die A- und die AAAA-Abfragen sequenziell und nicht parallel ausgeführt werden
  • Ändern precedence in /etc/gai.conf. Das hat keine Auswirkungen auf die DNS-Abfragen, sondern nur darauf, wie mehrere Antworten verarbeitet werden.
  • Die Verwendung von externen Resolvern (oder das Ausführen eines lokalen Resolver-Daemons, der die fehlerhaften DNS-Server umgeht) würde helfen, wird aber normalerweise von den Firewall-Richtlinien des Unternehmens nicht zugelassen. Und es kann interne Ressourcen unzugänglich machen.

Alternative hässliche Ideen:

  • Führen Sie einen DNS-Cache auf localhost aus. Konfigurieren Sie es so, dass alle Nicht-AAAA-Abfragen weitergeleitet werden, jedoch auf AAAA-Abfragen entweder mit NOERROR oder NXDOMAIN reagiert wird (abhängig vom Ergebnis der entsprechenden A-Abfrage). Ich bin mir jedoch nicht bewusst, dass ein DNS-Cache dazu in der Lage ist.
  • Verwenden Sie einige clevere iptables u32-Übereinstimmung oder Ondrej Caletka iptables DNS-Modul AAAA-Abfragen abzugleichen, um sie entweder abzulehnen (wie würde die Resolver-Bibliothek darauf reagieren?) oder um sie an einen lokalen DNS-Server umzuleiten, der auf alles mit einem leeren NOERROR 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 sie einige häufig vorgeschlagene nicht funktionierende Lösungen auf die schwarze Liste setzt und nicht für eine einzelne Anwendung spezifisch ist. Folgend diese DiskussionIch habe meine Frage gestellt.


33
2017-10-01 09:03


Ursprung


PS: Entgegen der landläufigen Meinung zu SF gibt es einige gute Gründe, IPv6 / AAAA auf einem Computer in einem IPv4-only-Netzwerk zu deaktivieren, selbst dort, wo DNS funktioniert: Broadcast-Last reduzieren; Reduzieren Sie die Belastung von DNS-Resolvern um fast 50%. Reduzieren Sie Verbindungsstartzeiten (erheblich, wo DNS-Caches verzögert sind); Befolgen Sie die Best Practices, um nicht funktionale Funktionen zu deaktivieren, um die Sicherheit und Stabilität zu verbessern. Zugegebenermaßen, wenn ich vergessen habe, IPv6 wieder zu aktivieren, sobald es verfügbar ist, dann wird mein System zu einem IPv4-Legacy-Vorschaltgerät, das den IPv6-Rollout verhindert. Man sollte die aufgeführten Profis gegen diesen Betrug abwägen dürfen. - Nils Toedtmann
Gibt es einen Grund, warum Sie keinen lokalen Resolver auf localhost ausführen? Auf diese Weise eliminieren Sie die Abhängigkeit von (scheinbar) unzuverlässigen DNS-Resolvern anderer Leute. - Sander Steffann
@SanderSteffann Firewall-Richtlinien des Unternehmens lassen dies normalerweise nicht zu. Aber anderswo ist das eine Option. Ich werde es später zu meiner Frage hinzufügen. - Nils Toedtmann
@joeqwerty Wir machen keine Annahmen darüber, ob IPv6 vor Ort unterstützt wird oder nicht. Wir nehmen jedoch an, dass DNS-Server standardkonform sind. Auch einige IT-Abteilungen leider tun Ihnen fehlen die Fähigkeiten, ihre Infrastruktur richtig zu konfigurieren. Tut mir leid, dass ich so unverblümt bin. - Nils Toedtmann
Ich verstehe was du sagst. Sie müssen Ihre Box in ihrem Netzwerk arbeiten lassen und nicht umgekehrt. Und darum bitten Sie hier. Ich werde nur ein wenig verärgert, wenn wir im IT-Bereich unsere Kunden beschuldigen und sie nicht respektieren. Sie sind unser Brot und Butter. Für gut oder schlecht müssen wir das respektieren und respektieren. Unsere Kunden sind kein Hindernis für unser Geschäft, sie sind der Grund für unser Geschäft. - joeqwerty


Antworten:


Hör auf zu benutzen gethostbyname(). Sie sollten verwenden getaddrinfo() stattdessen, und sollte seit Jahren gewesen sein. Die Manpage warnt dich 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 schnelles Beispielprogramm in C, das Nachschlagen zeigt nur Ein Datensatz für einen Namen und eine Wireshark-Aufnahme, die das anzeigt nur Ein Record Lookups ging über das Netzwerk.

Insbesondere müssen Sie festlegen ai_family zu AF_INET wenn Sie nur A-Record-Lookups machen wollen. Dieses Beispielprogramm druckt nur die zurückgegebenen IP-Adressen. Siehe die getaddrinfo() man-Seite für ein vollständigeres Beispiel, wie ausgehende Verbindungen hergestellt werden können.

In dem Wireshark erfassen172.25.50.3 ist der lokale DNS-Resolver; Die Erfassung wurde dort aufgenommen, sodass Sie auch die ausgehenden Abfragen und Antworten sehen können. Beachten Sie, dass nur ein A-Datensatz wurde angefordert. Kein AAAA Lookup wurde jemals gemacht.

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

8
2017-07-25 17:34



Interessant! Ich werde untersuchen, welche Anwendungen AAAA-Anfragen auslösen. Wenn es nur uns gehört, werde ich deinen Vorschlag an unsere Entwickler weiterleiten. Aber ich habe eine starke Ahnung, dass eine Menge von Debian / Ubuntu-verpackter Software darunter leidet, und wir werden diese nicht patchen. - Nils Toedtmann
Ihre Bewerbung ist wahrscheinlich die wichtigste. Selbst wenn Sie alles andere nicht reparieren können, kann es die Situation verbessern. - Michael Hampton♦


Wenn Sie Zweifel haben, gehen Sie zum Quellcode über! 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 RES_USE_INET6 Flagge? Es zurückverfolgen, es kommt von res_setoptions (). Das ist wo resolv.conf wird eingelesen.

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


3
2017-10-02 20:40



RES_USE_INET6 können über eingestellt werden options inet6 im resolv.conf. Ich schätze mein Problem ist, dass es nicht sein kann nicht gesetzt sobald es zur Kompilierzeit eingestellt wurde, was alle großen Distributionen in diesen Tagen zu tun scheinen (richtig?). Daher die Feature-Anforderung für options no_inet6 das habe ich oben erwähnt. - Nils Toedtmann
Wie Sie dem Code entnehmen können, scheint es leider keine zu geben no_inet6 Option in res_setoptions(). Wie Sie jedoch aus (no) sehen könnenip6-dotintEs ist eine einfache Änderung hinzuzufügen. Um die Theorie zu testen, dass es standardmäßig von Ihrer Distribution gesetzt wird, würde ich die Paketquelldateien packen und sie einmal "neu" kompilieren (um zu bestätigen, dass das Paket das Verhalten repliziert) und dann Folgendes hinzufügen: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 }, zum options[] Array und sehen, ob das Problem verschwindet, wenn Sie diese Option aktivieren resolv.conf. - BMDan
Zu guter Letzt: Für was es wert ist, würde ich dies lösen, indem ich einen DNS-Cache auf localhost (wie Sie oben verweisen) ausführen. Es wäre viel einfacher, einen eigenen, gehackten DNS-Proxy / Cache zu pflegen, als eine gehackte Version einer Core-Systembibliothek beizubehalten. - BMDan


Sie könnten BIND als einen lokalen Resolver verwenden, es hat eine Option, AAAA zu filtern:

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


3
2017-07-25 21:09



Das ist ziemlich schwer für ein Embedded-Gerät. - Michael Hampton♦
Danke, mir war der AAAA-Filter von Bind nicht bekannt. Wie Michael erwähnt, ist es wahrscheinlich keine Lösung für uns aufgrund der großen Präsenz von Bind. Aber für diejenigen, die AAAA-Antworten in anderen Szenarien herausfiltern möchten, könnte dies ein gangbarer Weg sein. Ubuntu baut tatsächlich eine Bindung mit "--enable-filter-aaaa", zumindest am 14.04. Nicht sicher über Debian. - Siehe auch ipamworldwide.blogspot.co.uk/2011/09/... - Nils Toedtmann
Ich bin am 14.04 und es scheint nicht, dass diese Filteroption verfügbar ist. - Zitrax


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


0
2017-10-02 10:22



query-local-address6=tut etwas anderes (an welche IPv6-Adresse Anfragen gesendet werden sollen - beachten Sie, dass AAAA-Anfragen auch bei deaktiviertem IPv6 noch über IPv4 gelöst werden). Ich kann auch 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