Passa al contenuto principale

5. RESOLVER (RESOLVERS)

5.1. Introduzione (Introduction)

I resolver sono programmi che fanno da interfaccia tra i programmi utente e i name server di dominio. Nel caso più semplice, un resolver riceve una richiesta da un programma utente (ad esempio, programmi di posta, TELNET, FTP) sotto forma di una chiamata a subroutine, chiamata di sistema, ecc., e restituisce le informazioni desiderate in un formato compatibile con i formati dati dell'host locale.

Il resolver si trova sulla stessa macchina del programma che richiede i servizi del resolver, ma potrebbe aver bisogno di consultare name server su altri host. Poiché un resolver potrebbe aver bisogno di consultare diversi name server, o potrebbe avere le informazioni richieste in una cache locale, il tempo che un resolver impiegherà per completare può variare parecchio, da millisecondi a diversi secondi.

Un obiettivo molto importante del resolver è eliminare il ritardo di rete e il carico del name server dalla maggior parte delle richieste rispondendo ad esse dalla sua cache di risultati precedenti. Ne consegue che le cache che sono condivise da più processi, utenti, macchine, ecc., sono più efficienti delle cache non condivise.

5.2. Interfaccia client-resolver (Client-resolver interface)

5.2.1. Funzioni tipiche (Typical functions)

L'interfaccia client al resolver è influenzata dalle convenzioni dell'host locale, ma l'interfaccia resolver-client tipica ha tre funzioni:

1. Traduzione da nome host a indirizzo host (Host name to host address translation)

Questa funzione è spesso definita per imitare una precedente funzione basata su HOSTS.TXT. Data una stringa di caratteri, il chiamante vuole uno o più indirizzi IP a 32 bit. Nel DNS, si traduce in una richiesta per RR di tipo A. Poiché il DNS non preserva l'ordine degli RR, questa funzione può scegliere di ordinare gli indirizzi restituiti o selezionare l'"indirizzo migliore" se il servizio restituisce solo una scelta al client. Si noti che è raccomandato un ritorno di più indirizzi, ma un singolo indirizzo potrebbe essere l'unico modo per emulare i servizi HOSTS.TXT precedenti.

2. Traduzione da indirizzo host a nome host (Host address to host name translation)

Questa funzione seguirà spesso la forma di funzioni precedenti. Dato un indirizzo IP a 32 bit, il chiamante vuole una stringa di caratteri. Gli ottetti dell'indirizzo IP vengono invertiti, utilizzati come componenti del nome, e suffissati con "IN-ADDR.ARPA". Una query di tipo PTR viene utilizzata per ottenere l'RR con il nome primario dell'host. Ad esempio, una richiesta per il nome host corrispondente all'indirizzo IP 1.2.3.4 cerca RR PTR per il nome di dominio "4.3.2.1.IN-ADDR.ARPA".

3. Funzione di ricerca generale (General lookup function)

Questa funzione recupera informazioni arbitrarie dal DNS, e non ha controparte nei sistemi precedenti. Il chiamante fornisce un QNAME, QTYPE e QCLASS, e vuole tutti gli RR corrispondenti. Questa funzione spesso utilizzerà il formato DNS per tutti i dati RR invece di quello dell'host locale, e restituisce tutto il contenuto RR (ad esempio, TTL) invece di una forma elaborata con convenzioni di citazione locali.

Tipi di risultato (Result types)

Quando il resolver esegue la funzione indicata, di solito ha uno dei seguenti risultati da restituire al client:

  • Uno o più RR che forniscono i dati richiesti (One or more RRs giving the requested data): In questo caso il resolver restituisce la risposta nel formato appropriato.

  • Un errore di nome (NE) (A name error): Questo accade quando il nome referenziato non esiste. Ad esempio, un utente potrebbe aver digitato erroneamente un nome host.

  • Un errore di dati non trovati (A data not found error): Questo accade quando il nome referenziato esiste, ma i dati del tipo appropriato non esistono. Ad esempio, una funzione di indirizzo host applicata a un nome di casella postale restituirebbe questo errore poiché il nome esiste, ma nessun RR di indirizzo è presente.

È importante notare che le funzioni per la traduzione tra nomi host e indirizzi possono combinare le condizioni di errore "errore di nome" e "dati non trovati" in un singolo tipo di ritorno di errore, ma la funzione generale non dovrebbe. Una ragione per questo è che le applicazioni potrebbero chiedere prima un tipo di informazione su un nome seguito da una seconda richiesta allo stesso nome per qualche altro tipo di informazione; se i due errori sono combinati, allora query inutili possono rallentare l'applicazione.

5.2.2. Alias (Aliases)

Mentre tenta di risolvere una particolare richiesta, il resolver potrebbe scoprire che il nome in questione è un alias. Ad esempio, il resolver potrebbe scoprire che il nome dato per la traduzione da nome host a indirizzo è un alias quando trova l'RR CNAME. Se possibile, la condizione di alias dovrebbe essere segnalata dal resolver al client.

Nella maggior parte dei casi un resolver riavvia semplicemente la query al nuovo nome quando incontra un CNAME. Tuttavia, quando esegue la funzione generale, il resolver non dovrebbe seguire gli alias quando l'RR CNAME corrisponde al tipo di query. Questo permette query che chiedono se un alias è presente. Ad esempio, se il tipo di query è CNAME, l'utente è interessato all'RR CNAME stesso, e non agli RR al nome a cui punta.

Possono verificarsi diverse condizioni speciali con gli alias. Più livelli di alias dovrebbero essere evitati a causa della loro mancanza di efficienza, ma non dovrebbero essere segnalati come un errore. I loop di alias e gli alias che puntano a nomi non esistenti dovrebbero essere catturati e una condizione di errore restituita al client.

5.2.3. Fallimenti temporanei (Temporary failures)

In un mondo meno che perfetto, tutti i resolver occasionalmente non saranno in grado di risolvere una particolare richiesta. Questa condizione può essere causata da un resolver che si separa dal resto della rete a causa di un guasto del collegamento o di un problema del gateway, o meno spesso da un guasto coincidente o dall'indisponibilità di tutti i server per un particolare dominio.

È essenziale che questo tipo di condizione non debba essere segnalato come un errore di nome o dati non presenti alle applicazioni. Questo tipo di comportamento è fastidioso per gli umani, e può causare il caos quando i sistemi di posta utilizzano il DNS.

Mentre in alcuni casi è possibile affrontare tale problema temporaneo bloccando la richiesta indefinitamente, questo di solito non è una buona scelta, in particolare quando il client è un processo server che potrebbe passare ad altre attività. La soluzione raccomandata è avere sempre il fallimento temporaneo come uno dei possibili risultati di una funzione resolver, anche se questo può rendere più difficile l'emulazione delle funzioni HOSTS.TXT esistenti.

5.3. Strutture interne del resolver (Resolver internals)

Ogni implementazione di resolver utilizza algoritmi leggermente diversi, e tipicamente spende molta più logica nel gestire errori di vario tipo rispetto alle occorrenze tipiche. Questa sezione delinea una strategia di base raccomandata per l'operazione del resolver, ma lascia i dettagli a [RFC-1035].

5.3.1. Resolver stub (Stub resolvers)

Un'opzione per implementare un resolver è spostare la funzione di risoluzione fuori dalla macchina locale e in un name server che supporta query ricorsive. Questo può fornire un metodo facile per fornire servizio di dominio in un PC che manca delle risorse per eseguire la funzione resolver, o può centralizzare la cache per un'intera rete locale o organizzazione.

Tutto ciò di cui lo stub rimanente ha bisogno è un elenco di indirizzi di name server che eseguiranno le richieste ricorsive. Questo tipo di resolver presumibilmente ha bisogno delle informazioni in un file di configurazione, poiché probabilmente manca della sofisticazione per localizzarle nel database di dominio. L'utente deve anche verificare che i server elencati eseguiranno il servizio ricorsivo; un name server è libero di rifiutare di eseguire servizi ricorsivi per qualsiasi o tutti i client. L'utente dovrebbe consultare l'amministratore di sistema locale per trovare name server disposti a eseguire il servizio.

Questo tipo di servizio soffre di alcuni svantaggi. Poiché le richieste ricorsive possono richiedere un tempo arbitrario per essere eseguite, lo stub potrebbe avere difficoltà nell'ottimizzare gli intervalli di ritrasmissione per gestire sia i pacchetti UDP persi che i server morti; il name server può essere facilmente sovraccaricato da uno stub troppo zelante se interpreta le ritrasmissioni come nuove richieste. L'uso di TCP può essere una risposta, ma TCP può ben porre oneri sulle capacità dell'host che sono simili a quelli di un vero resolver.

5.3.2. Risorse (Resources)

Oltre alle proprie risorse, il resolver può anche avere accesso condiviso a zone mantenute da un name server locale. Questo dà al resolver il vantaggio di un accesso più rapido, ma il resolver deve fare attenzione a non lasciare mai che le informazioni memorizzate nella cache sovrascrivano i dati di zona. In questa discussione il termine "informazioni locali" è inteso a significare l'unione della cache e tali zone condivise, con la comprensione che i dati autorevoli sono sempre usati in preferenza ai dati memorizzati nella cache quando entrambi sono presenti.

Il seguente algoritmo del resolver presume che tutte le funzioni siano state convertite in una funzione di ricerca generale, e utilizza le seguenti strutture dati per rappresentare lo stato di una richiesta in corso nel resolver:

SNAME

Il nome di dominio che stiamo cercando.

STYPE

Il QTYPE della richiesta di ricerca.

SCLASS

Il QCLASS della richiesta di ricerca.

SLIST

Una struttura che descrive i name server e la zona che il resolver sta attualmente cercando di interrogare. Questa struttura tiene traccia della migliore ipotesi corrente del resolver su quali name server detengono le informazioni desiderate; viene aggiornata quando le informazioni in arrivo cambiano l'ipotesi. Questa struttura include l'equivalente di un nome di zona, i name server noti per la zona, gli indirizzi noti per i name server, e informazioni storiche che possono essere utilizzate per suggerire quale server è probabile che sia il migliore da provare dopo. L'equivalente del nome di zona è un conteggio di corrispondenze del numero di etichette dalla radice in giù che SNAME ha in comune con la zona interrogata; questo è usato come misura di quanto "vicino" il resolver è a SNAME.

SBELT

Una struttura "cintura di sicurezza" della stessa forma di SLIST, che è inizializzata da un file di configurazione, e elenca i server che dovrebbero essere utilizzati quando il resolver non ha alcuna informazione locale per guidare la selezione del name server. Il conteggio delle corrispondenze sarà -1 per indicare che non è noto che nessuna etichetta corrisponda.

CACHE

Una struttura che memorizza i risultati dalle risposte precedenti. Poiché i resolver sono responsabili dello scarto dei vecchi RR il cui TTL è scaduto, la maggior parte delle implementazioni converte l'intervallo specificato negli RR in arrivo in una sorta di tempo assoluto quando l'RR viene memorizzato nella cache. Invece di contare i TTL individualmente, il resolver ignora o scarta semplicemente i vecchi RR quando li incontra nel corso di una ricerca, o li scarta durante spazzamenti periodici per recuperare la memoria consumata dai vecchi RR.

5.3.3. Algoritmo (Algorithm)

L'algoritmo di livello superiore ha quattro passi:

  1. Vedere se la risposta è nelle informazioni locali, e se sì restituirla al client.

  2. Trovare i migliori server da interrogare.

  3. Inviare loro query fino a quando una restituisce una risposta.

  4. Analizzare la risposta, sia:

    a. Se la risposta risponde alla domanda o contiene un errore di nome, memorizzare nella cache i dati così come restituirli al client.

    b. Se la risposta contiene una delega migliore ad altri server, memorizzare nella cache le informazioni di delega, e andare al passo 2.

    c. Se la risposta mostra un CNAME e questo non è la risposta stessa, memorizzare nella cache il CNAME, cambiare SNAME al nome canonico nell'RR CNAME e andare al passo 1.

    d. Se la risposta mostra un fallimento del server o altri contenuti bizzarri, eliminare il server dall'SLIST e tornare al passo 3.

Passo 1: Cercare informazioni locali (Step 1: Search local information)

Il passo 1 cerca nella cache i dati desiderati. Se i dati sono nella cache, si presume che siano abbastanza buoni per l'uso normale. Alcuni resolver hanno un'opzione nell'interfaccia utente che forzerà il resolver a ignorare i dati memorizzati nella cache e consultare un server autorevole. Questo non è raccomandato come predefinito. Se il resolver ha accesso diretto alle zone di un name server, dovrebbe controllare se i dati desiderati sono presenti in forma autorevole, e se sì, utilizzare i dati autorevoli in preferenza ai dati memorizzati nella cache.

Passo 2: Trovare i migliori server (Step 2: Find best servers)

Il passo 2 cerca un name server a cui chiedere i dati richiesti. La strategia generale è cercare RR di name server disponibili localmente, partendo da SNAME, poi il nome di dominio parent di SNAME, il nonno, e così via verso la radice. Quindi se SNAME fosse Mockapetris.ISI.EDU, questo passo cercherebbe RR NS per Mockapetris.ISI.EDU, poi ISI.EDU, poi EDU, poi . (la radice). Quando viene trovato un elenco di name server, il resolver dovrebbe ordinarli secondo la preferenza e le prestazioni attese. Il resolver dovrebbe quindi cercare di contattare i server in quell'ordine, iniziando con il più preferito.

Passo 3: Inviare query (Step 3: Send queries)

Il passo 3 invia query fino a quando viene ricevuta una risposta. L'algoritmo di base è ciclare attraverso tutti gli indirizzi per tutti i server con un timeout tra ogni trasmissione. Il resolver dovrebbe usare UDP per le query quando possibile, e usare TCP solo quando la risposta è troncata o quando il resolver è disposto a pagare il sovraccarico della creazione e chiusura della connessione TCP.

Passo 4: Analizzare la risposta (Step 4: Analyze response)

Il passo 4 analizza le risposte. Il resolver dovrebbe essere altamente paranoico nel parsing delle risposte. Dovrebbe anche verificare che la risposta corrisponda alla query che ha inviato utilizzando il campo ID nella risposta.