advanced DNS
(Written by Paul Cobbaut, https://github.com/paulcobbaut/, with contributions by: Alex M. Schapelle, https://github.com/zero-pytagoras/)
This chapter expands your DNS server with topics like round robin dns
for load balancing servers, dns delegation
to delegate child domains
to another team and split horizon dns
so you can provide local service
locations to clients.
There is more to dns
, content will be added rsn
.
example: DNS round robin
When you create multiple A records for the same name, then
bind
will do a round robin
of the order in which the
records are returned. This allows the use of DNS as a load balancer
between hosts, since clients will usually take the first ip-address
offered.
Consider this example from the /etc/bind/db.paul.local
zone
configuration file. There are two A records for www
pointing to two
distinct ip addresses.
root@linux:~# grep www /etc/bind/db.paul.local
www IN A 10.104.33.30
www IN A 10.104.33.31
Below a screenshot of nslookup
querying a load balanced A record.
Notice the order of ip addresses returned.
root@linux:~# nslookup www.paul.local 10.104.33.30
Server: 10.104.33.30
Address: 10.104.33.30#53
Name: www.paul.local
Address: 10.104.33.31
Name: www.paul.local
Address: 10.104.33.30
root@linux:~# nslookup www.paul.local 10.104.33.30
Server: 10.104.33.30
Address: 10.104.33.30#53
Name: www.paul.local
Address: 10.104.33.30
Name: www.paul.local
Address: 10.104.33.31
Try to set up a website on two web servers (with a small difference so
you can distinguish the websites) and test the round robin
.
DNS delegation
You can delegate
a child domain to another DNS server. The child
domain then becomes a new zone, with authority at the new dns server.
When delegation
is properly set up, then clients that query your
parent zone will also be able to resolve the delegated child zones.
example: DNS delegation
We have another Linux server
named debian10b
and we want to make it
responsible for the child domain test42.paul.local
.
Note the name of the servers in the screenshots are either debian10
(hosting the parent domain) or debian10b
(hosting the child domain).
We start by adjusting the /etc/bind/named.comf.local
file (on the
server hosting the parent domain) to make sure that no forwarder will be
used when resolving authoritative names.
root@linux:~# grep -A4 paul.local /etc/bind/named.conf.local
zone "paul.local" IN {
type master;
file "/etc/bind/db.paul.local";
allow-update { none; };
allow-transfer { 10.104.15.20; };
forwarders { };
};
root@linux:~#
Technically, you could also set allow-transfer
to { any; };
while
troubleshooting and then refine it later, but this is not needed for
delegation.
Then we add the delegation to our zone database:
root@linux:~# tail -3 /etc/bind/db.paul.local
$ORIGIN test42.paul.local.
@ IN NS ns2.test42.paul.local.
ns2 IN A 10.104.33.31 ; the glue record
root@linux:~#
Don\'t forget to restart bind
and verify /var/log/syslog
.
root@linux:~# service bind9 restart
Stopping domain name service...: bind9.
Starting domain name service...: bind9.
root@linux:~# grep paul.local /var/log/syslog | cut -c28- | tail -2
named[3202]: zone paul.local/IN: loaded serial 2014100801
named[3202]: zone paul.local/IN: sending notifies (serial 2014100801)
root@linux:~#
Note that on your terminal you can type tail -40 /var/log/syslog
because the only reason I use grep
, cut
and tail -2
is to limit
the size of the screenshots in this book.
Next we create a zone database file on the second server, as seen in this screenshot:
root@linux:~# cat /etc/bind/db.test42.paul.local
; child zone for classroom teaching
$TTL 86400
$ORIGIN test42.paul.local.
@ IN SOA ns2.test42.paul.local. root.test42.paul.local. (
2014100802 ; Serial
1h ; Refresh
1h ; Retry
2h ; Expire
900 ) ; Negative Cache TTL
;
; name servers
;
IN NS ns2.test42.paul.local.
IN NS debian10b.test42.paul.local.
;
; servers
;
ns2 IN A 10.104.33.31
debian10b IN A 10.104.33.31
testsrv IN A 10.104.33.31
root@linux:~#
The second server also needs a zone definition in named.conf.local
,
followed by a restart of bind
.
root@linux:~# cat /etc/bind/named.conf.local
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "test42.paul.local" IN {
type master;
file "/etc/bind/db.test42.paul.local";
allow-update { none; };
allow-transfer { any; };
};
root@linux:~#
Testing on the parent server:
root@linux:~# dig ns1.paul.local +short
10.104.33.30
root@linux:~# dig ns2.test42.paul.local +short
10.104.33.31
root@linux:~# dig debian10b.test42.paul.local +short
10.104.33.31
example: split-horizon dns
Suppose you want to answer dns queries depending on who is asking. For example when someone from the 10.104.15.0/24 network (managed by Jesse) asks for the A record www.paul.local, then dns answers with 10.104.33.30. But when someone from the 10.104.42.0/24 network (managed by Keith) asks for the same A record of www.paul.local, he will get 10.104.33.31 as an answer.
A split-horizon
setup can be used to redirect people to local
copies
of certain services.
In this example we want to decide on specific answers for two networks
(Jesse\'s and Keith\'s) and prevent them from using our dns server for
recursion
, while maintaining the capability to resolve the internet
and our paul.local zone from our own network.
We start by creating three view
clauses in named.conf.local
.
root@linux:/etc/bind# cat named.conf.local
view "paul" {
match-clients { 10.104.33.0; localhost; };
include "/etc/bind/named.conf.default-zones";
zone "paul.local" IN {
type master;
file "/etc/bind/db.paul.local";
allow-update { none; };
};
}; // end view internal
view "jesse" {
match-clients { 10.104.15/24; };
zone "paul.local" IN {
type master;
file "/etc/bind/db.paul.local.jesse";
allow-update { none; };
};
}; // end view jesse
view "keith" {
match-clients { 10.104.42/24; };
zone "paul.local" IN {
type master;
file "/etc/bind/db.paul.local.keith";
allow-update { none; };
};
}; // end view keith
Note that we included the default-zones
in the internal zone. It is
mandatory to put all zones inside views when using a view.
The zone files are identical copies, except for the www
record. You
can see that the round robin
is still active for internal users,
computers from 10.104.15.0/24 (Jesse) will always receive 10.104.33.30
while computers from 10.104.42.0/24 (Keith) will receive 10.104.33.31.
root@linux:/etc/bind# grep www db.paul.local db.paul.local.[jk]*
db.paul.local:www IN A 10.104.33.30
db.paul.local:www IN A 10.104.33.31
db.paul.local.jesse:www IN A 10.104.33.30
db.paul.local.keith:www IN A 10.104.33.31
old dns topics
All the dns things below this paragraph are old and in urgent need of review.
old example: reverse DNS
1. We can add ip to name resolution to our dns-server using a reverse dns zone.
2. Start by adding a .arpa zone to /etc/bind/named.conf.local like this (we set notify to no to avoid sending of notify messages to other name servers):
root@linux:/etc/bind# grep -A4 arpa named.conf.local
zone "1.168.192.in-addr.arpa" {
type master;
notify no;
file "/etc/bind/db.192";
};
3. Also create a zone database file for this reverse lookup zone.
root@linux:/etc/bind# cat db.192
;
; BIND reverse data file for 192.168.1.0/24 network
;
$TTL 604800
@ IN SOA ns.cobbaut.paul root.cobbaut.paul. (
20110516 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.
37 IN PTR ns.cobbaut.paul.
1 IN PTR anya.cobbaut.paul.
30 IN PTR mac.cobbaut.paul.
root@linux:/etc/bind#
4. Test with nslookup or dig:
root@linux:/etc/bind# dig 1.168.192.in-addr.arpa AXFR
old DNS load balancing
Not as above. When you have more than one DNS server authoritative for a zone, you can spread queries amongst all server. One way to do this is by creating NS records for all servers that participate in the load balancing of external queries.
You could also configure different name servers on internal clients.
old DNS notify
The original design of DNS in rfc 1034 and rfc 1035 implemented a
refresh
time in the SOA
record to configure a time loop for slaves
to query their master server. This can result in a lot of useless pull
requests, or in a significant lag between updates.
For this reason dns notify (rfc 1996)
was designed. The server will
now notify slaves whenever there is an update. By default this feature
is activated in bind
.
Notify can be disabled as in this screenshot.
zone "1.168.192.in-addr.arpa" {
type master;
notify no;
file "/etc/bind/db.192";
};
old testing IXFR and AXFR
Full zone transfers (AXFR) are initiated when you restart the bind
server, or when you manually update the zone database file directly.
With nsupdate
you can update a zone database and initiate an
incremental zone transfer.
You need DDNS allowed for nsupdate
to work.
root@linux:/etc/bind# nsupdate
> server 127.0.0.1
> update add mac14.linux-training.be 86400 A 192.168.1.23
> send
update failed: REFUSED
old DDNS integration with DHCP
Some organizations like to have all their client computers in DNS. This
can be cumbersome to maintain. Luckily rfc 2136
describes integration
of DHCP servers with a DNS server. Whenever DHCP acknowledges a client
ip configuration, it can notify DNS with this clients ip-address and
name. This is called dynamic updates
or DDNS.
old reverse is forward in-addr.arpa
Reverse lookup is actually iomplemented as a forward lookup in the
in-addr.arpa
domain. This domain has 256 child domains (from
0.in-addr.arpa to 255.in-addr.arpa), with each child domain having again
256 child domains. And this twice more to a structure of over four
billion (2 to the power 32) domains.
old ipv6
With rfc 3596 came ipv6 extensions for DNS. There is the AAAA record for
ipv6 hosts on the network, and there is the ip6.int
domain for reverse
lookup (having 16 child domains from 0.ip6.int to f.ip6.int, each of
those having again 16 child domains...and this 16 times.
old DNS security: file corruption
To mitigate file corruption on the zone files
and the
bind configuration
files protect them with Unix permissions and take
regular backups.
old DNS security: zone transfers
Limit zone transfers to certain ip addresses instead of to any
.
Nevermind that ip-addresses can be spoofed, still use this.
old DNS security: zone transfers, ip spoofing
You could setup DNSSEC (which is not the easiest to maintain) and with rfc 2845(tsig?) and with rfc 2930(tkey, but this is open to brute force), or you could disable all zone transfers and use a script with ssh to copy them manually.
old DNS security: queries
Allow recursion only from the local network, and iterative queries from outside only when necessary. This can be configured on master and slave servers.
view "internal" {
match-clients { 192.168.42/24; };
recursion yes;
...
};
view "external" {
match-clients { any; };
recursion no;
...
};
Or allow only queries from the local network.
options {
allow-query { 192.168.42.0/24; localhost; };
};
zone "cobbaut.paul" {
allow-query { any; };
};
Or only allow recursive queries from internal clients.
options {
allow-recursion { 192.168.42.0/24; localhost; };
};
old DNS security: chrooted bind
Most Linux distributions allow an easy setup of bind in a chrooted
environment.
old DNS security: DNSSEC
DNSSEC uses public/private keys to secure communications, this is described in rfc\'s 4033, 4034 and 4035.
old DNS security: root
Do not run bind as root. Do not run any application daemon as root.