Very quickly, what is DNSSEC?
A hierarchical system to authenticate (+integrity) DNS to avoid forgery using public key cryptography.You create a set of private/public keys, use private to sign your zone and publish public to your top-level domain via your registrar (who has to support it, see ICANN's list) or publish it to ISC DLV.
When asked for a domain, DNSSEC-enabled resolvers check the hierarchy of signatures. If a domain said it was using DNSSEC but signature is bad, no result.
Why DNSSEC?
I acknowledge it is far from perfect:- Security: Daniel J. Bernstein is a fervent opponent with good arguments, see DNSCurve (alternative to DNSSEC, lists attacks and comparison), his 27c3 talk (DNSCurve vs. DNSSEC, amplification, TCPCurve) or more recently Cryptography worst practices (amplification).
- Complexity: I find it too complex for what it provides, which (IMHO) means very few will use it as it was designed.
- See also Bert Hubert's The role of DNS and DNSSEC in information security, DNSSEC: the good & very bad and DNSSEC: Reality & Utility.
DNS resolver: Unbound
I was using ISC BIND. It supports DNSSEC with:1 2 3 4 | dnssec-enable yes; dnssec-validation auto; // ISC DLV https://dlv.isc.org/about/using dnssec-lookaside . trust-anchor dlv.isc.org.; |
Solution: change software. I wanted to switch to Unbound for some time and the fact that it has the option (domain-insecure) to the previous problem made me switch.
Related fragments of my configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | server: # The following line will configure unbound to perform cryptographic # DNSSEC validation using the root trust anchor. auto-trust-anchor-file: "root.key" # File with DLV trusted keys. Same format as trust-anchor-file. # There can be only one DLV configured, it is trusted from root down. dlv-anchor-file: "dlv.isc.org.key" domain-insecure: 42 domain-insecure: ovh stub-zone: name: "42" stub-addr: 81.93.248.68 stub-addr: 91.194.60.196 stub-addr: 193.17.192.53 stub-zone: name: "ovh" stub-addr: 213.251.128.133 stub-addr: 213.251.188.133 |
DNS server: PowerDNS
DNSSEC is complex to set up and maintain with BIND. There are plenty docs, tools and scripts on the subject, but I wanted something simple.So I turned to PowerDNS by Bert Hubert: it has DNSSEC support since version 3.0 (July 2011) and it's easy (quote: "minimal administrative overhead"). Indeed, PowerDNS handles all the key rotation and resigning maintenance. I acknowledge it is a security trade-off but good enough for me.
Since I like having my zones in BIND text format (easy to edit), I did not switch to MySQL/PostgreSQL/SQLite backends but used the convenient BIND backend.
Fragment from my pdns.conf:
1 2 3 4 | master=yes launch=bind bind-config=named.conf bind-dnssec-db=bind-dnssec.db |
Then to enable DNSSEC on your domain:
1 2 3 4 | $ pdnssec secure-zone example.com $ pdnssec set-nsec3 example.com $ pdnssec rectify-zone example.com # not needed if BIND-only mode $ invoke-rc.d pdns restart |
1 2 | $ pdnssec rectify-zone example.com # not needed if BIND-only mode $ invoke-rc.d pdns reload |
Next, extract public info from your zone: DNSKEY (public key) and DS (hashes of public key) records.
1 | $ pdnssec show-zone example.com |
Finally, check your setup with DNSSEC Analyzer and DNSViz.
Secondary DNS
I was using two free secondary DNS services: BuddyNS and PUCK. Unfortunately BuddyNS does not support DNSSEC, so I switched to PUCK only. Just note that it can be a little slow to update (1+ hour).Cool stuff in DNS which can benefit from DNSSEC
SSHFP (RFC 4255) records, fingerprint of your SSH server:1 2 3 | $ dig +short SSHFP stalkr.net 1 1 D353AA5D599D37647682566ECB8553AE851998EF 2 1 76B50825241C1A85BCFD6954C3DCE2E65D4B71A0 |
PGP keys in DNS. First, PKA (no RFC):
1 2 3 | $ dig +short TXT stalkr._pka.stalkr.net "v=pka1\;fpr=7D6740F72080593D0F71E9863D1D15C9AFCE54F8\; |
1 2 | $ dig +tcp +short CERT stalkr.stalkr.net PGP 0 0 mQGiBEnIIn0RBADwVyT0DtawUJNxHdaKM [...] full cert |
DANE (RFC draft), fingerprint of web server SSL/TLS certificate. Using dane tool from sshfp version 1.2:
1 2 3 | $ dane --rfc stalkr.net _443._tcp.stalkr.net. IN TLSA 1 1 9454E68DBD3A9C0F460 9D033E291D53563A27CAB2C5AF4B482D66024BB841670 |
1 2 3 4 5 | $ echo | openssl s_client -connect stalkr.net:443 2>/dev/null | openssl x509 | \ python -c 'import sys, hashlib; cert="".join(sys.stdin.read().strip().split("\n")[1:-1]); print hashlib.sha256(cert.decode("base64")).hexdigest()' 9454e68dbd3a9c0f4609d033e291d53563a27cab2c5af4b482d66024bb841670 |
DNS(SEC) resources
- DNS health check: IntoDNS, no DNSSEC but it's very good
- SIDN DNSSEC test, tells you if your resolver has DNSSEC support
- VeriSign Labs DNSSEC Analyzer, very good and clear (but no ISC DLV check)
- DNSViz, visual analysis of the DNSSEC authentication chain and resolution path (also checks ISC DLV)
- ICANN's list of registrars that support end user DNSSEC management
- Unbound documentation: unbound.conf
- PowerDNS trac/wiki: PDNSSEC
- PowerDNS doc: Chapter 12. Serving authoritative DNSSEC data and 12.8.3. PowerDNSSEC hybrid BIND-mode operation
- Bert Hubert blog: Easiest DNSSEC ever when running PowerDNS in BIND mode
- DNSSEC-Tools project, useful if you want to use BIND
- Mike Cardwell blog: Understanding DNSSEC, what you can put in DNS (SSL, SSH, PGP, Email/DKIM) and explanation of DNSSEC and DNSSEC with BIND
- PGP keys in DNS, PKA (no RFC) and CERT (RFC 2538, 4398)
- sshfp for SSHFP records (RFC 4255) and since version 1.2 DANE (RFC draft)
- swede tool by Pieter Lexis to create and check TLSA records
Nice writeup, thanks!
ReplyDeleteBert - PowerDNS
Good write up. However, your TLSA record isn't correct:
ReplyDelete----
$ ./swede verify stalkr.net
Received the following record for name _443._tcp.stalkr.net.:
Usage: 1 (End-Entity Constraint + chain to CA)
Selector: 1 (SubjectPublicKeyInfo)
Matching Type: 247 (INVALID)
Certificate for Association: 8e7813af03043dc0f42d05e3ad3d0f4df7136f750f9df9eb7036ec2001d82e40178078f360faeb4db8041f38d7aef4
Error: The TLSA record is invalid.
Matching Type: invalid (247 is not one of 0, 1 or 2)
----
It appears to be based on an older draft (the dane tool is not up-to-date):
----
$ dig +short TYPE65468 _443._tcp.stalkr.net
\# 50 0101F78E7813AF03043DC0F42D05E3AD3D0F4DF7136F750F9DF9EB70 36EC2001D82E40178078F360FAEB4DB8041F38D7AEF4
----
Create a valid one using swede (I'm biased, I made swede): https://github.com/pieterlexis/swede
Good catch but yes, I know ;) I'm using not-up-to-date-with-the-rfc-draft-18 versions of sslh and PowerDNS, hence the comment about the fact it's a changing RFC draft. I will bother to fix this when it's stabilized as RFC, for now it was just to play with it.
ReplyDeleteThanks anyway, especially for the hint to your tool! Very good, I updated the post to link it.
I use PowerDNS with MySQL backend and PowerAdmin for Zones.
ReplyDeleteThey work faultlessly .... Easy to use ..
@Josh : How did you create both keys and update them ?
ReplyDeleteSomething went wrong...
ReplyDeleteWarning! No TLSA records for _443._tcp.stalkr.net. were found.
PKIX validation without DANE will be performed.
91.121.51.205 did not dane-validate, because: Could not PKIX validate
As the output says, the error is because I removed TLSA while it was still a draft. But thanks for your comment, now it's an RFC so I put it back.
ReplyDeleteI used swede to create the TLSA record, with patched m2crypto to use SNI because my web server uses it:
$ swede create -s 1 -o rfc stalkr.net
No certificate specified on the commandline, attempting to retrieve it from the server stalkr.net.
Attempting to get certificate from 91.121.51.205
Got a certificate with Subject: /CN=stalkr.net
_443._tcp.stalkr.net. IN TLSA 1 1 1 a0e5e59adc9932a4d9977fe37c50da32d12119fe1478ffca89620bfa3206b750
Verify works:
$ swede verify stalkr.net
Received the following record for name _443._tcp.stalkr.net.:
Usage: 1 (End-Entity Constraint + chain to CA)
Selector: 1 (SubjectPublicKeyInfo)
Matching Type: 1 (SHA-256)
Certificate for Association: a0e5e59adc9932a4d9977fe37c50da32d12119fe1478ffca89620bfa3206b750
This record is valid (well-formed).
Attempting to verify the record with the TLS service...
Unable to resolve stalkr.net.: Unsuccesful lookup or no data returned for rrtype 28.
Got the following IP: 91.121.51.205
SUCCESS (Usage 1): Certificate offered by the server matches the one mentioned in the TLSA record and chains to a valid CA certificate
The matched certificate has Subject: /CN=stalkr.net
I presume you were using http://check.sidnlabs.nl/dane/?
It fails to validate: "91.121.51.205 did not dane-validate, because: The TLSA record(s) did not match with the server certificate (chain)", but I think it's because they don't include CAcert.
Testing locally http://www.nlnetlabs.nl/projects/ldns/ works:
$ ./ldns-dane verify -f /etc/ssl/certs/ca-certificates.crt stalkr.net 443
91.121.51.205 dane-validated successfully
PUCK gives only one server
ReplyDeletePUCK do support Notify Slaves, so propagation can be fast.
I suggest you also take a look at Roller Network (http://rollernet.us) because it support all three that's important for you : DNSSEC (for security), Notify Slaves (for quick propagation of updated record) and gives two servers (despite both being in the same town, Reno, Nevada).