Secure DNS: Difference between revisions
m (→What You Need) |
|||
(10 intermediate revisions by 2 users not shown) | |||
Line 6: | Line 6: | ||
==What You Need== |
==What You Need== |
||
; BIND 9.3 : |
; BIND 9.3 : For example available in Debian Testing or Unstable. To get it into Debian Stable put the testing-sources into <var>/etc/apt/sources.list</var>, e.g. <pre><nowiki> deb http://ftp.de.debian.org/debian etch main |
||
deb http://security.debian.org/ etch/updates main</nowiki></pre> and into <var>/etc/apt/apt.conf</var>: <pre> APT::Default-Release "3.1*"</pre>You can then install bind 9.3 with<pre>apt-get install bind9/testing dnsutils/testing</pre> |
deb http://security.debian.org/ etch/updates main</nowiki></pre> and into <var>/etc/apt/apt.conf</var>: <pre> APT::Default-Release "3.1*"</pre>You can then install bind 9.3 with<pre>apt-get install bind9/testing libisccc0/testing dnsutils/testing</pre> |
||
==Key-Management== |
|||
It's best to generate two keypairs for each zone: a key-signing key (KSK) and a zone-signing key (ZSK). |
|||
; Key-signing key : The key-signing key will only be used to sign the zone-signing key and will be the key that is transmitted to the parent zone as a designed signer or to the clients as a secure entry-point. If this key is rolled over all those parties will have to be informed. |
|||
; Zone-signing key : This key is used to actually sign the zone data. If this key is rolled over it will only have to be resigned by the key-signing key with no external notification necessary. |
|||
The keys are generated with |
|||
dnssec-keygen -a RSASHA1 -b 1024 -n ZONE <var>snug.local</var> |
|||
for the zone-signing key and |
|||
dnssec-keygen -f KSK -a RSASHA1 -b 2048 -n ZONE <var>snug.local</var> |
|||
for the key-signing key (where <var>snug.local</var> is the name of the zone). Of course you can choose keysize and algorithm to your heart's content (<tt>dnssec-keygen --help</tt> gives a list of possible combinations), but only DSA and RSASHA1 are required to be implemented. Note also that it would be wise to choose a stronger key for the KSK as it can't be changed easily. For the same reason it should be removed from the computer after use and brought to some safe storage. |
|||
After each key generation the base name of the key files is printed, e.g. |
|||
K<var>snug.local.+005+40668</var> |
|||
With this base name two files are generated: the private key file (<tt>K<var>snug.local.+005+40668</var>.private</tt>) and the public key file (<tt>K<var>snug.local.+005+40668</var>.key</tt>). For obvious reasons the private key should be kept secret. |
|||
The <tt>.key</tt> with the public key will have a DNSKEY suitable for including in a zone file, e.g. like the following (key material omitted for clarity): |
|||
<var>snug.local.</var> IN DNSKEY <var>257</var> 3 5 <var>AQO...USjD</var> |
|||
In BIND the 257 in the fourth column indicates a key-signing key, a zone-signing key would have a 256 there. |
|||
==Signing Zones== |
|||
Before signing the zone there must be two modifications made to the zone: |
|||
# The serial number has to be incremented (as we're going to change the zone data) |
|||
# Both key files have to be included, e.g. like |
|||
$include K<var>snug.local.+005+19919</var>.key ; ZSK |
|||
$include K<var>snug.local.+005+40668</var>.key ; KSK |
|||
<!-- This stupid wiki won't let me include preformatted text within a list item, so the above is not semantically correct. There is a workaround using [pre][nowiki] ... [/nowiki][/pre] (I'm using it at with the definition list close to the top of this page) but someone thought it would be cool to escape all [ in a [pre] into <, so that would 'eat' my [var] markup. |
|||
WTF? For some even more stupid reason I can't use less-than signs in a comment, so I replaced them with [ |
|||
--[[User:Henryk|Henryk]] 14:41, 12 Sep 2005 (CEST) --> |
|||
After that the zone can be signed, e.g. |
|||
dnssec-signzone -o <var>snug.local</var> \ |
|||
-k K<var>snug.local.+005+40668</var> \ |
|||
<var>db.snug.local</var> \ |
|||
K<var>snug.local.+005+19919</var>.key |
|||
where <var>snug.local</var> is the name of the zone, K<var>snug.local.+005+40668</var> is the <em>base name</em> of the key-signing key, <var>db.snug.local</var> is the name of the zonefile and K<var>snug.local.+005+19919</var>.key is the public part of the zone-signing key. |
|||
The <tt>dnssec-signzone</tt> tool will then create an output zone file <var>db.snug.local</var>.signed which should be used instead of <var>db.snug.local</var> in the BIND configuration. Then reload the zones with <tt>rndc reload</tt>. |
|||
==Distributing the keys== |
|||
After the keys are in the DNS you need to distribute the Secure Entry Point to all resolvers that should use it. For this purpose <tt>dnssec-keysign</tt> generated a <tt>keyset-<var>snug.local.</var></tt> file which contains the public key that must be distributed. The file will contain something like |
|||
snug.local 60 IN DNSKEY 257 3 5 ( |
|||
AQO3WtpCi9DeNLkgfGpHT2iWX2CheGzviden |
|||
..... |
|||
iJc0GqBEISlzeaOGS89h |
|||
) ; |
|||
From this the lifetime and <tt>IN DNSKEY</tt> must be stripped and the remaining entry put into the <tt>named.conf</tt> in a trusted-keys section like this: |
|||
trusted-keys { |
|||
"snug.local." 257 3 5 " |
|||
AQO3WtpCi9DeNLkgfGpHT2iWX2CheGzviden |
|||
.... |
|||
iJc0GqBEISlzeaOGS89h |
|||
"; |
|||
}; |
|||
The verifying resolver also needs a |
|||
options { |
|||
recursion yes; |
|||
dnssec-enable yes; |
|||
}; |
|||
==You're secure!== |
|||
Now your zone should be secured. You can test this with <tt>dig</tt> for example: |
|||
chunk:~$ dig ruth.snug.local |
|||
; <<>> DiG 9.3.1 <<>> ruth.snug.local |
|||
;; global options: printcmd |
|||
;; Got answer: |
|||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24773 |
|||
;; flags: qr rd ra '''ad'''; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 |
|||
;; QUESTION SECTION: |
|||
;ruth.snug.local. IN A |
|||
;; ANSWER SECTION: |
|||
ruth.snug.local. 60 IN A 10.0.23.1 |
|||
ruth.snug.local. 60 IN A 10.0.42.1 |
|||
;; Query time: 3 msec |
|||
;; SERVER: 127.0.0.1#53(127.0.0.1) |
|||
;; WHEN: Mon Sep 12 16:01:39 2005 |
|||
;; MSG SIZE rcvd: 65 |
|||
The <tt>'''ad'''</tt> (Authentic Data) flag indicates a response that was successfully authenticated throught DNSSEC. |
|||
=Securing Server-Server communication= |
|||
With a shared secret servers make sure that they receive secured and correct zones. |
|||
How to create a shared secret? |
|||
Every base64 string is okay - you can use a mime-encoded /dev/random or you can use the dnssec-keygen utility to generate good random base64 strings. |
|||
dnssec-keygen -r /dev/random -a HMAC-MD5 -b 128 -n HOST tmp |
|||
This creates two files: A .key file and a .private file, both contain base64 strings. |
|||
Extract this key and put it into both named.conf.local. |
|||
key ruth.snug.local.-clod.snug.local. { |
|||
algorithm hmac-md5; |
|||
secret "OMx1JHEcK+grorUD7PV0sw=="; |
|||
}; |
|||
And put this in our named.conf at our Master-DNS-Server ruth.snug.local. from our domain snug.local. |
|||
zone "snug.local" { |
|||
type master; |
|||
file db.snug.local; |
|||
allow-notify { 10.0.42.2;}; |
|||
allow-transfer { key ruth.snug.local.-clod.snug.local. ; }; |
|||
notify yes; |
|||
}; |
|||
...and for our slave: |
|||
server ruth.snug.local. { |
|||
keys {ruth.snug.local.-clod.snug.local.;}; |
|||
}; |
|||
So Bind uses the secret "OMx..." for every zone-transfer between ruth.snug.local. and clod.snug.local. |
Latest revision as of 16:46, 13 September 2005
Introduction
The DNS Security Extensions, also known as DNSSEC, make it possible verify the authenticity and integrity of data obtained from the domain name system. To enable DNSSEC operation modified resolvers are needed that check data received from DNS servers. On the part of the authoritative name servers no modifications are necessary except for additional DNS records containing the signature data.
Quick How-To
There is an excellent howto available from RIPE at [1].
What You Need
- BIND 9.3
- For example available in Debian Testing or Unstable. To get it into Debian Stable put the testing-sources into /etc/apt/sources.list, e.g.
deb http://ftp.de.debian.org/debian etch main
deb http://security.debian.org/ etch/updates main and into /etc/apt/apt.conf:
APT::Default-Release "3.1*"
You can then install bind 9.3 with
apt-get install bind9/testing libisccc0/testing dnsutils/testing
Key-Management
It's best to generate two keypairs for each zone: a key-signing key (KSK) and a zone-signing key (ZSK).
- Key-signing key
- The key-signing key will only be used to sign the zone-signing key and will be the key that is transmitted to the parent zone as a designed signer or to the clients as a secure entry-point. If this key is rolled over all those parties will have to be informed.
- Zone-signing key
- This key is used to actually sign the zone data. If this key is rolled over it will only have to be resigned by the key-signing key with no external notification necessary.
The keys are generated with
dnssec-keygen -a RSASHA1 -b 1024 -n ZONE snug.local
for the zone-signing key and
dnssec-keygen -f KSK -a RSASHA1 -b 2048 -n ZONE snug.local
for the key-signing key (where snug.local is the name of the zone). Of course you can choose keysize and algorithm to your heart's content (dnssec-keygen --help gives a list of possible combinations), but only DSA and RSASHA1 are required to be implemented. Note also that it would be wise to choose a stronger key for the KSK as it can't be changed easily. For the same reason it should be removed from the computer after use and brought to some safe storage.
After each key generation the base name of the key files is printed, e.g.
Ksnug.local.+005+40668
With this base name two files are generated: the private key file (Ksnug.local.+005+40668.private) and the public key file (Ksnug.local.+005+40668.key). For obvious reasons the private key should be kept secret.
The .key with the public key will have a DNSKEY suitable for including in a zone file, e.g. like the following (key material omitted for clarity):
snug.local. IN DNSKEY 257 3 5 AQO...USjD
In BIND the 257 in the fourth column indicates a key-signing key, a zone-signing key would have a 256 there.
Signing Zones
Before signing the zone there must be two modifications made to the zone:
- The serial number has to be incremented (as we're going to change the zone data)
- Both key files have to be included, e.g. like
$include Ksnug.local.+005+19919.key ; ZSK $include Ksnug.local.+005+40668.key ; KSK
After that the zone can be signed, e.g.
dnssec-signzone -o snug.local \ -k Ksnug.local.+005+40668 \ db.snug.local \ Ksnug.local.+005+19919.key
where snug.local is the name of the zone, Ksnug.local.+005+40668 is the base name of the key-signing key, db.snug.local is the name of the zonefile and Ksnug.local.+005+19919.key is the public part of the zone-signing key.
The dnssec-signzone tool will then create an output zone file db.snug.local.signed which should be used instead of db.snug.local in the BIND configuration. Then reload the zones with rndc reload.
Distributing the keys
After the keys are in the DNS you need to distribute the Secure Entry Point to all resolvers that should use it. For this purpose dnssec-keysign generated a keyset-snug.local. file which contains the public key that must be distributed. The file will contain something like
snug.local 60 IN DNSKEY 257 3 5 ( AQO3WtpCi9DeNLkgfGpHT2iWX2CheGzviden ..... iJc0GqBEISlzeaOGS89h ) ;
From this the lifetime and IN DNSKEY must be stripped and the remaining entry put into the named.conf in a trusted-keys section like this:
trusted-keys { "snug.local." 257 3 5 " AQO3WtpCi9DeNLkgfGpHT2iWX2CheGzviden .... iJc0GqBEISlzeaOGS89h "; };
The verifying resolver also needs a
options { recursion yes; dnssec-enable yes; };
You're secure!
Now your zone should be secured. You can test this with dig for example:
chunk:~$ dig ruth.snug.local ; <<>> DiG 9.3.1 <<>> ruth.snug.local ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24773 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;ruth.snug.local. IN A ;; ANSWER SECTION: ruth.snug.local. 60 IN A 10.0.23.1 ruth.snug.local. 60 IN A 10.0.42.1 ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Sep 12 16:01:39 2005 ;; MSG SIZE rcvd: 65
The ad (Authentic Data) flag indicates a response that was successfully authenticated throught DNSSEC.
Securing Server-Server communication
With a shared secret servers make sure that they receive secured and correct zones.
How to create a shared secret?
Every base64 string is okay - you can use a mime-encoded /dev/random or you can use the dnssec-keygen utility to generate good random base64 strings.
dnssec-keygen -r /dev/random -a HMAC-MD5 -b 128 -n HOST tmp
This creates two files: A .key file and a .private file, both contain base64 strings. Extract this key and put it into both named.conf.local.
key ruth.snug.local.-clod.snug.local. { algorithm hmac-md5; secret "OMx1JHEcK+grorUD7PV0sw=="; };
And put this in our named.conf at our Master-DNS-Server ruth.snug.local. from our domain snug.local.
zone "snug.local" { type master; file db.snug.local; allow-notify { 10.0.42.2;}; allow-transfer { key ruth.snug.local.-clod.snug.local. ; }; notify yes; };
...and for our slave:
server ruth.snug.local. { keys {ruth.snug.local.-clod.snug.local.;}; };
So Bind uses the secret "OMx..." for every zone-transfer between ruth.snug.local. and clod.snug.local.