10.2. Chrooting Bind

Attenzione

La trattazione del CHROOT si riferisce esclusivamente a BIND v8.X!

Creare un ambiente chroot per un qualche servizio/demone significa creargli un mini filesystem, su cui si applicherà il comando chroot, che renderà la directory che lo contiene la sua directory root /: se anche riuscissero a violare il servizio, si ritroverebbero un sistema minimo in cui potranno fare ben poco. Di solito si assegnano i file in questa directory a un utente creato appositamente e senza alcun privilegio. Per portare il vostro Bind in un ambiente chroot, dovrete ricompilare dai sorgenti... quindi dovrete avere tutti i tool e librerie necessarie, fate riferimento alla documentazione presente nei sorgenti di Bind, che potete e dovete scaricare da: http://www.isc.org/bind.html, cercate il file bind-src.tar.gz. Per prima cosa create la struttura delle directory che accoglierà il vostro nuovo e fiammante Dns. Io ho usato /chroot/named/, con la seguente struttura risultante:

  /chroot
    +-- /named
          +-- /bin
          +-- /dev
          +-- /etc
                +-- /bind          
          +-- /lib
          +-- /var
                +-- /run
     

Quindi date i seguenti comandi:

mkdir /chroot
mkdir /chroot/named
mkdir /chroot/named/bin
mkdir /chroot/named/dev
mkdir /chroot/named/etc
mkdir /chroot/named/lib
mkdir /chroot/named/etc/bind
mkdir /chroot/named/var
mkdir /chroot/named/var/run
     

Ora creiamo l'utente e il gruppo, io ho usato UID e GID 200, che sulla mia Debian erano liberi, voi controllate che effettivamente sul vostro sistema non siano già assegnati, e fate attenzione quando usate la redirezione!!! Se vi scappa un singolo > invece di >>, potete dire addio ai vostri utenti e gruppi!!!:

echo 'named:x:200:200:Nameserver:/chroot/named:/bin/false' >> /etc/passwd
echo 'named:x:200:' >> /etc/group
echo 'named:x:200:' > /chroot/named/etc/group
     

Ora copiate i file della precedente configurazione di bind nella nuova directory (se avete usato i miei file, vanno tutti in /chroot/named/etc/bind/, tranne named.conf che va in /chroot/named/etc/). In seguito quest'ultimo file andrà modificato in minima parte per indicare i nuovi percorsi.

Siccome vorrete dei bei log, se non avete una versione recente di syslogd che supporti l'opzione -a (non dovreste avere problemi con le moderne distribuzioni, ma comunque controllate la manpage di syslogd per accertarvene) in modo da poter fare ascoltare il vostro demone syslog già presente anche su un altro socket, avete a questo punto due strade da seguire: installare holelogd, prelevabile presso: ftp://ftp.obtuse.com/pub/utils/utils-1.0.tar.gz, configurandolo seguendo le sue istruzioni e avviandolo dallo script con cui avviate bind, prima di questo naturalmente, con un comando simile al seguente:

daemon /usr/local/sbin/holelogd /chroot/named/dev/log
     

(guardate negli script alla fine, le righe sono commentate), oppure configurare bind per fare il log su file invece che via syslog.

Facciamo appartenere i file all'utente creato in precedenza:

chown -R named:named /chroot/named/etc/bind
chown named:named /chroot/named/var/run
     

e copiamo nelle directory di pertinenza alcuni file di supporto, come la libreria C, ricreando anche la sua cache:

cd /chroot/named/lib
cp -p /lib/libc-2.*.so .
ln -s libc-2.*.so libc.so.6
cp -p /lib/ld-2.*.so .
ln -s ld-2.*.so ld-linux.so.2
cp /sbin/ldconfig /chroot/named/bin/
chroot /chroot/named /bin/ldconfig -v
cp /etc/localtime /chroot/named/etc/
mknod /chroot/named/dev/null c 1 3
chmod 666 /chroot/named/dev/null
     

Con questo avete finito di preparare il filesystem base, ora passiamo alla configurazione e compilazione dei sorgenti, nel momento in cui scrivo erano disponibili in versione 8.2.4:

mkdir /usr/local/src/bind
cd /usr/local/src/bind
tar xvzf /percorso/dei/sorgenti/bind-src.tar.gz
     

dovete modificare alcune opzioni nel file src/port/linux/Makefile.set, in particolare cambiare la riga:

DESTRUN=/var/run
     

in modo che diventi:

DESTRUN=/chroot/named/var/run
     

e cambiare tutti i percorsi /usr/... in /usr/local/..., nello stesso file. Ora modificate il file src/bin/named/named.h, cercando la riga:

#include "pathnames.h"
     

e trasformandola come segue, commentandola e aggiungendo altre cose che serviranno durante la compilazione:

/*
#include "pathnames.h"
*/
#define _PATH_NDCSOCK    "/var/run/ndc"
#define _PATH_CONF       "/etc/named.conf"
#define _PATH_DEBUG      "named.run"
#define _PATH_XFERTRACE  "xfer.trace"
#define _PATH_XFERDDT    "xfer.ddt"
#define _PATH_XFER       "/bin/named-xfer"
#define _PATH_DUMPFILE   "named_dump.db"
#define _PATH_STATS      "named.stats"
#define _PATH_MEMSTATS   "named.memstats"
#define _PATH_PIDFILE    "/var/run/named.pid"
#define _PATH_TMPXFER    "xfer.ddt.XXXXXX"
     

A questo punto potete compilare:

cd src
make clean
make depend
make
     

NON date il make install, in quanto a questo punto dovete rimuovere la vostra precedente installazione di bind! Provvedete, usando il metodo adatto alla vostra distribuzione, ma solo DOPO aver fatto una copia di backup dello script che viene usato per avviare il DNS, che dopo modificheremo per adattarlo alla nuova situazione. Di solito questo script è /etc/rc.d/init.d/named nelle distribuzioni tipo RedHat o Mandrake, o /etc/init.d/bind in Debian. Ora potete dare il make install per installare i tool accessori. Gli unici file binari che dovranno finire nell'ambiente chroot sono named e named-xfer, e per sicurezza facciamo in modo che il programma named appena installato in /usr/local/sbin/ non possa essere avviato:

cp src/bin/named/named /chroot/named/bin
cp src/bin/named-xfer/named-xfer /chroot/named/bin
chmod 000 /usr/local/sbin/named
     

Ora cercate lo script di avvio del demone syslogd (di solito nella directory /etc/init.d/ o simile) e modificatelo nelle opzioni di avvio, in modo da aggiungere a quelle giè presenti (di solito "-m 0") anche l'opzione:

-a /chroot/named/dev/log
     

e riavviate syslogd. Dopo il suo riavvio, dovreste trovare il nuovo file /chroot/named/dev/log con caratteristiche simili alle seguenti:

srw-rw-rw-   1 root     root            0 Mar 13 20:58 log
     

Ora modifichiamo lo script di avvio di bind di cui prima avete fatto una copia di riserva (perché l'avete fatto, vero? ;-) ). Seguono 2 versioni di script, per RedHat e Debian, se usate altre distribuzioni, adattateli, tenendo presente che le opzioni da aggiungere sono: -t /chroot/named -u named -g named.

=== Script di avvio per RedHat ===

#!/bin/sh
#
# named           This shell script takes care of starting and stopping
#                 named (BIND DNS server).
#
# chkconfig: 345 55 45
# description: named (BIND) is a Domain Name Server (DNS) \
# that is used to resolve host names to IP addresses.
# probe: true

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

[ -f /chroot/named/bin/named ] || exit 0

[ -f /chroot/named/etc/named.conf ] || exit 0

#echo -n "Starting holelogd: "
#daemon /usr/local/sbin/holelogd /chroot/named/dev/log
#echo "."

# See how we were called.
case "$1" in
  start)
        # Start daemons.
        echo -n "Starting named: "
        daemon /chroot/named/bin/named -u named -g named -t /chroot/named
        echo
        touch /var/lock/subsys/named
        ;;
  stop)
        # Stop daemons.
        echo -n "Shutting down named: "
        killproc named
        rm -f /var/lock/subsys/named
        echo
        ;;
  status)
        /usr/local/sbin/ndc status
        exit $?
        ;;
  restart)
        /usr/local/sbin/ndc -n /chroot/named/bin/named "restart -u named -g named -t /chroot/named"
        exit $?
        ;;
  reload)
        /usr/local/sbin/ndc reload
        exit $?
        ;; 
  probe)
        # named knows how to reload intelligently; we don't want linuxconf
        # to offer to restart every time
        /usr/local/sbin/ndc reload >/dev/null 2>&1 || echo start
        exit 0
        ;;

  *)
        echo "Usage: named {start|stop|status|restart}"
        exit 1
esac

exit 0
     

=== Script di avvio per Debian ===

#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin

test -x /chroot/named/bin/named || exit 0

#echo -n "Starting holelogd: "
#daemon /usr/local/sbin/holelogd /chroot/named/dev/log
#echo "."

case "$1" in
  start)
    echo -n "Starting domain name service: named"
    start-stop-daemon --start --quiet  \
        --exec /chroot/named/bin/named -- -g named -u named -t /chroot/named
    echo "."    
    ;;

  stop)
    echo -n "Stopping domain name service: named"
    start-stop-daemon --stop --quiet --pidfile /chroot/named/var/run/named.pid  \
        --exec /chroot/named/bin/named -- -g named -u named -t /chroot/named
    echo "."    
    ;;

  restart)
    /usr/local/sbin/ndc -n /chroot/named/bin/named "restart -u named -g named -t /chroot/named"
    ;;
    
  reload)
    /usr/local/sbin/ndc reload
    ;;

  force-reload)
        $0 restart
    ;;

  *)
    echo "Usage: /etc/init.d/bind {start|stop|reload|restart|force-reload}" >&2
    exit 1
    ;;
esac

exit 0
     

Le ultime modifiche riguardano il file /chroot/named/etc/named.conf, per indicare le nuove posizioni dei file. Ecco il file modificato:

options {
    directory "/etc/bind";
    pid-file "/var/run/named.pid";
    named-xfer "/bin/named-xfer";
    #query-source address * port 53;
    allow-transfer {
        127.0.0.1;
        192.168.0.0/24;
    };
    allow-query {
        127.0.0.1;
        192.168.0.0/24;
    };
    forward first;
    forwarders {
        193.70.152.25;
        193.70.192.25;
        195.130.224.18;
        195.130.225.129;
    };
};

// extra block for ndc to work in chroot jail - maybe redundant
controls {
    unix "/var/run/ndc" perm 0600 owner 0 group 0;
};

// reduce log verbosity on issues outside our control
logging {
    category lame-servers { null; };
    category cname { null; };
};

// prime the server with knowledge of the root servers
zone "." {
        type hint;
        file "/etc/bind/db.root";
};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912
zone "localhost" {
        type master;
        file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
        type master;
        file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
        type master;
        file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
        type master;
        file "/etc/bind/db.255";
};

// local area network
zone "mrshark.home" {
    type master;
    file "/etc/bind/mrshark.home";
};
zone "0.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/mrshark.home.rev";
};
     

Con questo, dopo aver riavviato, dovreste avere il vostro DNS funzionante in ambiente Chroot! Un ultimo consiglio: ogni tanto saltano fuori bug anche rilevanti in questo software, quindi vorrete sicuramente aggiornare all'ultima versione disponibile per risolverli. NON dovete rifare tutto da capo! Dovete seguire solo i passi per la modifica dei sorgenti di bind, la sua ricompilazione e la sua installazione/copia di file nell'ambiente Chroot. Il resto dei passaggi vanno fatti solo alla prima installazione! ;-) Per provare che tutto sia andato bene, controllate nei file di syslog ci siano le chiamate di avvio di named e dell'avvenuto chroot e cambio di UID/GID, e usate lsof per controllare che i socket relativi al DNS appartengono agli UID/GID del vostro named. Dovreste avere un output simile al seguente:

Aug 17 07:46:12 pingu named[1066]: starting (/etc/named.conf).  named 8.2.4-REL Thu Jul 12 16:14:49 CEST 2001 ^Iroot@pingu:/usr/local/src/bind-8.2.4/src/bin/named
Aug 17 07:46:12 pingu named[1066]: hint zone "" (IN) loaded (serial 0)
Aug 17 07:46:12 pingu named[1066]: master zone "localhost" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: master zone "127.in-addr.arpa" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: master zone "0.in-addr.arpa" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: master zone "255.in-addr.arpa" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: master zone "mrshark.home" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: master zone "0.168.192.in-addr.arpa" (IN) loaded (serial 1)
Aug 17 07:46:12 pingu named[1066]: listening on [127.0.0.1].53 (lo)
Aug 17 07:46:12 pingu named[1066]: listening on [192.168.0.1].53 (eth0)
Aug 17 07:46:12 pingu named[1066]: listening on [151.26.33.74].53 (ppp0)
Aug 17 07:46:12 pingu named[1066]: Forwarding source address is [0.0.0.0].1049
Aug 17 07:46:12 pingu named[1067]: chrooted to /chroot/named
Aug 17 07:46:12 pingu named[1067]: group = named
Aug 17 07:46:12 pingu named[1067]: user = named
Aug 17 07:46:12 pingu named[1067]: Ready to answer queries.