... 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-inet6
wie 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 inet6
aus /etc/resolv.conf. Es war gar nicht da,inet6
ist heutzutage einfach standardmäßig aktiviert. - Einstellung
options single-request
in /etc/resolv.conf. Dies stellt nur sicher, dass die A- und AAAA-Abfragen nacheinander und nicht parallel ausgeführt werden - Änderung
precedence
in /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.
quelle
Antworten:
Hör auf zu benutzen
gethostbyname()
. Sie solltengetaddrinfo()
stattdessen verwenden, und das schon seit Jahren. Die Manpage warnt Sie sogar davor.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_INET
wenn nur A-Datensatz-Lookups durchgeführt werden sollen. Dieses Beispielprogramm druckt nur die zurückgegebenen IP-Adressen. In dergetaddrinfo()
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.
quelle
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_INET6
Flagge? Wenn Sie es zurückverfolgen, kommt es von res_setoptions () . Hierresolv.conf
wird eingelesen.Und ... das sind mir keine Ideen. Ich bin völlig unklar, wie es ist, dass eingestellt
RES_USE_INET6
wird, wenn nicht inresolv.conf
.quelle
options inet6
in gesetzt werdenresolv.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?). Daheroptions no_inet6
habe ich den oben erwähnten Feature-Request dazu .no_inet6
Option zu gebenres_setoptions()
. Wie Sie jedoch an (no-) sehen könnenip6-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 demoptions[]
Array und sehen , ob die Das Problem verschwindet, wenn Sie diese Option aktivierenresolv.conf
.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
quelle
Haben Sie versucht, PDNS-recursor einzurichten, in Ihrer /etc/resolv.conf einzustellen und "AAAA" -Nachschläge zu verweigern? Verwenden Sie so etwas wie
query-local-address6=
quelle
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 :(