wiki:bind

Name service using bind

Installation

sudo apt-get update
sudo apt-get install bind9 bind9utils

Configure primary

Change to configuration directory /etc/bind

If using rfc1918-Addresses in own network, comment the corresponding lines in zones.rfc1918, e.g. using 192.168.*.*-Addresses, change the file in

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

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

make directory for zones mkdir zones

and configure forwarding zone, e.g. by vi zones/db.rhein-main-festival.org:

;
; BIND forward data file for rhein-main-festival.org
;
$TTL	604800
@	IN	SOA	dns1.rhein-main-festival.org. admin.dns1.rhein-main-festival.org. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
	IN	NS	dns1.rhein-main-festival.org.
	IN	NS	dns2.rhein-main-festival.org.
;
dns1.rhein-main-festival.org.	IN	A	192.168.178.44
dns2.rhein-main-festival.org.	IN	A	192.168.178.22
;
home1.rhein-main-festival.org.	IN	A	192.168.178.38
home2.rhein-main-festival.org.	IN	A	192.168.178.41
;
trac.rhein-main-festival.org.	IN	A	192.168.178.42
;
mini.rhein-main-festival.org.	IN	A	192.168.178.23

and reverse zone for local network, e.g. in vi zones/db.178.168.192

;
; BIND reverse data file for managed network 192.168.178.0/24
;
$TTL	604800
@	IN	SOA	dns1.rhein-main-festival.org. admin.dns1.rhein-main-festival.org. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
	IN	NS	dns1.rhein-main-festival.org.
	IN	NS	dns2.rhein-main-festival.org.
;
44	IN	PTR	dns1.rhein-main-festival.org.
22	IN	PTR	dns2.rhein-main-festival.org.
38	IN	PTR	home1.rhein-main-festival.org.
41	IN	PTR	home2.rhein-main-festival.org.
42	IN	PTR	trac.rhein-main-festival.org.
23	IN	PTR	mini.rhein-main-festival.org.

In named.conf.options add a acl to restrict access to local network, just at the head of the file:

acl "trusted" {
	localnets;	# local network
};

and add some options in the options block, e.g.g behind the directory-option:

.
.
.
	directory "/var/cache/bind";

        allow-query { trusted; };
        recursion yes;                 # enables resursive queries
        allow-recursion { trusted; };  # allows recursive queries from "trusted" clients
        listen-on { any; };   # ns1 private IP address - listen on private network only
        allow-transfer { none; };      # disable zone transfers by default

set a forwarder for all foreign addresses:

	forwarders {
		192.168.178.1;
	};

Finally enable the local configs in named.conf.local:

zone "rhein-main-festival.org" {
    type master;
    file "/etc/bind/zones/db.rhein-main-festival.org"; # zone file path
    allow-transfer { 192.168.178.22; };         # ns2 private IP address - secondary
};

zone "178.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.178.168.192";  # 192.168.178.0/24 subnet
    allow-transfer { 192.168.178.22; };  # ns2 private IP address - secondary
};

check the configuration running

$ sudo named-checkconf
$ sudo named-checkzone rhein-main-festival.org zones/db.rhein-main-festival.org
zone rhein-main-festival.org/IN: loaded serial 1
OK
$ sudo named-checkzone 178.168.192.in-addr.arpa zones/db.178.168.192
zone 178.168.192.in-addr.arpa/IN: loaded serial 1
OK

...and restart the service with sudo service bind9 restart.

Check for obvious problems in syslog using sudo tail -30 /var/log/syslog and do some testing with nslookup - localhost

Configure secondary

Once again, change to /etc/bind and - if you'd like to be sure, reflect your networks in zones.rfc1918

Then, create a directory slaves and make it owned by bind:bind:

$ sudo mkdir slaves
$ sudo Clown bind:bind slaves

Edit named.conf.options using exactly the options as you did on primary. Finally edit named.conf.local to add your configuration:

zone "rhein-main-festival.org" {
    type slave;
    file "/etc/bind/slaves/db.rhein-main-festival.org"; # zone file path
    masters { 192.168.178.44; };         # dns1 private IP address - primary
};

zone "178.168.192.in-addr.arpa" {
    type slave;
    file "/etc/bind/slaves/db.178.168.192";  # 192.168.178.0/24 subnet
    masters { 192.168.178.44; };  # dns1 private IP address - primary
};

Restart the service, check the syslog and test. You should find the transferred zones in the slaves-directory:

$ sudo service bind9 restart
$ sudo tail -35 /var/log/syslog
$ ls -l slaves/
-rw-r--r-- 1 bind bind 756 Apr 24 08:20 db.178.168.192
-rw-r--r-- 1 bind bind 604 Apr 24 08:20 db.rhein-main-festival.org
$ nslookup - localhost

Common Pitfalls

  • Forgotten to increment the serial

This may result in the server working on the old data.

  • Forgotten dot at end of name

This will result in the domain being added to the entry

  • slaves-directory not owned by bind

Server will come up but cannot transfer the zone

LDAP gateway

#!/bin/bash

#
### INCLUDE USEFUL COMMANDS

#. /opt/infra/script/include.sh
DOMAIN="dc=pribas,dc=com"
SEARCH="ldapsearch -h 10.1.0.99 -T"

#
### CONFIGURATION

## GET NETWORKS

NET=""
NET="$($SEARCH -b ou=networks,$DOMAIN objectClass=top ipNetworkNumber | grep ipNetworkNumber | cut -d':' -f2 | tr -d ' ')"

NETWORKS=""
for ent in $NET
do
        net=$($SEARCH -b ou=networks,$DOMAIN ipNetworkNumber=$ent | grep "cn=" | cut -d':' -f2 | cut -d'=' -f2| cut -d',' -f1) 
        ip=$(echo "$ent") 
        ip1=$(echo "$ip"|cut -d'.' -f1) 
        ip2=$(echo "$ip"|cut -d'.' -f2) 
        ip3=$(echo "$ip"|cut -d'.' -f3) 
        ip4=$(echo "$ip"|cut -d'.' -f4) 
        NETWORKS="$ip1.$ip2.$ip3 $NETWORKS"
done

SERIAL=$(date +%y%m%d%H%M)
NEWDIR="bind.$SERIAL"
HOSTNAME=$(hostname)
###
#

#
### test prerequisits
test ! -L /etc/bind && echo "/etc/bind is not a link, exiting!!" && exit 1
test ! -d template && echo "templates not in place, exiting!!" && exit 1
if [ $(pfexec id|cut -d' ' -f3) != "euid=0(root)" ]
then
        echo "Unable to become root. Exiting"
        exit 1
fi
###
#

#
### Prepare new directory
rm -rf $NEWDIR/
cp -rp template $NEWDIR/
sed -e "s/HOSTNAME/$HOSTNAME/" -e "s/SERIAL/$SERIAL/" $NEWDIR/db.pribas.template > $NEWDIR/db.pribas
sed -e "s/HOSTNAME/$HOSTNAME/" -e "s/SERIAL/$SERIAL/" $NEWDIR/db.infra.template > $NEWDIR/db.infra
###
#

#
### generate new dns tables

#--------------------
## ZONES
#--------------------

UNITS=""
UNITS="$($SEARCH -b ou=Hosts,$DOMAIN -s one objectClass=organizationalUnit ou | grep "ou:" | cut -d':' -f2 | tr -d ' ')"

ZONE=""
for ent in $UNITS
do
        UNITS2="$($SEARCH -b ou=$ent,ou=hosts,$DOMAIN -s one objectClass=organizationalUnit dn | grep "ou=" | cut -d'=' -f2 | cut -d',' -f1| tr -d ' ')";
                for ent2 in $UNITS2
                do
                        if [ "$ent2" != "" ]; 
                        then 
                                ZONE="$($SEARCH -b ou=$ent2,ou=$ent,ou=hosts,$DOMAIN -s one objectClass=top ipHostNumber | grep ipHostNumber | cut -d':' -f2 | tr -d ' ')"
                                        for ent3 in $ZONE
                                        do
                                                zn=$($SEARCH -b ou=hosts,$DOMAIN ipHostNumber=$ent3 | grep "dn:" | grep "cn=" | cut -d':' -f2 | cut -d'=' -f2| cut -d',' -f1)
                                                ip=$(echo "$ent3")
                                                ip1=$(echo "$ip"|cut -d'.' -f1)
                                                ip2=$(echo "$ip"|cut -d'.' -f2)
                                                ip3=$(echo "$ip"|cut -d'.' -f3)
                                                ip4=$(echo "$ip"|cut -d'.' -f4)

                                                        for number in $zn
                                                        do
                                                                if expr  "$NETWORKS" : ".*$ip1.$ip2.$ip3">/dev/null
                                                                then
                                                                        if [ "$(grep "$number IN A $ip" $NEWDIR/db.pribas)" == "" ]
                                                                        then
                                                                                echo "$number IN A $ip">>$NEWDIR/db.pribas

                                                                                        if ! test -e $NEWDIR/db.$ip3.$ip2.$ip1
                                                                                        then
                                                                                                sed -e "s/HOSTNAME/$HOSTNAME/" -e "s/SERIAL/$SERIAL/" $NEWDIR/db.reverse > $NEWDIR/db.$ip3.$ip2.$ip1
                                                                                                echo >>$NEWDIR/named.conf.local
                                                                                                echo "zone \"$ip3.$ip2.$ip1.in-addr.arpa\" {">>$NEWDIR/named.conf.local
                                                                                                echo "  type master;">>$NEWDIR/named.conf.local
                                                                                                echo "  file \"/etc/bind/db.$ip3.$ip2.$ip1\";">>$NEWDIR/named.conf.local
                                                                                                echo "};">>$NEWDIR/named.conf.local
                                                                                        fi
                                                                                echo "$ip4 IN PTR $number.">>$NEWDIR/db.$ip3.$ip2.$ip1
                                                                        fi
                                                                fi
                                                        done
                                                done
                        fi
                done
        ZONE2="$($SEARCH -b ou=$ent,ou=hosts,$DOMAIN -s one objectClass=top ipHostNumber | grep ipHostNumber | cut -d':' -f2 | tr -d ' ')"
                for ent4 in $ZONE2
                do
                        zn=$($SEARCH -b ou=hosts,$DOMAIN ipHostNumber=$ent4 | grep "dn:" | grep "cn=" | cut -d':' -f2 | cut -d'=' -f2| cut -d',' -f1)
                        ip=$(echo "$ent4")
                        ip1=$(echo "$ip"|cut -d'.' -f1)
                        ip2=$(echo "$ip"|cut -d'.' -f2)
                        ip3=$(echo "$ip"|cut -d'.' -f3)
                        ip4=$(echo "$ip"|cut -d'.' -f4)

                                for number in $zn
                                do
                                        if expr  "$NETWORKS" : ".*$ip1.$ip2.$ip3">/dev/null
                                        then
                                                if [ "$(grep "$number IN A $ip" $NEWDIR/db.pribas)" == "" ]
                                                then
                                                        echo "$number IN A $ip">>$NEWDIR/db.pribas

                                                                if ! test -e $NEWDIR/db.$ip3.$ip2.$ip1
                                                                then
                                                                        sed -e "s/HOSTNAME/$HOSTNAME/" -e "s/SERIAL/$SERIAL/" $NEWDIR/db.reverse > $NEWDIR/db.$ip3.$ip2.$ip1
                                                                        echo >>$NEWDIR/named.conf.local
                                                                        echo "zone \"$ip3.$ip2.$ip1.in-addr.arpa\" {">>$NEWDIR/named.conf.local
                                                                        echo "  type master;">>$NEWDIR/named.conf.local
                                                                        echo "  file \"/etc/bind/db.$ip3.$ip2.$ip1\";">>$NEWDIR/named.conf.local
                                                                        echo "};">>$NEWDIR/named.conf.local
                                                                fi
                                                        echo "$ip4 IN PTR $number.">>$NEWDIR/db.$ip3.$ip2.$ip1
                                                fi
                                        fi
                                done
                done
done

###
#

#
### remove helpers
rm $NEWDIR/db.reverse
rm $NEWDIR/db.pribas.template
rm $NEWDIR/db.infra.template
###
#

#
### Figure out, if any change happend - maybe we can avoid the restart, because nothing changed
changed=""
for file in $(ls $NEWDIR/)
do
        test ! -e /etc/bind/$file && changed="new:$file $changed"
                if (( $(diff $NEWDIR/$file /etc/bind/$file|wc -l) > 4 ))
                then
                changed="$file $changed"
                fi
done
###
#
test -n "$changed" && echo "($SERIAL) changed: $changed"
test -z "$changed" && echo "($SERIAL) nothing changed" && rm -rf $NEWDIR/ && exit 0

#
### bring new files in place
pfexec mv $NEWDIR /etc/
test -L /etc/bind && pfexec rm /etc/bind && pfexec ln -s /etc/$NEWDIR /etc/bind
###
#

#
### restart dns and check for success
if pfexec kill -1 $(ps -ef|grep named|grep -v grep|awk '{print$2}')
then
        echo "Success!"
        exit 0
else
        echo "Restart failed!"
        exit 1
fi
###
#

template/db.infra:

;; db.infra
;; Forwardlookupzone für pribas
;;
$TTL 2D
@       IN      SOA     HOSTNAME.pribas. hostmaster.pribas.com. (
                        SERIAL      ; Serial
                                4H      ; Refresh
                                2H      ; Retry
                                1W      ; Expire
                                1D )    ; TTL Negativ Cache

@                               IN      NS      HOSTNAME.pribas.
                                IN      MX      10 cs-mail-brem-p.

localhost                       IN      A       127.0.0.1
cs-mail-brem-p                  IN      A       10.1.0.251
infra                           IN      CNAME   cs-mail-brem-t

template/db.pribas.template:

;; db.pribas
;; Forwardlookupzone für pribas
;;
$TTL 2D
@       IN      SOA     HOSTNAME.pribas. hostmaster.pribas.com. (
                        SERIAL      ; Serial
                                4H      ; Refresh
                                2H      ; Retry
                                1W      ; Expire
                                1D )    ; TTL Negativ Cache

@                               IN      NS      HOSTNAME.pribas.
                                IN      MX      10 HOSTNAME.pribas.
                                IN      MX      20 mail.pribas.

localhost                       IN      A       127.0.0.1
s3                              IN      CNAME   mail
groupware                       IN      CNAME   mail
ldap                            IN      CNAME   mail
nagios                          IN      CNAME   infraserv
;bacula                          IN      CNAME   infraserv

template/db.reverse:

$TTL 2D
@       IN      SOA     HOSTNAME.pribas. hostmaster.pribas.com. (
                                SERIAL      ; Serial
                                        8H      ; Refresh
                                        2H      ; Retry
                                        4W      ; Expire
                                        2D )    ; TTL Negative Cache

@       IN      NS      HOSTNAME.pribas.

template/named.conf.local:

//
// Do any local configuration here
//

zone "pribas" {
        type master;
        file "/etc/bind/db.pribas";
};

zone "infra" {
        type master;
        file "/etc/bind/db.infra";
};

template/named.conf.options:

acl internals { 127.0.0.1/32; 192.168.1.0/24; 10.1.10.0/24; 10.1.11.0/24; 10.1.0.0/24; 10.1.12.0/24; 10.1.20.0/24; 10.1.3.0/24; 10.2.20.0/24; 10.4.20.0/24;};

options {
        directory "/var/cache/bind";

        // If there is a firewall between you and nameservers you want
        // to talk to, you might need to uncomment the query-source
        // directive below.  Previous versions of BIND always asked
        // questions using port 53, but BIND 8.1 and later use an unprivileged
        // port by default.

        // query-source address * port 53;

        // If your ISP provided one or more IP addresses for stable 
        // nameservers, you probably want to use them as forwarders.  
        // Uncomment the following block, and insert the addresses replacing 
        // the all-0's placeholder.
        forward only;
        forwarders {
                194.25.0.52;
                194.25.0.60;
                194.25.0.68;
        };

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { };
        listen-on { any; };
        allow-query { internals; };
};
Last modified 4 months ago Last modified on Apr 25, 2018, 7:34:41 AM