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:dnssec-enable yes; dnssec-validation auto; // ISC DLV https://dlv.isc.org/about/using dnssec-lookaside . trust-anchor dlv.isc.org.;But problem if you also want to resolve alternative TLDs such as .42 or .ovh, they will not resolve because insecure and BIND does not have an option to mark domains as insecure.
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:
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. # http://ftp.isc.org/www/dlv/dlv.isc.org.key dlv-anchor-file: "dlv.isc.org.key" domain-insecure: 42 domain-insecure: ovh # http://wiki.42registry.org/page/Resolve 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.133Rest of the configuration is simple.
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:
master=yes launch=bind bind-config=named.conf bind-dnssec-db=bind-dnssec.dbThis bind-dnssec-db is very new. For older 3.0 versions and according to the doc, you need to use an extra sqlite3 backend and insert a new record for your domain (but that's all, PowerDNS takes care of the rest).
Then to enable DNSSEC on your domain:
$ 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 restartWhat if you update the zone file? Rectify + reload:
$ 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.
$ pdnssec show-zone example.comand publish it to your registrar (who will send it to your top-level domain) and/or to ISC DNSSEC Look-aside Validation (DLV) Registry.
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:$ dig +short SSHFP stalkr.net 1 1 D353AA5D599D37647682566ECB8553AE851998EF 2 1 76B50825241C1A85BCFD6954C3DCE2E65D4B71A0Then use VerifyHostKeyDNS yes.
PGP keys in DNS. First, PKA (no RFC):
$ dig +short TXT stalkr._pka.stalkr.net "v=pka1\;fpr=7D6740F72080593D0F71E9863D1D15C9AFCE54F8\; uri=http://stalkr.net/pgp.asc"Second, CERT (RFC 2538, 4398):
$ 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:
$ dane --rfc stalkr.net _443._tcp.stalkr.net. IN TLSA 1 1 9454E68DBD3A9C0F460 9D033E291D53563A27CAB2C5AF4B482D66024BB841670The fingerprint is indeed the one from my webserver:
$ 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()' 9454e68dbd3a9c0f4609d033e291d53563a27cab2c5af4b482d66024bb841670Warning though, it's still an RFC draft and is changing, but when it settles it should be good!
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).