djbdns - Un'alternativa (sicura) a BIND

di Luca Morettoni <luca at morettoni dot net>
Ultimo aggiornamento: $Date: 2006/01/27 16:34:07 $, versione $Revision: 1.4 $

La versione aggiornata del presente documento è disponibile su: morettoni.net/docs/djbdns.html

E' finalmente disponibile il libro "djbdns, un'alternativa (sicura) a BIND", edito dal Gruppo Editoriale Infomedia, Pisa - codice ISBN: 8881500205.
Il libro si propone come naturale completamento di questo documento, è stato arricchito con molte sezioni riguardanti le configurazioni, la programmazione e molto altro!
Potete acquistare una copia online qui!. Supporta questo progetto:

L'autore si riserva tutti i diritti e ne ammette la pubblicazione in qualsiasi forma solo con autorizzazione.


Indice


1. Premessa

Il presente articolo è stato redatto per poter presentare in maniera rapida l'utilizzo e le funzionalità di djbdns, una raccolta di programmi per la gestione di un DNS. Tutte le informazioni riportate sono frutto dell'esperienza personale e di una continua ricerca su Internet. Ogni critica, commento o segnalazione sono ben accetti in modo da poter rendere questo testo sempre più completo ed utile a chiunque. In caso di utilizzo degli esempi o comandi riportati nel testo, nè l'autore, nè chi pubblica il presente documento, potrà in alcun modo essere ritenuto responsabile di qualsiasi conseguenza possa scaturirne.


2. Introduzione

Sicuramente molti di voi avranno già sentito parlare di qmail (cr.yp.to/qmail.html), un MTA alternativo a Sendmail che sta prendendo sempre più piede su Internet, sviluppato da Dan Bernstein con un principio fondamentale: avere un software sicuro. Un altro software "interessante" sviluppato da Bernstein è djbdns, un ottimo sistema per DNS. Anche djbdns è stato sviluppato per essere sicuro e l'autore ha addirittura messo in palio un premio di 500 dollari per chiunque trovi un baco nel sistema (per i dettagli consiglio di leggere: cr.yp.to/djbdns/guarantee.html) e, visti i recenti problemi di sicurezza di BIND, direi che solo questo è già un buon motivo per iniziare a valutarne le caratteristiche.


3. Cos'è un DNS?

Prima di iniziare a vedere cos'è e come funziona djbdns è importante chiarire (a grandi linee ovviamente) come funziona un DNS. Esistono due tipologie principali di servizi DNS: gli "authoritative DNS" e i "resolver DNS" (o recursive resolver). Vediamo di capire cosa e quali sono le loro funzioni con degli esempi, partendo dai "resolver DNS".
E' fondamentale capire la netta distinzione tra questi due tipi di servizi, anche perchè purtroppo BIND integra entrambe le modalità e troppo spesso i suoi utenti tendono a confondersi, mentre djbdns li mantiene nettamente separati.

3.1. Resolver DNS

I resolver DNS sono quei sistemi che permettono di "risolvere" il nome a dominio (es. www.gufi.org) in indirizzo IP della macchina da contattare attraverso un meccanismo di "interrogazioni" che andremo ad analizzare.
Quando dal nostro PC ad esempio apriamo l'home page del GUFI (Gruppo Utenti FreeBSD Italia), il nostro sistema ottiene dal file /etc/resolv.conf l'indirizzo del resolver da utilizzare e provvede, tramite la porta UDP 53, a richiedergli di risolvere l'indirizzo "www.gufi.org".
Il nome del dominio viene diviso in campi, ognuno separato dal carattere . (punto), e ogni campo viene analizzato da destra verso sinistra; il nome così come è stato scritto e come siamo normalmente abituati a farlo non è completo, infatti la corretta notazione richiederebbe anche un punto finale, quindi il nome corretto sarebbe "www.gufi.org.".
Ora campo per campo (ricordo sempre da destra verso sinistra) vedremo come il resolver svolge il suo lavoro:
il primo campo trovato è il solo punto, che sta ad indicare la radice, ovvero il punto di partenza della ricerca; il resolver contatta una serie di server conosciuti (i root server) chiedendo appunto a quale IP corrisponda l'indirizzo www.gufi.org. La risposta che otterrà non sarà quella che ci si attendeva, infatti i root server sicuramente non sono a conoscenza degli indirizzi IP per tale dominio, tuttavia ci viene fornito insieme alla risposta negativa un prezioso indizio, ovvero quale (o quali) server contattare per richiedere informazioni sulla zona "org".
Il resolver sfrutta subito questo suggerimento, rifacendo nuovamente la medesima interrogazione al server della zona "org", tuttavia anche in questo caso otterrà sempre una risposta parziale, ovvero il server indicherà solamente un elenco di server a cui richiedere le informazioni, questa volta per la zona "gufi".
Reinoltrando la richesta all'ennesimo server questa volta otterremo l'IP associato al nome www.gufi.org. visto che finalmente siamo riusciti a contattare il server di tipo authoritative per la zona "gufi".
Questi "indizi" che il nostro resolver riceve di volta in volta dai server che interroga hanno un nome specifico, i glue records che incontreremo e/o definiremo nel nostro eventuale DNS autoritativo.
E' ovvio che il resolver per ogni interrogazione non eseguirà di nuovo tutta la trafila vista prima, infatti tutte le risposte ottenute interrogando i vari nameserver vengono poste in cache, in modo da essere immediatamente disponibili per le richieste successive. Ad esempio se volessimo risolvere l'indirizzo IP per il dominio mail.freebsd.org, il nostro resolver già conosce il server authoritative per la zona "org" quindi eviterà di interrogare i root server risparmiando un passaggio; se invece la mia richiesta fosse cvs.gufi.org, il server authoritative contattato sarebbe quello della zona "gufi" (in questo caso i passaggi risparmiati sarebbero due).

3.2. Authoritative DNS

Nel paragrafo precedente, parlando dei resolver, abbiamo tirato in ballo i server DNS di tipo Authoritative che rappresentano le macchine che contengono le informazioni sui domini. In queste macchine andremo esclusivamente a mappare i vari nomi (zone) con i relativi indirizzi IP.
Ora dovrebbe essere più chiaro il ruolo dei due tipi di server DNS, gli authoritative che "custodiscono" le informazioni dei nomi a dominio (zone) e i resolver che vanno ad individuare quali sono i server di tipo authoritative per il dominio/zona cercato e ne ottengono le informazioni.


4. Cos'è djbdns?

Ora che abbiamo più chiaro il funzionamento dei servizi di DNS andiamo ad analizzare gli strumenti che djbdns ci mette a disposizione. Il pacchetto è costituito in realtà da diversi programmi che operano insieme, questo sia per dare una maggiore sicurezza all'intero sistema sia per rendere il tutto estremamente modulare; in più djbdns non necessita di girare come utente root e ogni suo programma in esecuzione lavora in chroot in una cartella ben definita. Un'altra caratteristica interessante di djbdns è il formato dei suoi file di configurazione, i quali potrebbero sembrare alquanto criptici per chi proviene da BIND, ma una volta entrati nella logica utilizzata dall'autore se ne trarranno molti benefici. Questi file sono infatti strutturati per essere facilmente manipolati via software e/o generati automaticamente. Esistono diversi script che permettono di mantenere le proprie zone in un database e di "esportarle" rapidamente nel formato adatto a djbdns. Ultima nota prima di tuffarci alla scoperta di questo potente strumento: per poter funzionare correttamente djbdns ha bisogno di daemontools e ucspi-tpc, due software sempre realizzati da Bernstein (consiglio di leggere le informazioni che trovate sul sito, oppure il capitolo 6. Programmi correlati del presente documento, dedicato a loro). Nel resto dell'articolo darò per scontato che sono ambedue installati correttamente, e che daemontools sia configurato per leggere la directory dei servizi in /var/services.

4.1. Installazione

djbdns viene distribuito sotto forma di sorgenti da compilare nel proprio computer, quindi occorre innanzi tutto scaricare il pacchetto con i sorgenti disponibili all'indirizzo cr.yp.to/djbdns/djbdns-1.05.tar.gz e salvarlo in una directory di lavoro dove andremo a scompattarlo e compilarlo con i seguenti comandi:

	tar xfz djbdns-1.05.tar.gz
	cd djbdns-1.05
	make
Terminata la fase di compilazione, la cui durata dipenderà dalle risorse e dalla velocità del vostro computer, come utente root daremo:
	make setup check
Nel caso in cui il vostro sistema sia un *BSD consiglio di utilizzare l'installazione tramite ports, ad esempio in FreeBSD con l'albero dei ports dovutamente installato e aggiornato basterà digitare (sempre da root):
	cd /usr/ports/dns/djbdns
	make install clean
A questo punto sara possibile configurare e utilizzare djbdns secondo le esigenze.

4.2. Authoritative DNS: tinydns

tinydns rappresenta il cuore di djbdns, essendo il tool che si occupa delle risposte di tipo "authoritative" per i domini che ha in gestione. Di per sè il lavoro svolto è relativamente semplice, tinydns rimane in attesa di richieste e, nel caso in cui la richiesta riguardi un dominio presente nel suo database, fornisce la risposta adeguata, altrimenti non ritorna alcuna informazione. Il cuore vero di tinydns è proprio questo database di configurazione (in BIND sarebbero i file di zona) che sicuramente a prima vista spaventerà per il suo formato alquanto "particolare"; tuttavia la scelta di questo formato è dovuta al fatto di poter rendere questo file facilmente editabile con strumenti informatici (ad esempio sed) o addirittura di poterlo generare con dati provenienti da fonti esterne (es. database).

4.2.1. Configurazione

Prima di entrare nei dettagli del database di tinydns andiamo ad installarlo, creando innanzi tutto due utenti con cui far girare il programma e il suo logger:

	useradd -d /nonexistent -s /nonexistent Gtinydns
	useradd -d /nonexistent -s /nonexistent Gdnslog
oppure:
	pw user add Gtinydns -d /nonexistent -s /nonexistent
	pw user add Gdnslog -d /nonexistent -s /nonexistent
I nomi ovviamente possono essere scelti a proprio piacimento, tuttavia il consiglio è quello di utilizzare quelli "standard" consigliati da Bernstein, compresa la G maiuscola iniziale per rendere i nomi assolutamente univoci nel sistema. Ora non resta altro da fare che creare la struttura di base per tinydns con il comando:
	tinydns-conf Gtinydns Gdnslog /usr/local/etc/tinydns indirizzo_IP
in questo modo avremo in /usr/local/etc/tinydns lo scheletro della configurazione pronto ad essere aggiunto alla lista dei servizi di daemontools con:
	ln -s /usr/local/etc/tinydns /var/service
tuttavia prima di far partire il servizio consiglierei di modificare lo script log/run (tutti i path si intendono relativi a quello di configurazione del servizio, nel nostro esempio /usr/local/etc/tinydns), in quanto tutti i log verranno memorizzati in log/main. Per spostare il tutto in /var/log/tinydns useremo:
	mkdir /var/log/tinydns
	chown -R Gdnslog /var/log/tinydns
e modificheremo lo script log/run in modo tale che al posto di ./main ci sia la direcotry sopra creata: seguendo l'esempio il nostro log/run conterrà:
	#!/bin/sh
	exec setuidgid dnslog multilog t /var/log/tinydns

4.2.2. Le zone

Ora che il nostro authoritative DNS è funzionante, dobbiamo iniziare a creare le varie zone. Come accennato precedentemente il tutto è controllato tramite un file: root/data. Questo file di testo in realtà non viene utilizzato da tinydns, infatti il programma effettua le letture dal file root/data.cdb, ovvero la versione "binaria" di data, il tutto per poter rendere più veloce il tempo di risposta alle interrogazioni. Ogni volta che dovremo modificare o aggiungere le informazioni di una zona andremo ad editare esclusivamente il file data, poi provvederemo alla "compilazione" con un semplice make (per i curiosi consiglio di dare un occhio al Makefile presente in root). Nel caso in cui non ci siano errori di sintassi, verrà generato il nuovo file data.cdb e le modifiche avranno effetto immediato, senza dover killare nessun processo. Cominciamo a vedere più nel dettaglio il formato del file di configurazione, facendo una comparazione con il formato della configurazione di BIND. Ricordo inoltre che nel paragrafo 5.1. Migrazione da BIND a djbdns vedremo come prelevare le informazioni da un server BIND e convertirle automaticamente in formato tinydns.
E' possibile inserire anche linee di commento, precedute dal carattere #, tutto il testo che segue verrà ignorato fino alla fine della riga.
In linea generale il formato dei dati di tinydns è così strutturato:

	<tipo>parametro_1[:parametro_2][:parametro_3]...[:parametro_n]
dove <tipo> rappresenta il tipo di informazione che andiamo a descrivere. mentre gli eventuali parametri verranno separati dal carattere : (due punti). Quasi tutti i tipi di dati che andremo a descrivere hanno un parametro che indicherò con local e che non descriverò, per poi tornarne a parlare al termine del paragrafo.

Cominciamo con:
	.dominio:indirizzo_ip:nome:ttl:timestamp:local
questa riga crea le informazioni principali per il nameserver di "dominio", ovvero "traducendo" in formato BIND otterremo:
La cosa che forse potrà sembrarci strana è la generazione automatica del nameserver primario in nome.ns.dominio e che potrebbe creare difficoltà se vogliamo utilizzare dns1.dominio, basterà indicare:
	.dominio:indirizzo_ip:dns1.dominio:ttl:timestamp:local
Come è facile intuire dal nome, ttl rappresenta il "Time To Live", ovvero il tempo (in secondi) che l'informazione indicata può rimanere memorizzata in cache. Se si omette questo valore sarà assegnato automaticamente da tinydns, anche se normalmente si usa 86400 secondi (24 ore).
Il valore di timestamp invece ha un doppio significato, a seconda del valore di ttl: se ttl è pari a zero, il timestamp rappresenta la scadenza dell'informazione, mentre se ttl è diverso da zero oppure viene omesso, rappresenta la data di inizio validità dell'informazione.
Questo comando informa tinydns che è lui il server autoritativo per la zona dominio, di conseguenza verranno generati anche i "glue records" per la zona stessa.

Una versione più limitata del comando precedente è:
	&dominio:indirizzo_ip:nome:ttl:timestamp:local
questa volta verranno create esclusivamente le informazioni per:
anche in questo caso per non ottenere l'aggiunta automatica di "ns" tra nome e dominio basterà inserire il nome completo da dare al nameserver (vedi esempio precedente).
Attenzione, in questo caso non vengono generati i glue records per il dominio, di conseguenza è consigliabile utilizzare questo comando solo per delegare una sottozona ad un altro DNS.

Infine, se fosse necessario creare solo il record SOA potremmo ricorrere a:
	Zdominio:ns_primario:contact_address:seriale:refresh_time:retry_time:expire_time:minimum_time:ttl:timestamp:local
sicuramente in questo record sono facilmente individuabili tutte le informazioni che eravamo abituati ad indicare nel SOA della zona. Evito di spiegarne il relativo significato, tuttavia è possibile omettere i valori dei seguenti campi (in parentesi ho indicato il valore assegnato per default da tinydns):
Avete letto bene, il numero seriale della zona viene generato ed aggiornato automaticamente da tinydns, ogni volta che andiamo ad apportare delle modifiche al nostro database, comodo vero? Tuttavia se stiamo migrando (come spero) da un server BIND prima di poter sfruttare questa caratteristica è necessario aggiustare manualmente il seriale al primo aggiornamento delle zone (in fondo al testo troverete i passaggi da effettuare).

Un'altra informazione fondamentale per un dominio sono i record MX, ovvero i Mail Exchanger, dichiarabili con:
	@dominio:indirizzo_ip:nome:n_precedenza:ttl:timestamp:local
che creerà le informazioni per:
Come per i record NS, se si vuole attribuire un nome arbitrario al mail exchanger (ad esempio mail.dominio) andrà indicato per esteso nel campo nome.

infine:
	=nome:indirizzo_ip:ttl:timestamp:local
creerà:
nel caso in cui non fosse necessario creare il record PTR useremo:
	+nome:indirizzo_ip:ttl:timestamp:local
Per dovere di cronaca esistono anche altri tipi di record meno utilizzati, vediamoli rapidamente:
	Cnome1:nome2:ttl:timestamp:local
crea un record CNAME in modo che nome1 faccia riferimento a nome2
	'dominio:testo:ttl:timestamp:local
crea un record TXT associato a dominio con contenuto "testo"
	^dominio:nome:ttl:timestamp:local
crea un record PTR, facendo puntare "dominio" a "nome"

Moltissime persone dicono che tinydns non supporta tutti i record DNS gestiti da BIND, questo per fortuna non è vero, infatti grazie ad un comando è possibile creare "manualmente" qualsiasi record non previsto dall'autore.
Con una riga del tipo:
	:dominio:codice:data:ttl:timestamp:local
e settando opportunamente i campi codice e data è possibile personalizzare le risposte generate da tinydns.
Se ad esempio volessi aggiungere un record RP (Responsible Person, ovvero il responsabile per un dominio) aggiungeremo la seguente linea al nostro file data:
	:morettoni.local:17:\004luca\011morettoni\005local\000\000:
In questo esempio la nostra entry RP per il dominio morettoni.local sarà la stringa "luca@morettoni.local" (il carattere @ viene sostituito dal punto). Ovviamente nella sezione data vanno impostati i dati così come devono essere restituiti al client, di conseguenza se dobbiamo inserire valori non ASCII possiamo ricorrere alla notazione ottale come nell'esempio.
Su Internet possiamo trovare numerosi programmi che ci permettono di generare in automatico le stringhe da aggiungersi al file data, in particolare vorrei segnalare:
Per un approfondimento sul formato e sul significato di quanto visto finora, consiglio di leggere attentamente la descrizione "ufficiale" del formato del file di configurazione, reperibile su: cr.yp.to/djbdns/tinydns-data.html.

Riprendiamo ora la discussione sospesa inizialmente sul significato del campo local presente su tutti i record (ricordo che questo campo è opzionale). In pratica local rappresenta un tag di tipo testo (verranno presi in considerazione solo i primi due caratteri), e con uno speciale comando è possibile definire uno o più contesti in cui tale tag è valido, ovvero dei casi dove poter includere o escludere determinati record del DNS; cerchiamo di chiarire meglio il funzionamento con un esempio pratico:
	%in:192.168.0
	%ex

	=luca.dominio:192.168.0.35:::in
	=luca.dominio:213.1.1.68:::ex
le prime due righe definiscono due tag, il primo in è valido per tutti i client con indirizzo 192.168.0.x mentre tutti gli altri avranno il tag ex, in questo modo luca.dominio verrà "risolto selettivamente" in funzione del tag associato al client (quindi del suo IP).
In generale la sintassi per l'assegnazione dei tag è:
	%local:network_ip

4.2.3. I log

I log generati da tinydns purtroppo non sono immediatamente leggibili, tuttavia a colpo d'occhio è possibile individuare possibili anomalie del nostro server autoritativo. Il primo &guot;ostacolo" che ci troviamo ad affrontare durante un'analisi di questi log è il formato esadecimale utilizzato per loggare gli IP (e le porte) di provenienza delle query. Infatti tinydns loggherà le richieste proveninenti dall'IP 192.168.0.1 con la stringa c0a80001 (per risalire alla versione decimale basta scomporre la stringa nei quattro ottetti c0.a8.00.01 e ricorventirli singolarmente in decimale).
Ogni richiesta viene loggata su una singola riga che conterrà i seguenti campi:

	timestamp ip:porta:id stato tipo richiesta
In questa tabella trovate elencati alcuni tipi di record e il relativo valore loggato da tinydns:
RecordValore
A0001
NS0002
CNAME0005
SOA0006
PTR000c
MX000f
TXT0010
AXFR00fc
ANY00ff
Riporto infine un estratto da un file di log di tinydns usato per una rete privata.
	@400000004061b79c158d632c starting tinydns
	@400000004061b7a3212a035c c0a8000a:7cb8:6498 + 0001 ibm.morettoni.local
	@400000004061b7a61534df04 c0a8000a:cee5:9ec7 + 001c ibm.morettoni.local
	@400000004061b7a70cfad67c c0a8000a:2512:462c + 000c 1.0.168.192.in-addr.arpa
	@400000004061b7a7263b9edc c0a8000a:b6b2:ed58 + 0001 home.morettoni.local
	@400000004061b7a72a40660c c0a8000a:ab96:b849 + 001c home.morettoni.local
	@40000000406213a316f714ec c0a8000a:5a99:6db4 + 001c build.morettoni.local
	@40000000406213a3176f84f4 c0a8000a:4539:bcef + 0001 build.morettoni.local
	@40000000406221540f50094c c0a8000a:8867:f801 + 000f home.morettoni.local
	@4000000040623d763420d74c c0a8000a:f58a:2d4f - 0001 warez.morettoni.local

4.3. Resolver DNS: dnscache

dnscache è la parte di djbdns che si occupa di rispondere ESCLUSIVAMENTE alle interrogazioni sulle risoluzioni dei nomi, e le risposte che fornirà ai client saranno esclusivamente quelle ritenute sicure. Queste informazioni vengono prelevate da nameserver di tipo authoritative che vengono chiamati in causa come spiegato nell'introduzione.

4.3.1. Configurazione

Prima di iniziare a configurare dnscache è necessario creare due utenti nel sistema con i quali verranno eseguiti dnscache stesso ed il suo logger, quindi come root impartiremo i comandi:

	useradd -d /nonexistent -s /nonexistent Gdnscache
	useradd -d /nonexistent -s /nonexistent Gdnslog
oppure:
	pw user add Gdnscache -d /nonexistent -s /nonexistent
	pw user add Gdnslog -d /nonexistent -s /nonexistent
la G maiuscola che precede i due nomi è stata scelta esclusivamente per rendere univoci globalmente i nomi utente, è chiaro che siete liberi di scegliere una qualsiasi combinazione di nomi valida.
Ora non resta altro che creare lo scheletro di configurazione con il comando dnscache-conf, nel nostro caso è sufficiente:
	dnscache-conf Gdnscache Gdnslog /usr/local/etc/dnscache indirizzo_IP
in questo modo verrà creata una struttura di configurazione nella directory /usr/local/etc/dnscache e il servizio si metterà in ascolto delle richieste sull'indirizzo specificato con indirizzo_IP, se si fosse omesso questo parametro, dnscache avrebbe utilizzato l'indirizzo 127.0.0.1.
Prima di dare il via al servizio è bene effettuare alcuni controlli sulla configurazione appena creata. In particolar modo nella sottodirectory log andiamo ad analizzare il file run, per default i log infatti verranno memorizzati in /usr/local/etc/dnscache/log/main, è buona norma invece tenerli memorizzati ad esempio in /var/log, basterà quindi modificare il contenuto di log/run sostituendo ./main con il path alla directory da noi desiderata (ovviamente dovremmo crearla e assegnarla all'utente scelto per i log, nel nostro caso Gdnslog), ad esempio nella mia configurazione il file log/run ha il seguente contenuto:
	#!/bin/sh
	exec setuidgid Gdnslog multilog t /var/log/dnscache
ora non resta che linkare la directory di configurazione alla directory dei servizi di daemontools con:
	ln -s /usr/local/etc/dnscache /var/service
e in pochi secondi il nostro resolver sarà completamente funzionante! Prima però di andare ad aggiornare tutti i resolv.conf degli altri client della rete dobbiamo ancora una volta effettuare alcune modifiche alla configurazione di base di dnscache, infatti per default dnscache-conf soddisferà solo le richieste provenienti dall'indirizzo IP 127.0.0.1. Tutte le configurazioni di dnscache risiedono nella directory root (sempre relativa alla directory creata da dnscache-conf), all'interno troviamo altre due cartelle: ip e servers. Servers contiene un solo file chiamato @ in cui è memorizzata la lista dei root server che dnscache andrà ad interrogare, mentre la directory ip conterrà dei file di lunghezza zero, e i nomi rappresenteranno gli indirizzi IP o le reti da cui potranno pervernire le richieste di interrogazione; per default troveremo solo un file chiamato 127.0.0.1 appunto. Se volessimo configurare il tutto in modo che risponda alle interrogazioni provenienti solo dall'ip 192.168.0.50 daremo:
	touch /usr/local/etc/dnscache/root/ip/192.168.0.50
mentre se intendiamo accettare le interrogazioni provenienti dagli IP 192.168.0.x il comando sarà:
	touch /usr/local/etc/dnscache/root/ip/192.168.0
Un'altra cartella che contiene files interessanti è env, dentro la quale troviamo diversi file contenenti varie impostazioni di dnscache, tra questi c'è da segnalare il più importante: CACHESIZE, dal cui nome si intuisce che si tratta della dimensione massima (in byte) della cache utilizzabile. Un'altra variabile utilizzata è DATALIMIT che impone la dimensione massima del segmento dati di dnscache (ovviamente deve essere maggiore di CACHESIZE).

4.3.2. La cache

E' chiaro che non è facile stabilire in modo generico di quanta cache abbiamo bisogno, tuttavia su cr.yp.to/djbdns/cachesize.html Bernstein spiega un metodo di analisi dei log per stabilire un limite di cache in funzione del traffico effettivo sul DNS.
dnscache scrive nei log una riga contrassegnata dal tag stats, seguita da quattro numeri che stanno a rappresentare:

il valore che a noi interessa è cache motion, ovvero il secondo, tale numero indica il numero di byte scritti in cache da quando è stato attivato il servizio. Per il nostro calcolo occorrerà memorizzare tale numero e poi ricontrollarlo dopo 24 ore. Per facilitare tale operazione consiglio di utilizzare un file di log separato per i valori stats modificando lo script log/run nel seguente modo:
	#!/bin/sh
	exec setuidgid Gdnslog multilog t /var/log/dnscache/ '-*' '+* stats * * * *' /var/log/dnscache/stats
In questo modo il file /var/log/dnscache/stats/current conterrà solo le linee che ci interessano permettendo un'analisi rapida. Ricavata quindi la differenza tra i due valori di cache motion basterà dividere la dimensione della cache impostata con il risultato della differenza e se il numero che avremo si approssimerà a questi valori: Visto che il TTL medio delle zone si aggira intorno ai due/tre giorni sarà il caso di alzare il limite di memoria di CACHESIZE per valori inferiori al tre.
Un settaggio interessante di dnscache è quello di poter indicare quali siano i server authoritative per alcune zone evitando così le interrogazioni viste prima. Con i seguenti comandi:
	echo "192.168.0.28" > /var/service/dnscache/root/servers/morettoni.net
	svc -t /var/service/dnscache
ogni interrogazione che dnscache riceverà per il dominio morettoni.net e le sue sottozone (es. mail.morettoni.net) verrà richiesta al server authoritative all'indirizzo 192.168.0.28, mentre tutte le altre seguiranno il normale funzionamento.

4.4. Le liste RBL: rbldns

djbdns può essere utile per creare delle liste basate su indirizzi IP, come ad esempio le liste RBL utili per controllare il traffico di posta proveniente da IP indesiderati (o autorizzati). Questo compito puo' essere svolto perfettamente da tinydns, tuttavia se abbiamo la necessità di gestire liste di IP possiamo ricorrere ad una versione "alleggerita" che è rbldns.

4.4.1. Configurazione

Anche per rbldns è necessario creare due utenti, uno per il servizio stesso e l'altro per i log, da root daremo:

	useradd -d /nonexistent -s /nonexistent Grbldns
	useradd -d /nonexistent -s /nonexistent Gdnslog
oppure:
	pw user add Grbldns -d /nonexistent -s /nonexistent
	pw user add Gdnslog -d /nonexistent -s /nonexistent
La struttura per il servizio verrà creata grazie al comando rbldns-conf, i parametri che occorrerà indicare sono:
	rbldns-conf Grbldns Gdnslog /usr/local/etc/rbldns indirizzo_IP base
in questo modo verrà creata una struttura di configurazione nella directory /usr/local/etc/rbldns e il servizio si metterà in ascolto delle richieste sull'indirizzo specificato con indirizzo_IP, e utilizzerà base come zona per le interrogazioni in arrivo.
Anche per questo servizio i log per default verranno scritti nella directory ./main, se si desidera memorizzarli altrove sarà sufficiente modificare il contenuto dello script log/run come abbiamo visto per i servizi precedenti.
Ora non resta che linkare la directory di configurazione alla directory dei servizi di daemontools con:
	ln -s /usr/local/etc/rbldns /var/service
e in pochi secondi il nostro DNS per liste RBL sarà completamente funzionante!
Il sistema si metterà in ascolto sulla porta 53 dell'indirizzo IP indicato in fase di configurazione, le interrogazioni che accetterà saranno del tipo 4.3.2.1.base (dove base è la stringa scelta precedentemente), e la risposta sarà positiva se l'indirizzo IP 1.2.3.4 è presente nel database di rbldns.

4.4.2. La lista RBL

Ora che abbiamo visto il funzionamento generale di rbldns vediamo di scoprire come gestire la lista degli indirizzi IP. Fondamentalmente i dati che possiamo inserire nel file data, presente nella directory root sono tre:

Saltiamo la parte che riguarda i commenti e andiamo subito a preparare la nostra lista di indirizzi IP; per primo definiamo i valori di base della lista, ovvero un indirizzo IP da restituire per tutte le interrogazioni che arriveranno e un testo da restituire per le interrogazioni di tipo TXT, normalmente questo testo descriverà brevemente la lista oppure il motivo per cui l'indirizzo IP è presente in essa. La sintassi è:
	:indirizzo_ip:testo
normalmente come indirizzo_ip si utilizza un valore arbitrario (tipo 127.0.0.2) mentre il testo può essere un breve testo descrittivo come accennato precedentemente, in più se al termine della nostra stringa inseriamo un simbolo $ questo verrà sostituito con l'indirizzo IP che è eventualmente presente in lista. Passiamo ora ad inserire gli indirizzi IP veri e propri, per inserire un IP basta semplicemente indicarlo:
	1.2.3.4
Oltre al singolo indirizzo IP è possibile indicare un'intera classe di indirizzi, se ad esempio volessi mettere in lista tutti gli indirizzi che vanno da 192.168.0.1 fino a 192.168.0.255 basterà aggiungere la linea:
	192.168.0.0/24
Vediamo ora un esempio reale di lista RBL utilizzata per bloccare lo spam in arrivo da alcuni indirizzi conosciuti, definiamo la lista inserendo nel file root/data queste righe:
	# lista RBL privata
	:127.0.0.2:tu sei uno spammer $

	192.168.0.0/24
	10.0.0.1
ultimata la fase di editing daremo il comando make in modo da aggiornare il file data.cdb (come succedeva per le zone di tinydns), ora la nostra lista RBL è pronta, e conterrà tutti gli indirizzi IP della classe C 192.168.0.x e l'indirizzo 10.0.0.1, vediamo come arrivano (e se arrivano) le risposte utilizzando i client per le interrogazioni ai DNS. Partiamo con dnsq (che fa parte dei vari tool di djbdns) e facciamo una interrogazione (per la sintassi del comando consiglio di leggere la relativa manpage, presto integrerò) el documento anche una breve descrizione di questi comandi)
	home:~% dnsq txt 1.0.168.192.rbl.local 127.0.0.1
	16 1.0.168.192.rbl.local:
	82 bytes, 1+1+0+0 records, response, authoritative, noerror
	query: 16 1.0.168.192.rbl.local
	answer: 1.0.168.192.rbl.local 2048 16 \036tu\040sei\040uno\040spammer\040192.168.0.1

	home:~% dnsq a 1.0.168.192.rbl.local 127.0.0.1
	1 1.0.168.192.rbl.local:
	55 bytes, 1+1+0+0 records, response, authoritative, noerror
	query: 1 1.0.168.192.rbl.local
	answer: 1.0.168.192.rbl.local 2048 A 127.0.0.2
nella prima interrogazione ho richiesto al server in ascolto su 127.0.0.1 se esisteva un record di tipo TXT dell'indirizzo IP 192.168.0.1 ed ho ottenuto una risposta positiva (ovvero l'IP è presente in lista) con il relativo testo descrittivo (notate come gli spazi vengono scritti in ottale), con la seconda richiesta invece chiediamo solo se esite un record di tipo A, e se ciò è vero otterremo il valore 127.0.0.2. Come avrete potuto notare, gli indirizzi che vado di volta in volta a controllare vengono inviati scritti al rovescio, seguiri da nome che ho scelto per la mia lista (parametro base di rbldns-conf visto precedentemente), quindi se volessi controllare l'indirizzo IP:
	A.B.C.D
nella lista rbl.pippo.it dovrei inviare una richiesta di tipo A oppure TXT per il nome:
	D.C.B.A.rbl.pippo.it
Per concludere vediamo le due richieste precenti fatte questa volta con un altro strumento forse più conosciuto, ovvero dig:
	home:~% dig @127.0.0.1 txt 1.0.168.192.rbl.local

	; <<>> DiG 8.3 <<>> @127.0.0.1 txt 1.0.168.192.rbl.local 
	; (1 server found)
	;; res options: init recurs defnam dnsrch
	;; got answer:
	;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4
	;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
	;; QUERY SECTION:
	;;      1.0.168.192.rbl.local, type = TXT, class = IN

	;; ANSWER SECTION:
	1.0.168.192.rbl.local.  34m8s IN TXT    "tu sei uno spammer 192.168.0.1"

	;; Total query time: 2 msec
	;; FROM: home.morettoni.local to SERVER: 127.0.0.1  127.0.0.1
	;; WHEN: Mon Nov 24 09:42:13 2003
	;; MSG SIZE  sent: 39  rcvd: 82

	home:~% dig @127.0.0.1 a 1.0.168.192.rbl.local

	; <<>> DiG 8.3 <<>> @127.0.0.1 a 1.0.168.192.rbl.local 
	; (1 server found)
	;; res options: init recurs defnam dnsrch
	;; got answer:
	;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4
	;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
	;; QUERY SECTION:
	;;      1.0.168.192.rbl.local, type = A, class = IN

	;; ANSWER SECTION:
	1.0.168.192.rbl.local.  34m8s IN A      127.0.0.2

	;; Total query time: 1 msec
	;; FROM: home.morettoni.local to SERVER: 127.0.0.1  127.0.0.1
	;; WHEN: Mon Nov 24 09:42:17 2003
	;; MSG SIZE  sent: 39  rcvd: 55

4.5. Zone transfer: axfrdns

Fin'ora abbiamo analizzato il funzionamento dei due componenti principali di djbdns, tuttavia abbiamo trascurato un meccanismo importantissimo per i server di tipo authoritative, ovvero lo zone transfer. Rapidamente diciamo che ogni dominio deve avere un DNS di tipo authoritative primario e almeno uno secondario, ogni volta che vengono apportate delle modifiche nel server primario alle informazioni riguardanti il dominio, queste devono essere "comunicate" anche a tutti i secondari, appunto attraverso il meccanismo dello "zone transfer".
Esistono due casi da tenere in considerazione: sia il primario che il secondario utilizzano tinydns oppure uno o più secondari usano BIND.
La soluzione al primo caso è decisamente semplice e sicura, infatti le informazioni sulle zone vengono passate dal primario al secondario attraverso canali sicuri come ad esempio ssh o rsync, semplicemente copiando il file data.cdb usato da tinydsn. E' possibile modificare il Makefile presente nella directory root di tinydns inserendo un nuovo target del tipo:

	slaves: data.cdb
		scp data.cdb ip_secondario:/usr/local/etc/tinydns/root/data.cdb.new
		ssh ip_secondario mv /usr/local/etc/tinydns/root/data.cdb.new /usr/local/etc/tinydns/root/data.cdb
oppure è possibile ricorrere a rsync (specie se abbiamo un file data abbastanza grande) per trasmettere esclusivamente le modifiche da apportare al file, in questo caso il nostro Makefile (sempre del primario) diventerà:
	slaves: data.cdb
		rsync -az -e ssh data.cdb ip_secondario:/usr/local/etc/tinydns/root/data.cdb
E' anche consigliabile modificare (o addirittura cancellare) il Makefile negli slave in modo tale da impedire la generazione in locale del database.
Ora andiamo ad affrontare il secondo caso, ovvero effettuare lo zone transfer da tinydns a BIND; normalmente BIND rimane in attesa sulla porta TCP 53 in attesa di richieste da parte degli slave per dare inizio ad un aggiornamento di zona. Nel pacchetto djbdns è disponibile axfrdns il quale si occupa appunto di m
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.