Come disabilitare le ricerche AAAA?


35

... per compensare i server DNS rotti che sono al di fuori del nostro controllo.

Il nostro problema: implementiamo dispositivi incorporati che raccolgono dati dei sensori in vari siti, principalmente solo IPv4. Alcuni siti hanno reti scarsamente gestite, ad esempio cache DNS e / o firewall non configurati correttamente o altrimenti non funzionanti che ignorano del tutto le query AAAA o rispondono con risposte errate (ad es. IP sorgente errato!). Come fornitore esterno del dipartimento delle strutture, non abbiamo quasi alcuna influenza sui dipartimenti IT (a volte riluttanti). Le possibilità che correggano i loro server DNS / firewall in qualsiasi momento presto sono minuscole.

L'effetto sul nostro dispositivo è che con ogni gethostbyname (), i processi devono attendere fino al timeout delle query AAAA, a quel punto alcuni processi hanno già scaduto del tutto i loro tentativi di connessione.

Sto cercando soluzioni che siano ...

  • a livello di sistema. Non riesco a riconfigurare decine di applicazioni individualmente
  • non permanente e configurabile. Dobbiamo (ri) abilitare IPv6 dove / quando viene riparato / implementato. Il riavvio è OK.
  • Se una soluzione richiede la sostituzione di una libreria principale come glibc, il pacchetto della libreria sostitutiva dovrebbe essere disponibile da un repository ben noto (ad esempio Debian Testing, Ubuntu universe, EPEL). L'auto-costruzione non è un'opzione per così tanti motivi che non so nemmeno da dove cominciare, quindi non li elenco affatto ...

La soluzione più ovvia sarebbe quella di configurare la libreria del resolver, ad esempio tramite / etc / { resolv , nsswitch , gai } .conf per non interrogare i record AAAA. Un'opzione resolv.conf no-inet6come suggerito qui sarebbe esattamente quello che sto cercando. Purtroppo non è implementato, almeno non sui nostri sistemi (libc6-2.13-38 + deb7u4 su Debian 7; libc6-2.19-0ubuntu6.3 su Ubuntu 14.04)

Allora come? Si trovano i seguenti metodi suggeriti su SF e altrove, ma non di loro funzionano:

  • Disabilitare del tutto IPv6, ad esempio inserendo nella blacklist ipv6 LKM in /etc/modprobe.d/, oppure sysctl -w net.ipv6.conf.all.disable_ipv6=1. ( Per curiosità: perché il risolutore chiede AAAA in cui IPv6 è disabilitato? )
  • Rimozione options inet6da /etc/resolv.conf. In primo luogo non era lì, inet6è semplicemente abilitato per impostazione predefinita in questi giorni.
  • Impostazione options single-requestin /etc/resolv.conf. Ciò garantisce solo che le query A e AAAA vengano eseguite in sequenza anziché in parallelo
  • Modifica precedencein /etc/gai.conf. Ciò non influisce sulle query DNS, ma solo sul modo in cui vengono elaborate più risposte.
  • L'uso di resolver esterni (o l'esecuzione di un demone resolver locale che elude i server DNS rotti) sarebbe di aiuto, ma di solito non è consentito dalle politiche del firewall dell'azienda. E può rendere inaccessibili le risorse interne.

Idee brutte alternative:

  • Esegui una cache DNS su localhost. Configuralo per inoltrare tutte le query non AAAA, ma per rispondere alle query AAAA con NOERROR o NXDOMAIN (a seconda del risultato della query A corrispondente). Non sono a conoscenza di una cache DNS in grado di farlo però.
  • Usa una corrispondenza ip32 intelligente u32 o il modulo DNS iptables di Ondrej Caletka per abbinare le query AAAA, al fine di rifiutarle icmp (come reagirebbe la lib risolutore a quella?) O reindirizzarle a un server DNS locale che risponde a tutto con un NOERROR vuoto.

Si noti che ci sono domande simili e correlate su SE. La mia domanda differisce in quanto elabora il problema reale che sto cercando di risolvere, in quanto elenca i requisiti espliciti, in quanto elenca alcune soluzioni non funzionanti spesso suggerite e poiché non è specifico per una singola applicazione. A seguito di questa discussione , ho pubblicato la mia domanda.


13
PS: Contrariamente alla credenza popolare qui su SF, ci sono alcuni buoni motivi per disabilitare IPv6 / AAAA su una macchina in una rete solo IPv4, anche dove DNS funziona: ridurre il carico di trasmissione; Ridurre il carico sui resolver DNS di quasi il 50%; Ridurre i tempi di avvio della connessione (significativamente dove le cache DNS sono in ritardo); Seguire le migliori pratiche per disabilitare le funzionalità non funzionali per migliorare la sicurezza e la stabilità. Certo, se dimentico di riattivare IPv6 una volta che è disponibile, il mio sistema diventa un reattore legacy IPv4 che impedisce l'implementazione di IPv6. Si dovrebbe permettere di soppesare i pro elencati contro questo truffatore.
Nils Toedtmann,

Qual è il motivo per cui non esegui un resolver completo su localhost? In questo modo si elimina del tutto la dipendenza dai risolutori DNS (apparentemente) inaffidabili di altre persone.
Sander Steffann,

Le politiche del firewall di @SanderSteffann Company di solito non lo consentono. Ma altrove è un'opzione. Lo aggiungerò alla mia domanda più tardi.
Nils Toedtmann,

3
@joeqwerty Non stiamo ipotizzando se IPv6 sia supportato o meno sul sito. Diamo per scontato che i server DNS siano conformi agli standard. Inoltre, alcuni dipartimenti IT purtroppo non dispongono delle competenze per configurare correttamente la propria infrastruttura. Ci scusiamo per essere schietto su questo.
Nils Toedtmann,

4
Capisco quello che stai dicendo. Devi far funzionare la tua scatola sulla loro rete non viceversa, ed è quello che stai chiedendo qui. Sono solo un po 'seccato quando nel campo IT incolpiamo i nostri clienti e non li rispettiamo. Sono il nostro pane e burro. Nel bene o nel male dobbiamo rispettarlo e rispettarli. I nostri clienti non rappresentano un ostacolo per la nostra attività, sono la ragione della nostra attività.
joeqwerty,

Risposte:


9

Smetti di usare gethostbyname(). Dovresti usare getaddrinfo()invece, e dovrebbe essere stato per anni ormai. La pagina man ti avverte persino di questo.

Le funzioni gethostbyname * (), gethostbyaddr * (), herror () e hstrerror () sono obsolete. Le applicazioni dovrebbero usare invece getaddrinfo (3), getnameinfo (3) e gai_strerror (3).

Ecco un rapido programma di esempio in C che mostra come cercare solo i record A per un nome e una cattura di Wireshark che mostra che solo le ricerche dei record A sono passate sulla rete.

In particolare, è necessario impostare ai_familysu AF_INETse si desidera eseguire solo ricerche record. Questo programma di esempio stampa solo gli indirizzi IP restituiti. Vedi la getaddrinfo()pagina man per un esempio più completo di come effettuare connessioni in uscita.

Nella cattura Wireshark , 172.25.50.3 è il resolver DNS locale; la cattura è stata effettuata lì, quindi puoi anche vedere le sue query e risposte in uscita. Si noti che è stato richiesto solo un record A. Non è mai stata effettuata alcuna ricerca 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);
}

Interessante! Esaminerò quali applicazioni attivano le richieste AAAA. Se è solo nostro, allora inoltrerò il tuo suggerimento ai nostri sviluppatori. Ma ho la netta idea che molti software Debian / Ubuntu siano affetti da questo, e non li ripareremo.
Nils Toedtmann,

La tua applicazione è probabilmente la più importante. Anche se non puoi sistemare tutto il resto, potrebbe migliorare la situazione.
Michael Hampton

4

In caso di dubbi, vai al codice sorgente! Quindi, vediamo ... gethostbyname () sembra interessante; che descrive esattamente ciò che stiamo vedendo: prova prima IPv6, quindi torna a IPv4 se non ottieni una risposta che ti piace. Cos'è questa RES_USE_INET6bandiera? Tracciandolo indietro, viene da res_setoptions () . Questo è dove resolv.confviene letto.

E .... sono io a corto di idee. Non sono completamente chiaro come RES_USE_INET6sia impostato se non in resolv.conf.


RES_USE_INET6 può essere impostato tramite options inet6in resolv.conf. Immagino che il mio problema sia che non può essere disinserito una volta impostato al momento della compilazione, cosa che sembrano fare tutte le principali distro in questi giorni (giusto?). Pertanto la richiesta di funzionalità per options no_inet6quello che ho menzionato sopra.
Nils Toedtmann,

1
Sfortunatamente, come puoi vedere dal codice, non sembra esserci no_inet6un'opzione in res_setoptions(). Tuttavia, come puoi vedere da (no-) ip6-dotint, è una modifica facile da aggiungere. Per testare la teoria che è stato impostato di default per la vostra distro, mi piacerebbe afferrare i file di origine del pacchetto e compilare una volta "vergine" (per confermare che il pacchetto replica il comportamento) e quindi aggiungere: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },per la options[]matrice e vedere se il il problema scompare quando si imposta l'opzione in resolv.conf.
BMDan,

1
Infine: per quello che vale, lo risolverei eseguendo una cache DNS su localhost (come riferimento, sopra). Sarebbe molto più facile mantenere il proprio proxy / cache DNS hackerato piuttosto che mantenere una versione compromessa di una libreria di sistema di base.
BMDan,

3

Puoi usare BIND come resolver locale, ha un'opzione per filtrare AAAA:

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


2
È piuttosto pesante per un dispositivo incorporato.
Michael Hampton

Grazie, non ero a conoscenza del filtro AAAA di Bind. Come menziona Michael, probabilmente non è una soluzione per noi a causa della grande impronta di Bind. Ma per coloro che vogliono filtrare le risposte AAAA in altri scenari, potrebbe essere un modo praticabile. Ubuntu in realtà crea il bind con "--enable-filter-aaaa", almeno su 14.04. Non sono sicuro di Debian. - Vedi anche ipamworldwide.blogspot.co.uk/2011/09/…
Nils Toedtmann,

1
Sono il 14.04 e non sembra che questa opzione di filtro sia disponibile.
Zitrax,

0

Hai provato a installare PDNS-recursor, impostarlo nel tuo /etc/resolv.conf e negare le ricerche "AAAA" in esso? Usando qualcosa di similequery-local-address6=


1
query-local-address6=fa qualcosa di diverso (da quale indirizzo IPv6 inviare le query - nota che anche con IPv6 disabilitato, le richieste AAAA verranno comunque risolte tramite IPv4). Inoltre, non riesco a identificare alcuna altra impostazione che possa filtrare le query AAAA ( doc.powerdns.com/html/built-in-recursor.html ). Senza queste informazioni, la tua risposta non è molto utile :(
Nils Toedtmann,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.