Differences between revisions 5 and 6
Revision 5 as of 2017-02-04 08:59:18
Size: 2125
Editor: WilliMann
Comment: Title should reflect the version the HOWTO applies to
Revision 6 as of 2020-04-23 10:31:43
Size: 12413
Editor: MichaelPaoli
Comment: Substantial (mostly) rewrite - more complete, more explanations and important points, currently tested, more references/links
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
##https://wiki.debian.org/DNSSEC%20Howto%20for%20BIND%209.9+
Line 2: Line 3:
This is a minimal howto to get DNSSEC running with bind 9 on jessie. We assume an "clean", freshly installed bind9 here. I wrote this HOWTO to document how I got my first signed zone. This is an introductory howto to get DNSSEC running with BIND >=9.9 on
Debian >=8 (jessie). We assume an "clean", freshly installed bind9
here.

== Introduction ==
If you're looking for more general information about DNSSEC, you may
want to have a look at:<<BR>>
[[DNSSEC]]<<BR>>
[[https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions/|Domain Name System Security Extensions (DNSSEC) - Wikipedia]]

Approach used here. We use inline-signing here, as it relieves the
administrator of most of the hassle, hazards, and pitfalls of manually
maintaining DNSSEC and associated Resource Records (RRs), at least once
the initial configuration has been completed.

BIND version 9.9 (or later) is minimal requirement, and we presume a
"pure" Debian >=8 (jessie) host system with a "clean" installation of
the bind9 Debian package.<<BR>>
See also: [[Bind9]].

In our examples here, for security, we'll generally be
showing/using
[[https://en.wikipedia.org/wiki/Principle_of_least_privilege|Principle of least privilege - Wikipedia]].
That is most important/critical here, for any and all private keys. If
one wishes to be more permissive, for items other than private keys, one
may wish to allow read access in the general case, however in all cases
most all the files/data referenced here should be protected from general
write access. That generally means group bind will need read access,
and in some areas/locations/files, write access. Others should not have
write access, and must not have read access to private keys.

We generally show root prompt as a leading "# ", by convention.<<BR>>
We generally show non-root prompt as a leading "$ ", by convention.
Line 6: Line 39:
Make separate directory for keys and zones, let group bind write in zones:

{{{
cd /etc/bind
mkdir zones keys
chmod g+w zones
cd zones
}}}

Now create file example.mytld.zone
Make separate directory for keys and zones, let group bind write in
zones. We also use
[[https://en.wikipedia.org/wiki/Setuid#When_set_on_a_directory|SGID on directory]],
so by default items created in directory will have group ownership
matching that of the directory.

{{{
# umask 077
# mkdir /etc/bind/master /var/cache/bind/keys
# chgrp bind /etc/bind/master /var/cache/bind/keys
# chmod ug=rwx,o=,g+s /etc/bind/master /var/cache/bind/keys
}}}

Serial number (& scheme) for master zone file.

For the serial, we are showing the RFC recommended format: YYYYMMDDnn
While that has the advantage of the more human readable form,
with inline-signing - which we're using here, it will typically rather
quickly fall out-of-sync with its intended alignment to actual
corresponding YYYY-MM-DD date, and may lead to confusions and incorrect
presumptions. Alternatively, one may want to instead use seconds since
the epoch - "Unix time" (unixtime). Notably as inline-signing can
directly support unixtime, whereas with YYYYMMDDnn, the
only method inline-signing can use with that is increment, which will
simply increment the serial, regardless of when it is done.
If one wishes to use unixtime, the GNU date utility can
conveniently provide that:
{{{
$ date +%s
1587461621
}}}
And likewise convert back if one wants to see the more human time, e.g.:
{{{
$ date -d @1587461621
Tue Apr 21 09:33:41 GMT 2020
$ date --iso-8601=seconds -d @1587461621
2020-04-21T09:33:41+00:00
}}}
One can also use GNU date to get the YYYYMMDD portion of YYYYMMDDnn
format:
{{{
$ date +'%Y%m%d'
20200421
}}}

Note one also can't arbitrarily jump serial numbers around - that can
cause significant to major problems. But if we're starting new,
we're relatively free to pick - so long as we do a valid number within
range (both unixtime, and YYYYMMDDnn will be within range).

Now create master zone file, we show example.com - use your actual
domain, and we show YYYYMMDDnn serial format - use your actual
data/scheme. Likewise for the A record, we show 127.0.0.1,
for the BIND9 DNS nameserver to be useful and functional beyond the
local host, you'll need to use the applicable IP address(es)
for the A and/or AAAA record(s) corresponding to the NS record.
Also, hostmaster.example.com. should be or be replaced with valid
email address - replacing @ with ., and if there are any .'s
before that first @ in the email address, replace those with: \.
And end with: .
E.g.:
{{{
firstname.lastname@example.com
}}}
would become:
{{{
firstname\.lastname.example.com.
}}}

So, in /etc/bind/master we create our file example.com:
Line 19: Line 111:
@ IN SOA ns1.example.mytld. dnsmaster.example.mytld. (
                        2016080201 ;Serial
                        8H ; refresh
                        2H ; retry
                        1W ; expire
                        2H ; TTL
@ IN SOA     (
                   
ns1.example.com. ; MNAME
                        hos
tmaster.example.com. ; RNAME
                        2020042100 ; SERIAL
                        8H                 ; REFRESH
                        2H                 ; RETRY
                        1W                 ; EXPIRY
                        2H                 ; MINIMUM Negative Cache TTL
Line 26: Line 120:
        IN NS ns1.example.mytld.         IN NS ns1.example.com.
Line 28: Line 122:
www IN A 192.168.0.1
}}}

Add the following section to named.conf.local

{{{
zone "example.mytld" {
}}}
File permissions and ownership should be 640 root:bind:
{{{
# ls -ld example.com
-rw-r----- 1 root bind 4207 Apr 21 10:01 example.com
}}}
(if you implement dynamic DNS, you'll want to then change that to
bind:bind)

And in /etc/bind, add the following section to named.conf.local:
{{{
zone "example.com" {
Line 36: Line 135:
        file "/etc/bind/zones/example.mytld.zone";
        allow-query {any; };
        file "/etc/bind/master/example.com";
Line 42: Line 140:
Reload bind and check whether querying the zone works:

{{{
dig @127.0.0.1 example.mytld NS
Enable and start the service:
{{{
# systemctl enable bind9.service
# systemctl start bind9.service
}}}
or if it's already running, reload:
{{{
# systemctl reload bind9.service
}}}

You may need to install dnsutils for utilities such as dig:
{{{
# apt-get -y install dnsutils
}}}

Check whether querying the zone works:
{{{
$ dig @127.0.0.1 example.com. NS
Line 50: Line 162:
Execute

{{{
cd keys
dnssec-keygen -a RSASHA256 -b 2048 -3 example.mytld
dnssec-keygen -a RSASHA256 -b 2048 -3 -fk example.mytld
chmod g+r *
cd ..
}}}

to generate the keys and let BIND read the keys.

Add
{{{
Keys ...

{{{
At least as of 2020-04-21:
domain key algorithm bits
. KSK 8 2048
. ZSK 8 2048
org. KSK 7 2048
org. ZSK 7 1024
net. KSK 8 2048
net. ZSK 8 1280
com. KSK 8 2048
com. ZSK 8 1280
...
algorithms:
8 RSASHA256
7 NSEC3RSASHA1
}}}
Note that when setting up keys, notably number of bits - at least
for same algorithm, picking a larger number of bits than the weakest
link in ancestor chain, adds no real additional security, but does
add more DNS and network load - in both sizes of data transferred,
and cryptographic (CPU) overhead. Of course having smaller
corresponding bit size gives one weaker security. So, for
optimal performance without weakening security, one may may
want to consult current bit sizes used up the ancestor chain,
and also periodically review for change.

In our example here, with example.com, we pick values that
correspond with com (and .):

Create our initial keys:
{{{
# cd /var/cache/bind/keys
# dnssec-keygen -a RSASHA256 -b 2048 -f KSK example.com
# dnssec-keygen -a RSASHA256 -b 1280 example.com
}}}
Set permissions so group bind can read the keys:
{{{
# chgrp bind Kexample.com.+*
# chmod g=r,o= Kexample.com.+*
}}}

Be sure to securely SAVE COPIES of the keys!
Once the DS record(s) is(/are) set up in the delegating parent
domain/zone, if keys are lost, DNS(SEC) will be failed for a substantial
period of time, and one cannot be assured of fully and immediately
rectifying such situation without those same keys - any resolvers,
etc. that understand and use DNSSEC may continue to reject DNS data from
the domain until the DNSSEC issue is resolved - including any
relevant caching and timeouts on data and keys seen, including keys seen
earlier.

# cd /etc/bind

Add to the zone "example.com" section in the file named.conf.local:
{{{
        inline-signing yes;
Line 65: Line 221:
        inline-signing yes;
}}}

to the zone "example.mytld" section in named.conf.local.

Add

{{{
         key-directory "/etc/bind/keys/";
}}}
        serial-update-method increment;
}}}
or if one alternatively, uses unixtime for the zone serial number,
(see also further above about serial numbers), then instead,
use this for serial-update-method:
{{{
        serial-update-method unixtime;
}}}

Add:
{{{
     key-directory "/var/cache/bind/keys";
}}}
Line 78: Line 236:
Execute

{{{
rndc loadkeys example.mytld
NSECSEED=$(printf "%04x%04x" $RANDOM $RANDOM)
rndc signing -nsec3param 1 0 10 $NSECSEED example.mytld.
}}}
reload the configuration:
{{{
# rndc reload
}}}
or:
{{{
# systemctl reload bind9.service
}}}

## are the rndc loadkeys and rndc signing parts strictly necessary?
Execute:
{{{
# rndc loadkeys example.com
# rndc signing -nsec3param 1 0 10 auto example.com
}}}
Line 88: Line 253:
Verify that the zone works by executing
{{{
dig @127.0.0.1 +dnssec example.mytld AXFR
}}}

You should see lines containing "RRSIG" and "NSEC3", and long hex-strings.

Main author: Willi Mann <<MailTo(willi@debian.org)>>
Verify that the zone works and is properly signed and ready for DS
delegation by executing:
{{{
# (d=example.com; k=$(dig @127.0.0.1 +norecurse "$d". DNSKEY | dnssec-dsfromkey -f - "$d" | awk '{print $4;}' | sort -u); delv @127.0.0.1 -a <(sed -e '/^;/d;s/ IN DNSKEY / /;s/^[^ ]* [^ ]* [^ ]* [^ ]* /&"/;:s;/"[^ ]*$/b t;s/\("[^ ]*\) /\1/;b s;:t;s/.*/trusted-keys {\n &";\n};/' /var/cache/bind/keys/K"$d".+008+"$k".key) +root="$d" "$d". SOA +multiline)
}}}
You should see a first output line of:
{{{
; fully validated
}}}
followed by SOA record data and then signature related data.

It is VERY IMPORTANT that the above be working properly before
proceeding further. Also, as noted above, one should be sure one has
made backup copies of the relevant keys, before proceeding further.

So, here's the part where we go fully "live" with DNSSEC.
Similar to NS records for nameserver delegation,
there are DS records for delegation of digital signatures/signing.

So, one needs to have the relevant DS record(s) added to the delegating
parent/upstream zone. Again, be sure the validation steps noted further
above have first been successfully completed before proceeding. If you
proceed with the next steps without first having the above working
properly, you'll significantly break your DNS, and it may take a
substantial period of time to fully rectify that. (Essentially if
DS data is set up in delegating parent/upstream zone, and you're not
properly functional and ready for that yet, essentially you're saying
that you're using DNSSEC and not to trust the data if it's not properly
set up and signed with the key data provided ... and then you'd not
have proper key data set up on your zone, so any DNS that honored DNSSEC
would reject your DNS data, and that may persist some fair while due to
key lifetimes, DNS TTLs, expiration, etc.)

So, next we obtain the needed DS data from our signed zone:

{{{
# (d=example.com; dig @127.0.0.1 +norecurse "$d". DNSKEY | dnssec-dsfromkey -f - "$d")
}}}

That gets one the DS records that need to be added to upstream/parent
delegating zone to make the DNSSEC effective from the delegating
authority(/ies). The precise procedure on adding those to the
delegating upstream/parent will depend what exactly is there.
It might be as simple as directly adding the relevant data to the
DNS nameserver. For some registrars, it may be matter of doing
copy/paste of the relevant data into some specific web form.
Some registrars will fetch the DNSKEY data from your zone,
determine the DS data from that, display it and ask for confirmation
to add it (in which case, to be sure to check that it matches
properly as expected).

Not covered here - alternative trust anchors - how to have DNSSEC
authority for nameservers, resolvers, etc. come from source
(e.g. local), directly (or indirectly), rather than directly or
indirectly from the Internet root (.) DNS nameservers.

== Documentation/References ==

[[DNSSEC]]<<BR>>
[[Bind9]]<<BR>>
[[https://ftp.isc.org/isc/dnssec-guide/dnssec-guide.pdf|BIND DNSSEC Guide]]<<BR>>
[DNSViz - A DNS visualization tool|http://dnsviz.net/]] (excellent visual DNS/DNSSEC analysis/troubleshooting)<<BR>>
BIND documentation:<<BR>>
If one has the bind9-doc package installed:<<BR>>
/usr/share/doc/bind9-doc/arm/<<BR>>
/usr/share/doc/bind9-doc/arm/Bv9ARM.html<<BR>>
or from ISC.org (upstream):<<BR>>
[[https://kb.isc.org/docs/aa-01031|An Overview of BIND 9 Documentation]] (be sure to use corresponding version, and realize there may be some Debian differences).<<BR>>
[[https://www.isc.org/downloads/bind/dnssec/|DNSSEC and BIND 9]]<<BR>>
[[http://dnssec.vs.uni-due.de/|DNSSEC Resolver Test]]<<BR>>
[[https://rootcanary.org/test.html|resolver DS and signing algorithm combination tester]]

This is an introductory howto to get DNSSEC running with BIND >=9.9 on Debian >=8 (jessie). We assume an "clean", freshly installed bind9 here.

Introduction

If you're looking for more general information about DNSSEC, you may want to have a look at:
DNSSEC
Domain Name System Security Extensions (DNSSEC) - Wikipedia

Approach used here. We use inline-signing here, as it relieves the administrator of most of the hassle, hazards, and pitfalls of manually maintaining DNSSEC and associated Resource Records (RRs), at least once the initial configuration has been completed.

BIND version 9.9 (or later) is minimal requirement, and we presume a "pure" Debian >=8 (jessie) host system with a "clean" installation of the bind9 Debian package.
See also: Bind9.

In our examples here, for security, we'll generally be showing/using Principle of least privilege - Wikipedia. That is most important/critical here, for any and all private keys. If one wishes to be more permissive, for items other than private keys, one may wish to allow read access in the general case, however in all cases most all the files/data referenced here should be protected from general write access. That generally means group bind will need read access, and in some areas/locations/files, write access. Others should not have write access, and must not have read access to private keys.

We generally show root prompt as a leading "# ", by convention.
We generally show non-root prompt as a leading "$ ", by convention.

Initial setup

Make separate directory for keys and zones, let group bind write in zones. We also use SGID on directory, so by default items created in directory will have group ownership matching that of the directory.

# umask 077
# mkdir /etc/bind/master /var/cache/bind/keys
# chgrp bind /etc/bind/master /var/cache/bind/keys
# chmod ug=rwx,o=,g+s /etc/bind/master /var/cache/bind/keys

Serial number (& scheme) for master zone file.

For the serial, we are showing the RFC recommended format: YYYYMMDDnn While that has the advantage of the more human readable form, with inline-signing - which we're using here, it will typically rather quickly fall out-of-sync with its intended alignment to actual corresponding YYYY-MM-DD date, and may lead to confusions and incorrect presumptions. Alternatively, one may want to instead use seconds since the epoch - "Unix time" (unixtime). Notably as inline-signing can directly support unixtime, whereas with YYYYMMDDnn, the only method inline-signing can use with that is increment, which will simply increment the serial, regardless of when it is done. If one wishes to use unixtime, the GNU date utility can conveniently provide that:

$ date +%s
1587461621

And likewise convert back if one wants to see the more human time, e.g.:

$ date -d @1587461621
Tue Apr 21 09:33:41 GMT 2020
$ date --iso-8601=seconds -d @1587461621
2020-04-21T09:33:41+00:00

One can also use GNU date to get the YYYYMMDD portion of YYYYMMDDnn format:

$ date +'%Y%m%d'
20200421

Note one also can't arbitrarily jump serial numbers around - that can cause significant to major problems. But if we're starting new, we're relatively free to pick - so long as we do a valid number within range (both unixtime, and YYYYMMDDnn will be within range).

Now create master zone file, we show example.com - use your actual domain, and we show YYYYMMDDnn serial format - use your actual data/scheme. Likewise for the A record, we show 127.0.0.1, for the BIND9 DNS nameserver to be useful and functional beyond the local host, you'll need to use the applicable IP address(es) for the A and/or AAAA record(s) corresponding to the NS record. Also, hostmaster.example.com. should be or be replaced with valid email address - replacing @ with ., and if there are any .'s before that first @ in the email address, replace those with: \. And end with: . E.g.:

firstname.lastname@example.com

would become:

firstname\.lastname.example.com.

So, in /etc/bind/master we create our file example.com:

$TTL    6400
@       IN      SOA     (
                        ns1.example.com.        ; MNAME
                        hostmaster.example.com. ; RNAME
                        2020042100              ; SERIAL
                        8H                      ; REFRESH
                        2H                      ; RETRY
                        1W                      ; EXPIRY
                        2H                      ; MINIMUM Negative Cache TTL
                        )
        IN      NS      ns1.example.com.
ns1     IN      A       127.0.0.1

File permissions and ownership should be 640 root:bind:

# ls -ld example.com
-rw-r----- 1 root bind 4207 Apr 21 10:01 example.com

(if you implement dynamic DNS, you'll want to then change that to bind:bind)

And in /etc/bind, add the following section to named.conf.local:

zone "example.com" {
        type master;
        file "/etc/bind/master/example.com";
        allow-transfer { 127.0.0.1; };
};

Enable and start the service:

# systemctl enable bind9.service
# systemctl start bind9.service

or if it's already running, reload:

# systemctl reload bind9.service

You may need to install dnsutils for utilities such as dig:

# apt-get -y install dnsutils

Check whether querying the zone works:

$ dig @127.0.0.1 example.com. NS

The signing part

Keys ...

At least as of 2020-04-21:
domain key algorithm bits
.      KSK 8         2048
.      ZSK 8         2048
org.   KSK 7         2048
org.   ZSK 7         1024
net.   KSK 8         2048
net.   ZSK 8         1280
com.   KSK 8         2048
com.   ZSK 8         1280
...
algorithms:
8 RSASHA256
7 NSEC3RSASHA1

Note that when setting up keys, notably number of bits - at least for same algorithm, picking a larger number of bits than the weakest link in ancestor chain, adds no real additional security, but does add more DNS and network load - in both sizes of data transferred, and cryptographic (CPU) overhead. Of course having smaller corresponding bit size gives one weaker security. So, for optimal performance without weakening security, one may may want to consult current bit sizes used up the ancestor chain, and also periodically review for change.

In our example here, with example.com, we pick values that correspond with com (and .):

Create our initial keys:

# cd /var/cache/bind/keys
# dnssec-keygen -a RSASHA256 -b 2048 -f KSK example.com
# dnssec-keygen -a RSASHA256 -b 1280 example.com

Set permissions so group bind can read the keys:

# chgrp bind Kexample.com.+*
# chmod g=r,o= Kexample.com.+*

Be sure to securely SAVE COPIES of the keys! Once the DS record(s) is(/are) set up in the delegating parent domain/zone, if keys are lost, DNS(SEC) will be failed for a substantial period of time, and one cannot be assured of fully and immediately rectifying such situation without those same keys - any resolvers, etc. that understand and use DNSSEC may continue to reject DNS data from the domain until the DNSSEC issue is resolved - including any relevant caching and timeouts on data and keys seen, including keys seen earlier.

# cd /etc/bind

Add to the zone "example.com" section in the file named.conf.local:

        inline-signing yes;
        auto-dnssec maintain;
        serial-update-method increment;

or if one alternatively, uses unixtime for the zone serial number, (see also further above about serial numbers), then instead, use this for serial-update-method:

        serial-update-method unixtime;

Add:

     key-directory "/var/cache/bind/keys";

to the options section in named.conf.options

reload the configuration:

# rndc reload

or:

# systemctl reload bind9.service

Execute:

# rndc loadkeys example.com
# rndc signing -nsec3param 1 0 10 auto example.com

to let bind sign the zone.

Verify that the zone works and is properly signed and ready for DS delegation by executing:

# (d=example.com; k=$(dig @127.0.0.1 +norecurse "$d". DNSKEY | dnssec-dsfromkey -f - "$d" | awk '{print $4;}' | sort -u); delv @127.0.0.1 -a <(sed -e '/^;/d;s/ IN DNSKEY / /;s/^[^ ]* [^ ]* [^ ]* [^ ]* /&"/;:s;/"[^ ]*$/b t;s/\("[^ ]*\) /\1/;b s;:t;s/.*/trusted-keys {\n    &";\n};/' /var/cache/bind/keys/K"$d".+008+"$k".key) +root="$d" "$d". SOA +multiline)

You should see a first output line of:

; fully validated

followed by SOA record data and then signature related data.

It is VERY IMPORTANT that the above be working properly before proceeding further. Also, as noted above, one should be sure one has made backup copies of the relevant keys, before proceeding further.

So, here's the part where we go fully "live" with DNSSEC. Similar to NS records for nameserver delegation, there are DS records for delegation of digital signatures/signing.

So, one needs to have the relevant DS record(s) added to the delegating parent/upstream zone. Again, be sure the validation steps noted further above have first been successfully completed before proceeding. If you proceed with the next steps without first having the above working properly, you'll significantly break your DNS, and it may take a substantial period of time to fully rectify that. (Essentially if DS data is set up in delegating parent/upstream zone, and you're not properly functional and ready for that yet, essentially you're saying that you're using DNSSEC and not to trust the data if it's not properly set up and signed with the key data provided ... and then you'd not have proper key data set up on your zone, so any DNS that honored DNSSEC would reject your DNS data, and that may persist some fair while due to key lifetimes, DNS TTLs, expiration, etc.)

So, next we obtain the needed DS data from our signed zone:

# (d=example.com; dig @127.0.0.1 +norecurse "$d". DNSKEY | dnssec-dsfromkey -f - "$d")

That gets one the DS records that need to be added to upstream/parent delegating zone to make the DNSSEC effective from the delegating authority(/ies). The precise procedure on adding those to the delegating upstream/parent will depend what exactly is there. It might be as simple as directly adding the relevant data to the DNS nameserver. For some registrars, it may be matter of doing copy/paste of the relevant data into some specific web form. Some registrars will fetch the DNSKEY data from your zone, determine the DS data from that, display it and ask for confirmation to add it (in which case, to be sure to check that it matches properly as expected).

Not covered here - alternative trust anchors - how to have DNSSEC authority for nameservers, resolvers, etc. come from source (e.g. local), directly (or indirectly), rather than directly or indirectly from the Internet root (.) DNS nameservers.

Documentation/References

DNSSEC
Bind9
BIND DNSSEC Guide
[DNSViz - A DNS visualization tool|http://dnsviz.net/]] (excellent visual DNS/DNSSEC analysis/troubleshooting)
BIND documentation:
If one has the bind9-doc package installed:
/usr/share/doc/bind9-doc/arm/
/usr/share/doc/bind9-doc/arm/Bv9ARM.html
or from ISC.org (upstream):
An Overview of BIND 9 Documentation (be sure to use corresponding version, and realize there may be some Debian differences).
DNSSEC and BIND 9
DNSSEC Resolver Test
resolver DS and signing algorithm combination tester