TSIG,DNSSEC and forward/reverse DNS delegation

Jephe Wu - http://linuxtechres.blogspot.com

Objective: setting up forward and reverse domain classless delegation, TSIG for zone transfer and DNSSEC for security.
Environment: CentOS 6.4 64bit, company domain is jephe.com, class C ip address for jephe.com is a.b.c.0/24.
Forward dns delegation: sg.jephe.com will be delegated to singapore office name server ns1.sg.jephe.com and ns2.sg.jephe.com
Classless reverse dns delegation: APNIC Australia is in charge of reverse DNS in-addr.arpa.
ISP1 will use ip address a.b.c.0-63 (master dns:ns1.jephe.com:a.b.c.1 slave dns:ns2.jephe.com:a.b.c.2);
ISP2 will use ip address a.b.c.64-127 (master dns: ns1.wu.com:a.b.c.65 slave dns:ns2.wu.com:a.b.c.66)



1. start up bind on CentOS 6.4 64bit VM
if it looks like hanging when you try to startup named service, e.g. stop at 'Generating /etc/rndc.key'.
You can modify /etc/init.d/named the following, add -r /dev/urandom and -t /var/named/chroot

 if /usr/sbin/rndc-confgen -r /dev/urandom -t /var/named/chroot -a > /dev/null 2>&1; then

2. chroot by default on CentOS 6.4
you can modify any file under /var/named/, they will be hard-linked to exact same filename with same inode number under  /var/named/chroot/var/named/.

3. forward domain delegation
on Australia name server, run

dnssec-keygen -a HMAC-MD5 -b 128 -n HOST jephe.com

it will generate 2 files which are Kjephe.com.+157+<XXX>.key and Kjephe.com.+157+<XXX>.private

On Australia /etc/named.conf:
----------------
zone "jephe.com" IN {
type master;
file "named.jephe.com";
allow-transfer { key key.jephe.com; };
};

include "jephe.com.key";
;note: jephe.com.key is a file under /var/named/, it contains symmetric keys for TSIG use.
------------

In file named.jephe.com, it looks like this:
--------------
$TTL 600
@ IN SOA jephe.com. admin.jephe.com. (
2013073001 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns1.jephe.com.
NS ns2.jephe.com.
ns1 A a.b.c.1
ns2 A a.b.c.2
www A a.b.c.3
mail A a.b.c.4


sg.jephe.com. 600 NS ns1.sg.jephe.com.
sg.jephe.com. 600 NS ns2.sg.jephe.com.

;now add glue record
ns1.sg.jephe.com. A a.b.c.65
ns2.sg.jephe.com. A a.b.c.66
------------

key file content on both AU and SG dns server is as follows:

[root@jephe named]# more jephe.com.key
key key.jephe.com {
algorithm HMAC-MD5;
secret "p0xJ5Bv5xzuY03QhUDWSjQ==";
};

server a.b.c.65 {
        keys { key.jephe.com; };
};


on Sinagpore dns server /etc/named.conf:
-------------
zone "jephe.com" IN {
type slave;
masters { a.b.c.1; };
file "slaves/named.jephe.com";
};

zone "sg.jephe.com" IN {
type master;
file "named.sg.jephe.com";
};

include "jephe.com.key";
-------------


4. reverse DNS delegation

On APNIC dns server:
---------------------
[root@apnic named]# more named.c.b.a
$TTL 3600
@ IN SOA c.b.a.in-addr.arpa. admin.c.b.a.in-addr.arpa. (
2013073001 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns1.jephe.com.
NS ns2.jephe.com.

1-63 NS ns1.jephe.com.
1-63 NS ns2.jephe.com.
$GENERATE 1-63 $ CNAME $.0-63

64-127  NS ns1.wu.com.
64-127 NS ns2.wu.com.
$GENERATE  64-127 $ CNAME $.64-127
-----------------

note: 
You also can use the following instead of $GENERATE line
1  CNAME 1.1-63
2  CNAME 2.1-63
3  CNAME 3.1-63
...
65 CNAME 65.64-127
66 CNAME 66.64-127
67 CNAME 67.64-127
...

on ns1.jephe.com master dns server, configure reverse dns as follows:
--------------
[root@jephe named]# more named.c.b.a
$ORIGIN 1-63.c.b.a.in-addr.arpa.
$TTL 600
@ SOA  1-63.c.b.a.in-addr.arpa. root.1-63.c.b.a.in-addr.arpa. (
2013073001
1h
30m
1w
24h )

NS  ns1.jephe.com.
NS  ns2.wu.com.

$GENERATE  1-63 $ PTR host$.jephe.com.

Note: you also can use the following instead of above $GENERATE line
65 PTR host65.jephe.com.
66 PTR host66.jephe.com.
...
-------------

on ns1.wu.com master dns server, configure reverse dns as follows:
---------------
$ORIGIN 64-127.c.b.a.in-addr.arpa.
$TTL 600
@ SOA  64-127.c.b.a.in-addr.arpa. root.64.127.c.b.a.in-addr.arpa. (
2013073001
1h
30m
1w
24h )

NS  ns1.wu.com.
NS  ns2.wu.com.

$GENERATE  64-127 $ PTR host$.wu.com.

Note: you also can use the following instead of above $GENERATE line
65 PTR host65.wu.com.
66 PTR host66.wu.com.
...
---------------

4. DNSSEC

Steps for setting up a Secure Zone jephe.com

a. Enable DNSSEC in the configuration file (named.conf) 
dnssec-enable yes;
dnssec-validation yes;

b. Create key pairs (KSK and ZSK) 

dnssec-keygen -a rsasha1 -b 1024 -n -3 zone jephe.com
dnssec-keygen -a rsasha1 -b 1024 -f ksk -3 -n zone jephe.com

this will generate 4 files, 2 files for zsk, 2 files for ksk.

c. include your DNSKEYs in the zone files named.jephe.com

$INCLUDE “K<myzone>.+005+<id_of_zsk>.key”
$INCLUDE “K<myzone>.+005+<id_of_ksk>.key”

d. sign the zone using secret zsk keys.
dnssec-signzone -o jephe.com -N increment -f named.jephe.com.signed -k
Kjephe.com.+005+idofksk named.jephe.com Kjephe.com.+005+idofzsk

This will generate another file called dsset-jephe.com. which is the hash of ksk public key.

e. Publish your public key 
give above hash file dsset-jephe.com to your .com NS server, they should include to their zone file
$INCLUDE “dsset-jephe.com."

f. update config file to use named.jephe.com.signed file as zone file  

g. test with dig
dig @nsserverof.com www.jephe.com  +dnssec
check if the above command has ad flag which indicates the returned answer is dnssec authenticated data.

5.logging for troubleshooting

logging {
channel my_dns_log { file "dns_log.txt"; severity debug 99; };
category queries { my_dns_log; };
category security { my_dns_log; };
category xfer-in { my_dns_log; };
category xfer-out { my_dns_log; };
};


6. query results example

[root@jephe named]# dig @localhost -x a.b.c.65

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6_4.4 <<>> @localhost -x 192.168.3.65
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25353
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;65.c.b.a.in-addr.arpa. IN PTR

;; ANSWER SECTION:
65.c.b.a.in-addr.arpa. 86400 IN CNAME 65.64-127.c.b.a.in-addr.arpa.
65.64-127.c.b.a.in-addr.arpa. 60 IN PTR ns1.sg.jephe.com.

;; AUTHORITY SECTION:
64-127.c.b.a.in-addr.arpa. 60 IN NS ns1.sg.jephe.com.
64-127.c.b.a.in-addr.arpa. 60 IN NS ns2.sg.jephe.com.

;; ADDITIONAL SECTION:
ns1.sg.jephe.com. 86400 IN A a.b.c.65

;; Query time: 1031 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Jul 28 19:04:24 2013
;; MSG SIZE  rcvd: 130


[root@jephe ~]# dig @192.168.3.1 jephe.com axfr

[root@jephe named]# dig @localhost jephe.com axfr
; Transfer failed.

[root@jephe named]# dig @localhost jephe.com axfr -k jephe.com.key

[root@jephe named]# dig @192.168.200.1 lab.net  +dnssec
note: assume 192.168.200.1 is the .net name server

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6_4.4 <<>> @192.168.200.1 lab.net +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2130
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;lab.net. IN A

;; ANSWER SECTION:
lab.net. 86400 IN A 192.168.3.1
lab.net. 86400 IN RRSIG A 5 2 86400 20130830032400 20130731032400 18513 lab.net. XLy8bq7fA0t4FEckC6wrjk

+kkPDU6CO05ftWlGGDK1engfcRKr4s35G4 a2Kd3vO7OCH92XQyPMGcW8QzBwfT/CPO7mCSn+gQ2c6ymUVnIJKeJSd5 QOVvdCph6mzweHCHB8DGN6vJ0ENSwOcfhz8vFaEYXgnttGFQwiCTLfzY
xHw=

;; AUTHORITY SECTION:
lab.net. 86383 IN NS ns1.lab.net.
lab.net. 86383 IN NS ns2.lab.net.
lab.net. 86383 IN RRSIG NS 5 2 86400 20130830032400 20130731032400 18513 lab.net. ngyOposOYTp2tPIFGhW7xwuMMbmvLqNDDt1n

+YvRbFVHjbUealyN6D1K Xw2j9X4Z7YjbtStgGDDyciovV2TmW89hSlQAISHMZAEzVLBxdCKTobfs 1Qn341eIhIpl7L8TuqiJ1ObHSS2TBW8208x2GaD5/pVjrTWEa21YbgUh +hY=

;; Query time: 63 msec
;; SERVER: 192.168.200.1#53(192.168.200.1)
;; WHEN: Wed Jul 31 16:15:40 2013
;; MSG SIZE  rcvd: 428


7. FAQ

a. all zones must be specified in view statement.
put all your zones inside view statement

b. client 127.0.0.1#37642: view internal: bad zone transfer request: 'domain.com/IN': non-authoritative zone (NOTAUTH)
client 127.0.0.1#37642: view internal: zone transfer setup failed

check master dns server zone file SOA part, must be 'domain.com'.



8. References

http://dnssec-debugger.verisignlabs.com
http://dnsviz.net/
http://dnssec.net/