Amministrare le zone dns di bind con nsupdate

Condividi:

Benchè sia comodo editare a mano i file di zona di bind, questa pratica espone a tutta una serie di problematica relative ad eventuali errori di sintassi, specialmente con zone complesse di grandi dimensioni

Se inoltre abbiamo a che fare con zone che vengono aggiornate dinamicamente ad esempio da un dhcp, la modifica del file di zona manda fuori sync la zona con il suo journal con il rischio di perdere record contenuti

dnsutils ci mette a disposizione nsupdate, uno strumento in grado di comunicare con bind con cui possiamo aggiungere e cancellare i resource record. Mantiene ordinato il file di zona, si occupa di gestire il file journal ed aggiorna automaticamente il contatore del record SOA

Il server bind su cui operiamo è online all’ indirizzo 127.0.0.1

Abbiamo bisogno di nsupdate contenuto in dnsutils, se non lo abbiamo installiamolo

# apt install dnsutils

Con questo strumento possiamo solo aggiornare zone, non le possiamo creare quindi per partire abbiamo bisogno quindi di una zona minimale, che per essere caricata da bind deve contenere il RR SOA, NS ed A del name server

Prendiamo ad esempio la zona del dominio “local.” costituita dai due file

  • /etc/bind/named.conf.local
    zone "local." {
      type master;
      file "/var/cache/bind/db.local";
    };
  • /var/cache/bind/db.local
    $ORIGIN .
    $TTL 3600       ; 1 hour
    local                   IN SOA  ns.local. hostmaster.local. (
                                    2019021400 ; serial
                                    3600       ; refresh (1 hour)
                                    600        ; retry (10 minutes)
                                    86400      ; expire (1 day)
                                    10800      ; minimum (3 hours)
                                    )
                            NS      ns.local.
                            A       127.0.0.1
    $ORIGIN local.
    ns                      A       127.0.0.1

Testiamo che il dns risponda con dig

# dig +short @127.0.0.1 ns.local
127.0.0.1

Per ovvie ragioni di sicurezza, non è possibile far comunicare in chiaro senza credenziali uno strumento di amministrazione come questo con un server dns. Abbiamo bisogno di una chiave di autenticazione che dobbiamo inserire nel config file di bind e che useremo con nsupdate

Creiamo ed installiamo la chiave TSIG

Lo strumento che ci permette di generare questa chiave è tsig-keygen. Potremmo usare anche dnssec-keygen ma tsig-keygen è più comodo perchè crea già il file .key da includere nel config file di bind

# tsig-keygen -a hmac-md5 local. > local.key

Impostiamo i permessi e spostiamo il file sotto /etc/bind

# chmod 640 local.key
# mv local.key /etc/bind

Visualizziamone il contenuto

# cat /etc/bind/local.key
key "local." {
        algorithm hmac-md5;
        secret "ZDkvtd591mBWHfYC+IOi1w==";
};

Dobbiamo includere questo file nella configurazione di bind ed aggiungere le credenziali di aggiornamento nella dichiarazione della zona local.

  • /etc/bind/named.conf.local

    include "/etc/bind/local.key";
    zone "local." {
      type master;
      file "/var/cache/bind/db.local";
      allow-update { key "local."; };
    };

Ricarichiamo bind e siamo pronti ad usare nsupdate

systemctl reload bind9
Eseguiamo nsupdate
# nsupdate -v -d -k /etc/bind/local.key
Creating key...
Creating key...
namefromtext
keycreate
>

Il client è pronto a ricevere i comandi. Con i comandi server e zone possiamo dire a quale server collegarci e su quale zona vogliamo operare, se non inviamo questi comandi sarà nsupdate a trovare master dns che poi inserirà gli aggiornamenti nella zona che descrive gli host che invieremo

> server 127.0.0.1
> zone local.
  • Per uscire si digita il comando quit o si invia CTRL+D
  • Gli inserimenti e le cancellazioni dei record possono essere inviate sia singolarmente che in serie, ma devono riferirsi alla stessa zona
  • I comandi di aggiornamento vengono caricati nel buffer di nsupdate ed inviati con il comando send
  • I nomi degli host devono sempre essere inseriti in forma qualificata
  • Ogni esecuzione del comando send incrementa il contatore del SOA
Inserimento di record

L’inserimento dei RR avviene con il comando update add

Alcuni record richiedono che venga valorizzato il campo ttl, se digitiamo il valore impostato nella direttiva $TTL non comparirà nel file di zona, un valore diverso invece introdurrà una assegnazione di $TTL prima ed una dopo il RR

> update add www.local. 3600 a 127.0.0.1
> update add api.local. 3600 cname www.local.

Con il comando show vediamo l’elenco di comandi nel buffer che verrà inviato

> show
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:      0
;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; UPDATE SECTION:
www.local.              3600    IN      A       127.0.0.1
api.local.              3600    IN      CNAME   www.local.

Inviamo le modifiche

> send
> quit

I record inseriti sono già online e possiamo verificarlo con dig, tuttavia non sono ancora state salvate nel file di zona

# dig +short -t A www.local.
127.0.0.1
# dig +short -t CNAME api.local.
www.local.

Se eseguiamo un restart di bind vediamo i due record inseriti ed il contatore del SOA incrementato

# systemctl stop bind9
# cat /var/cache/bind/db.local
$ORIGIN .
$TTL 3600       ; 1 hour
local                   IN SOA  ns.local. hostmaster.local. (
                                2019021401 ; serial
                                3600       ; refresh (1 hour)
                                600        ; retry (10 minutes)
                                86400      ; expire (1 day)
                                10800      ; minimum (3 hours)
                                )
                        NS      ns.local.
                        A       127.0.0.1
$ORIGIN local.
api                     CNAME   www
ns                      A       127.0.0.1
www                     A       127.0.0.1
Cancellazione di record

La cancellazione di record avviene con il comando update delete a cui va passato il nome host qualificato. Possono essere specificati tutti i campi del RR, in ogni caso bind cercherà di aggiornare quel RR che meglio corrisponde al RR dichiarato, cosa utile quando si hanno più record con lo stesso host name. Se avessimo un host con un record A ed un AAAA, specificando solo il nome host li elimineremmo entrambi, specificando anche il type ne elimineremmo uno solo

> update delete api.local CNAME
> send
> quit

Possiamo verificare che la modifica è già online in quanto dig non trova più il record CNAME

# dig +short -t CNAME api.local.

E riavviando bind troviamo il file di zona aggiornato con il serial number incrementato di uno

# systemctl restart bind9
# cat /var/cache/bind/db.local
$ORIGIN .
$TTL 3600       ; 1 hour
local                   IN SOA  ns.local. hostmaster.local. (
                                2019021402 ; serial
                                3600       ; refresh (1 hour)
                                600        ; retry (10 minutes)
                                86400      ; expire (1 day)
                                10800      ; minimum (3 hours)
                                )
                        NS      ns.local.
                        A       127.0.0.1
$ORIGIN local.
ns                      A       127.0.0.1
www                     A       127.0.0.1
Utilizzo non interattivo

I comandi possono essere inclusi in un file e fatti eseguire ad nsupdate con una sola riga di comando shell

  • comandi.txt

    update delete www.local. A
    update add www1.local. 3600 A 127.0.0.1
    update add www2.local. 3600 A 127.0.0.1
    update add www3.local. 3600 A 127.0.0.1
    send

Inviamo le modifiche

# nsupdate -v -k /etc/bind/local.key comandi.txt

Riavviamo bind e leggiamo la zona

# systemctl restart bind9
# cat /var/cache/bind/db.local
$ORIGIN .
$TTL 3600       ; 1 hour
local                   IN SOA  ns.local. hostmaster.local. (
                                2019021403 ; serial
                                3600       ; refresh (1 hour)
                                600        ; retry (10 minutes)
                                86400      ; expire (1 day)
                                10800      ; minimum (3 hours)
                                )
                        NS      ns.local.
                        A       127.0.0.1
$ORIGIN local.
ns                      A       127.0.0.1
www1                    A       127.0.0.1
www2                    A       127.0.0.1
www3                    A       127.0.0.1