When a DNS server resolves a query, it returns the answer to the client. The DNS server also stores the answer in its cache for the period of time that was allowed by the record’s TTL value. This way any subsequent requests are processed faster when the nameserver is asked to resolve the same names again. Caching-only server does not forward any zones.
Software
Software used in this article:
- Debian Wheezy
- Bind 9.8.4
Before We Begin
We are going to to set up a general purpose DNS server, which:
- Acts as master for two internal zones, and
- Acts as cache server for all other requests.
BIND server’s info:
- Hostname: dns.
- IP: 10.10.1.2.
- LAN: 10.10.1.0/24.
Two internal DNS zones will be setup:
- lan.local – a forward zone, translates domain names into IP addresses.
- 1.10.10 – a reverse zone, translates IP addresses into domain names.
DNS server will be secured by:
- Running BIND with less privileges.
- Limiting queries to LAN only.
- Limiting zone transfers to LAN only.
- Hiding the BIND version number and hostname from being disclosed.
- Configuring iptables to allow access to TCP/UDP ports 53 from LAN only.
Installation
Install BIND and resolvconf packages:
# apt-get update && apt-get install bind9 bind9utils resolvconf
Start BIND on boot:
# update-rc.d bind9 defaults update-rc.d: using dependency based boot sequencing
The dnsutils package contains dig and nslookup:
# apt-get install dnsutils
Our server’s network configuration is as below:
# cat /etc/network/interfaces auto lo iface lo inet loopback allow-hotplug eth0 iface eth0 inet static address 10.10.1.2 netmask 255.255.255.0 gateway 10.10.1.1 broadcast 10.10.1.255 dns-namesevers 127.0.0.1
Restart network configuration if any changes have been made:
# nohup sh -c "ifdown eth0 && ifup eth0"
Update the /etc/resolv.conf
file:
# resolvconf -u
Configuration
First thing to do is to make sure that BIND is not kept running with root privileges. Open /etc/default/bind9
and add the following line if one is not yet present:
OPTIONS="-u bind"
This tells the BIND service to setuid to the “bind” user after completing privileged operations, such as creating sockets that listen on privileged ports.
/etc/bind/named.conf
Some comments are provided. You are advised to check BIND v9.8 documentation for more info.
include "/etc/bind/rndc.key"; include "/etc/bind/named.conf.default-zones"; # Declaring control channels to be used by the rndc utility. controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; }; # Limiting access to local networks only. acl "clients" { 127.0.0.0/8; 10.10.1.0/24; }; # Global server configuration. options { directory "/var/cache/bind"; pid-file "/var/run/named/named.pid"; dump-file "/var/cache/bind/named.dump"; statistics-file "/var/cache/bind/named.stats"; # no forwarding, plus listen on IPv4 only forwarders {}; listen-on-v6 { none; }; # Maximum number of simultaneous client TCP connections to accept. tcp-clients 50; # Disable built-in server information zones. version none; hostname none; server-id none; # Attempt to do all the work required to answer the query. recursion yes; recursive-clients 500; allow-recursion { clients; }; allow-query { clients; }; # Only LAN users are allowed to receive zone transfers from the server. allow-transfer { clients; }; auth-nxdomain no; notify no; dnssec-enable yes; dnssec-validation auto; }; # Specifications of what to log, and where the log messages are sent. logging { channel "common_log" { file "/var/log/bind/named.log" versions 10 size 5m; severity error; print-category yes; print-severity yes; print-time yes; }; category default { "common_log"; }; category general { "common_log"; }; category queries { "common_log"; }; category client { "common_log"; }; category security { "common_log"; }; category query-errors { "common_log"; }; category lame-servers { null; }; }; # Internal zone definitions. zone "lan.local" { type master; file "/etc/bind/db.lan.local"; }; zone "1.10.10.in-addr.arpa" { type master; file "/etc/bind/db.1.10.10"; };
/etc/bind/db.lan.local
$TTL 86400 @ IN SOA localhost. root.localhost. ( 2014082401 ; Serial 86400 ; Refresh 3600 ; Retry 604800 ; Expire 7200 ) ; Negative Cache TTL @ IN NS localhost. @ IN A 10.10.1.2 dns IN A 10.10.1.2 gw IN A 10.10.1.1 www IN A 10.10.1.17
/etc/bind/db.1.10.10
$TTL 86400 @ IN SOA localhost. root.localhost. ( 2014082401 ; Serial 86400 ; Refresh 3600 ; Retry 604800 ; Expire 7200 ) ; Negative Cache TTL @ IN NS localhost. 1 IN PTR gw.lan.local. ;10.10.1.1 2 IN PTR dns.lan.local. ;10.10.1.2 17 IN PTR www.lan.local. ;10.10.1.17
Verify BIND Configuration
# named-checkconf /etc/bind/named.conf
Restart the Service
# service bind9 restart
Verify the service is listening on TCP/UDP ports 53:
# netstat -nltup | grep :53 tcp 0 0 10.10.1.2:53 0.0.0.0:* LISTEN 10905/named tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 10905/named udp 0 0 10.10.1.2:53 0.0.0.0:* 10905/named udp 0 0 127.0.0.1:53 0.0.0.0:* 10905/named
Configure Iptables on the BIND Server to Allow LAN Access
# iptables -A INPUT -s 10.10.1.0/24 -p tcp --dport 53 -j ACCEPT # iptables -A INPUT -s 10.10.1.0/24 -p udp --dport 53 -j ACCEPT
Quering DNS Server from a Client PC
Caching DNS Server
Verify that the BIND server is caching queries:
$ dig kernel.org | grep time ;; Query time: 237 msec
$ dig kernel.org | grep time ;; Query time: 1 msec
Note that cache data is discarded when BIND is restarted.
DNS Zone Transfer
This does not work if “allow-transfer { none; };” is specified in the named.conf
.
$ host -l lan.local lan.local name server localhost. lan.local has address 10.10.1.2 dns.lan.local has address 10.10.1.2 gw.lan.local has address 10.10.1.1 www.lan.local has address 10.10.1.17
To make dig output more readable:
$ alias dig='dig +noquestion +nocomments +nostats'
You can also use something like “dig +noall +answer”.
$ dig @lan.local lan.local axfr ; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +noquestion +nocomments +nostats @lan.local lan.local axfr ; (1 server found) ;; global options: +cmd lan.local. 3600 IN SOA localhost. root.localhost. 2014082401 86400 3600 604800 7200 lan.local. 3600 IN NS localhost. lan.local. 3600 IN A 10.10.1.2 dns.lan.local. 3600 IN A 10.10.1.2 gw.lan.local. 3600 IN A 10.10.1.1 www.lan.local. 3600 IN A 10.10.1.17 lan.local. 3600 IN SOA localhost. root.localhost. 2014082401 86400 3600 604800 7200
Reverse DNS Lookup
$ dig -x 10.10.1.2 ; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +noquestion +nocomments +nostats -x 10.10.1.2 ;; global options: +cmd 2.1.10.10.in-addr.arpa. 3600 IN PTR dns.lan.local. 1.10.10.in-addr.arpa. 3600 IN NS localhost. localhost. 604800 IN A 127.0.0.1 localhost. 604800 IN AAAA ::1
Query BIND Server’s Version and Hostname
Get BIND version. This does not work if “version none;” is specified in the named.conf
.
$ dig @lan.local version.bind chaos txt ; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +noquestion +nocomments +nostats @lan.local version.bind chaos txt ; (1 server found) ;; global options: +cmd version.bind. 0 CH TXT "9.8.4-rpz2+rl005.12-P1" version.bind. 0 CH NS version.bind.
Get BIND hostname. This does not work if “hostname none;” is specified in the named.conf
.
$ dig @lan.local hostname.bind chaos txt ; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +noquestion +nocomments +nostats @lan.local hostname.bind chaos txt ; (1 server found) ;; global options: +cmd hostname.bind. 0 CH TXT "dns" hostname.bind. 0 CH NS hostname.bind.
Troubleshooting
Check syslog:
# grep named /var/log/syslog | less
Check BIND log:
# tail /var/log/bind/named.log