NSD and OpenDNSSEC under FreeBSD 10 [Part 3: OpenDNSSEC]

This is the third part in the series of articles explaining how to run NSD and OpenDNSSEC under FreeBSD 10.

In this exercise we’re going to configure our signing server NS-SIGN which will be running OpenDNSSEC with DNSSEC keys stored in SoftHSM.

For the sake of simplicity, let’s assume we’re going to host a zone called signed.org.

Go to NS-FEED and generate new TSIG which will be used for the new zone transfers:

% cd /usr/local/etc/nsd
% dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST ns-feed-signed
% cat Kns-feed-signed.+163+18286.key

ns-feed-signed. IN KEY 512 3 163 8X/kvc25+9G1igCCpuuFf9sES0P+gryldjeIgA700Gw=

Add a new TSIG key and zone directives. Here is an updated nsd.conf of our hidden master:

server:
        ip-address: 10.9.128.1
        do-ip4: yes
        do-ip6: no
        verbosity: 2
        chroot: "/usr/local/etc/nsd"
        zonesdir: "/usr/local/etc/nsd"
        zonelistfile: "zone.list"
        database: "var/db/nsd/nsd.db"
        logfile: "var/log/nsd.log"
        pidfile: "var/run/nsd.pid"
        xfrdfile: "var/db/nsd/xfrd.state"
        xfrdir: "var/db/nsd/"
        hide-version: yes

remote-control:
        control-enable: yes
        control-interface: 127.0.0.1
        control-port: 8952
        server-key-file: "/usr/local/etc/nsd/nsd_server.key"
        server-cert-file: "/usr/local/etc/nsd/nsd_server.pem"
        control-key-file: "/usr/local/etc/nsd/nsd_control.key"
        control-cert-file: "/usr/local/etc/nsd/nsd_control.pem"

key:
        name: "tsig.sha256.plain"
        algorithm: hmac-sha256
        secret: "IseujRBzonAlWpVBLyyvn6ErSTp/CGui6+RIeXXLxb4="

key:
        name: "tsig.sha256.signed"
        algorithm: hmac-sha256
        secret: "8X/kvc25+9G1igCCpuuFf9sES0P+gryldjeIgA700Gw="

pattern:
        name: "plain-to-slaves"
        zonefile: "zones/%s"
        notify: 192.168.128.1 tsig.sha256.plain
        notify: 192.168.128.2 tsig.sha256.plain
        provide-xfr: 192.168.128.1-192.168.128.2 tsig.sha256.plain

pattern:
        name: "plain-to-signer"
        zonefile: "zones/%s"
        notify: 10.9.128.2 tsig.sha256.signed
        provide-xfr: 10.9.128.2 tsig.sha256.signed

zone:
        name: "plain.org"
        include-pattern: "plain-to-slaves"

zone:
        name: "signed.org"
        include-pattern: "plain-to-signer"

As you can see there is a new key directive, new pattern and a new zone added.

Create a file called signed.org under /usr/local/etc/nsd/zones directory:


$ORIGIN signed.org.
$TTL 1h
@       IN      SOA     signed.org.      hostmaster.signed.org. (
                        2014082701              ; serial number
                        3600                    ; refresh
                        900                     ; retry
                        1209600                 ; expire
                        1800                    ; ttl
                        )
; Name servers
                    IN      NS      ns1.signed.org.
                    IN      NS      ns2.signed.org.

; A records for name servers
ns1                 IN      A       192.168.128.1
ns2                 IN      A       192.168.128.2

; Additional A records
@                   IN      A       192.168.128.20
www                 IN      A       192.168.128.20

Reload the config of NSD so that the new zone is served:

% nsd-control reconfig

Verify that you can query it:


% dig @10.9.128.1 signed.org soa

; <<>> DiG 9.10.0-P2 <<>> @10.9.128.1 signed.org soa
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24606
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;signed.org.                      IN      SOA

;; ANSWER SECTION:
signed.org.               3600    IN      SOA     signed.org. hostmaster.signed.org. 2014082801 3600 900 1209600 1800

;; AUTHORITY SECTION:
signed.org.               3600    IN      NS      ns1.signed.org.
signed.org.               3600    IN      NS      ns2.signed.org.

;; ADDITIONAL SECTION:
ns1.signed.org.           3600    IN      A       192.168.128.1
ns2.signed.org.           3600    IN      A       192.168.128.2

;; Query time: 1 msec
;; SERVER: 10.9.128.1#53(10.9.128.1)
;; WHEN: Thu Aug 28 13:59:41 CEST 2014
;; MSG SIZE  rcvd: 164

Go to NS-SIGN and install required software:

% cd /usr/ports/dns/opendnssec && make install clean

Ensure that SOFTHSM is checked. Since I'm not going to use MySQL I select SQLITE as a DB backend.

Modify /etc/rc.conf to start OpenDNSSEC at boot:

# enable opendnssec
opendnssec_enable="YES"

Initialize SoftHSM database with the label "OpenDNSSEC". You will be prompted to provide with two PINs: SO PIN and user PIN. Note and keep both PINs in a secure place. The SO PIN can be used to reinitialize the token and the user PIN will be used by OpenDNSSEC to interact with the token.

% softhsm ----init-token ----slot 0 ----label "OpenDNSSEC"

    The SO PIN must have a length between 4 and 255 characters.
    Enter SO PIN: ****
    The user PIN must have a length between 4 and 255 characters.
    Enter user PIN: ****
    The token has been initialized.

Confirm that the slot has been initialized and available as per the config:

% softhsm ----show-slots

Available slots:
Slot 0
           Token present: yes
           Token initialized: yes
           User PIN initialized: yes
           Token label: OpenDNSSEC

% cat /usr/local/etc/softhsm.conf
0:/var/lib/softhsm/slot0.db

% ls -al /var/lib/softhsm/slot0.db
-rw-------  1 root  wheel  45056 Aug 28 18:14 /var/lib/softhsm/slot0.db

Create config files for OpenDNSSEC:

% cd /usr/local/etc/opendnssec

% cp addns.xml.sample addns.xml
% cp conf.xml.sample conf.xml
% cp kasp.xml.sample kasp.xml
% cp zonelist.xml.sample zonelist.xml

addns.xml is the config file where you define zone transfer settings or so called DNS adapters. I removed comments and examples so it could be easier to read it:




        
                
                        tsig.sha256.signed
                        hmac-sha256
                        8X/kvc25+9G1igCCpuuFf9sES0P+gryldjeIgA700Gw=
                

                
                        
                                
                                        
10.9.128.1
tsig.sha256.signed
10.9.128.1 tsig.sha256.signed
192.168.128.1 tsig.sha256.signed 192.168.128.2 tsig.sha256.signed
192.168.128.1
tsig.sha256.signed
192.168.128.2
tsig.sha256.signed

As you can see, we defined our TSIG that is used for signed zones. Inbound container contains the server where we get the plain zone from -- this is our hidden master NS-FEED. Outbound container contains servers where we send the zone after it has been signed -- these are our public slaves: NS-3 and NS-4.

conf.xml is the overall config file of OpenDNSSEC where you define global settings, like system paths, logging, key repositories and etc.





        

                
                        /usr/local/lib/softhsm/libsofthsm.so
                        OpenDNSSEC
                        ****
                        
                

        

        
                
                        3
                        local0
                

                /usr/local/etc/opendnssec/kasp.xml
                /usr/local/etc/opendnssec/zonelist.xml
        

        

                /usr/local/var/opendnssec/kasp.db
                PT3600S

        

        

                /usr/local/var/opendnssec/tmp
                4

                
                        
10.9.128.2
53

Mainly all settings are as per the default file. Don't forget to enter proper User PIN. The only thing I modified was the IP address under Listener container. This file will give you an idea about system paths where SQLite DB and working files are stored, which is useful during troubleshooting.

kasp.xml is a pretty important file where you define policies used to sign zones, for example, security parameters (algorithm, key size) and timing parameters (when the zone is supposed to be resigned and such):





        
                A default policy that will amaze you and your friends
                
                        PT2H
                        P3D
                        
                                P14D
                                P14D
                        
                        PT12H
                        PT3600S
                

                
                        
                                P100D
                                
                                        1
                                        5
                                        
                                
                        
                

                
                        PT3600S
                        PT3600S
                        PT3600S
                        P14D

                        
                                8
                                P1Y
                                SoftHSM
                        

                        
                                8
                                P90D
                                SoftHSM
                        
                

                
                        PT43200S
                        
                                PT3600S
                                PT3600S
                                datecounter
                        
                

                
                        PT9999S
                        
                                PT3600S
                        
                        
                                PT172800S
                                PT10800S
                        
                

        

I accepted the default policy called default. As per this policy, the lifetime of KSK is 1 year and the lifetime of ZSK is 90 days. The only thing I changed was the Serial container: changed to datecounter.

Finally, zonelist.xml is a file where you add your zone:



        
                default
                /usr/local/var/opendnssec/signconf/signed.org.xml
                
                        
                                /usr/local/etc/opendnssec/addns.xml
                        
                        
                                /usr/local/etc/opendnssec/addns.xml
                        
                
        

Note that we're using DNS adapter, which means that OpenDNSSEC won't expect any files as a source, but rather sign the zone it will get from our hidden master.

Initialize OpenDNSSEC database:

% ods-ksmutil setup

*WARNING* This will erase all data in the database; are you sure? [y/N] y
fixing permissions on file /usr/local/var/opendnssec/kasp.db
zonelist filename set to /usr/local/etc/opendnssec/zonelist.xml.
kasp filename set to /usr/local/etc/opendnssec/kasp.xml.
Repository SoftHSM found
No Maximum Capacity set.
RequireBackup NOT set; please make sure that you know the potential problems of using keys which are not recoverable
INFO: The XML in /usr/local/etc/opendnssec/conf.xml is valid
INFO: The XML in /usr/local/etc/opendnssec/zonelist.xml is valid
INFO: The XML in /usr/local/etc/opendnssec/kasp.xml is valid
WARNING: In policy default, Y used in duration field for Keys/KSK Lifetime (P1Y) in /usr/local/etc/opendnssec/kasp.xml - this will be interpreted as 365 days
Policy default found
Info: converting P1Y to seconds; M interpreted as 31 days, Y interpreted as 365 days
Zone signed.org found; policy set to default
Added zone signed.org to database

Verify that the zone is loaded:

% ods-ksmutil zone list

zonelist filename set to /usr/local/etc/opendnssec/zonelist.xml.
Found Zone: signed.org; on policy default

Start the signing engine and verify that it's running:

% ods-control start

Starting enforcer...
OpenDNSSEC ods-enforcerd started (version 1.4.6), pid 18968
Starting signer engine...
OpenDNSSEC signer engine version 1.4.6
Engine running.

% ps ax | grep ods

18968  -  Is      0:03.82 /usr/local/sbin/ods-enforcerd
19089  -  Is      0:01.64 /usr/local/sbin/ods-signerd -c /usr/local/etc/opendnssec/conf.xml

Check that the keys were generated:

% ods-ksmutil key list ----zone signed.org ----verbose

SQLite database set to: /usr/local/var/opendnssec/kasp.db
Keys:
Zone:                           Keytype:      State:    Date of next transition (to):  Size:   Algorithm:  CKA_ID:                           Repository:                       Keytag:
signed.org                      KSK           publish   2014-08-30 07:05:07 (ready)    2048    8           a502e7cae0ed679efc52436d7b8703fd  SoftHSM                           44774
signed.org                      ZSK           active    2014-11-27 17:05:07 (retire)   1024    8           96b05fab49d96e617ca2b2e3b12cb82a  SoftHSM                           57438

The important part here is the State column: our KSK key is in Publish state, which means it has been published in the zone, but it's not yet ready to be used (it hasn't been long enough in the zone to propagate). We have to wait till the next transition cycle, which will transfer our KSK to Ready state, and after that, we will be able to export the key and DS records.

You can also check the log files:

% tail /var/log/messages

Aug 29 22:16:28 ns-sign ods-enforcerd: WARNING: KSK rollover for zone 'signed.org' not completed as there are no keys in the 'ready' state; ods-enforcerd will try again when it runs next

Let's check the status after several hours:

% ods-ksmutil key list ----zone signed.org ----verbose

SQLite database set to: /usr/local/var/opendnssec/kasp.db
Keys:
Zone:                           Keytype:      State:    Date of next transition (to):  Size:   Algorithm:  CKA_ID:                           Repository:                       Keytag:
signed.org                      KSK           ready     waiting for ds-seen (active)   2048    8           a502e7cae0ed679efc52436d7b8703fd  SoftHSM                           44774
signed.org                      ZSK           active    2014-11-27 17:05:07 (retire)   1024    8           96b05fab49d96e617ca2b2e3b12cb82a  SoftHSM                           57438
% tail /var/log/messages

Aug 30 12:16:31 ns-sign ods-enforcerd: WARNING: New KSK has reached the ready state; please submit the DS for signed.org and use ods-ksmutil key ds-seen when the DS appears in the DNS.

Great -- the status has changed to Ready, which means we're ready to extract DS records for our domain:

% ods-ksmutil key export ----zone signed.org ----ds ----keystate READY

;ready KSK DS record (SHA1):
signed.org. 3600    IN      DS      44774 8 1 6af6caff1d7cb20c48cb240a40322103a18c4ef3

;ready KSK DS record (SHA256):
signed.org. 3600    IN      DS      44774 8 2 3c177857ccae27674f51cf233dc935d3d678769901fce8c623ea85184a6d40b6

Send both DS records to the registrar so that the chain is trusted. Once the new DSs are entered on the registrar side, complete the roll-over:

% ods-ksmutil key ds-seen -z signed.org -x 44774

Found key with CKA_ID a502e7cae0ed679efc52436d7b8703fd
Key a502e7cae0ed679efc52436d7b8703fd made active
Notifying enforcer of new database...
Performed a HUP ods-enforcerd

Where 44774 is the keytag of our zone.

The KSK key is now in active state and we finished with NS-SIGN!

% ods-ksmutil key list ----zone signed.org ----verbose

SQLite database set to: /usr/local/var/opendnssec/kasp.db
Keys:
Zone:                           Keytype:      State:    Date of next transition (to):  Size:   Algorithm:  CKA_ID:                           Repository:                       Keytag:
signed.org                      KSK           active    2015-08-30 12:39:01 (retire)   2048    8           a502e7cae0ed679efc52436d7b8703fd  SoftHSM                           44774
signed.org                      ZSK           active    2014-11-27 17:05:07 (retire)   1024    8           96b05fab49d96e617ca2b2e3b12cb82a  SoftHSM                           57438

The only thing that is still pending is the configuration of NS-3 and NS-4 to host our new signed zone. Here is the updated nsd.conf of NS-3 reflecting signed.org. Repeat the same on NS-4.

server:
        ip-address: 192.168.128.1
        do-ip4: yes
        do-ip6: no
        verbosity: 2
        chroot: "/usr/local/etc/nsd"
        zonesdir: "/usr/local/etc/nsd"
        zonelistfile: "zone.list"
        database: "var/db/nsd/nsd.db"
        logfile: "var/log/nsd.log"
        pidfile: "var/run/nsd.pid"
        xfrdfile: "var/db/nsd/xfrd.state"
        xfrdir: "var/db/nsd/"
        hide-version: yes

remote-control:
        control-enable: yes
        control-interface: 127.0.0.1
        control-port: 8952
        server-key-file: "/usr/local/etc/nsd/nsd_server.key"
        server-cert-file: "/usr/local/etc/nsd/nsd_server.pem"
        control-key-file: "/usr/local/etc/nsd/nsd_control.key"
        control-cert-file: "/usr/local/etc/nsd/nsd_control.pem"

key:
        name: "tsig.sha256.plain"
        algorithm: hmac-sha256
        secret: "IseujRBzonAlWpVBLyyvn6ErSTp/CGui6+RIeXXLxb4="

key:
        name: "tsig.sha256.signed"
        algorithm: hmac-sha256
        secret: "8X/kvc25+9G1igCCpuuFf9sES0P+gryldjeIgA700Gw="

pattern:
        name: "from-master"
        zonefile: "zones/%s"
        request-xfr: AXFR 10.9.128.1 tsig.sha256.plain
        provide-xfr: 172.16.128.1 tsig.sha256.plain
        allow-notify: 10.9.128.1 tsig.sha256.plain
        notify: 172.16.128.1 tsig.sha256.plain

pattern:
        name: "from-signer"
        zonefile: "zones/%s"
        request-xfr: AXFR 10.9.128.2 tsig.sha256.signed
        provide-xfr: 172.16.128.1 tsig.sha256.signed
        allow-notify: 10.9.128.2 tsig.sha256.signed
        notify: 172.16.128.1 tsig.sha256.signed

zone:
        name: "plain.org"
        include-pattern: "from-master"

zone:
        name: "signed.org"
        include-pattern: "from-signer"

You can now add a new DNS record in signed.org zone, increase the serial and reload the zone (all to be done on NS-FEED). The record will be automatically signed by NS-SIGN and the zone transferred to NS-3/4.

Thanks for reading! The setup is completed.

Tags: , , , , , , ,

Leave a Reply