372 lines
20 KiB
Markdown
372 lines
20 KiB
Markdown
+++
|
|
title = "DNSSEC + DANE: Part 2"
|
|
date = "2013-09-15"
|
|
tags = ["security", "technical", "DANE"]
|
|
+++
|
|
|
|
#### Setting up DNSSEC + DANE ( + SSHFP )
|
|
|
|
Assuming you've been convinced that it's a good idea to set up DNSSEC and DANE,
|
|
the point of this article is to demonstrate how I did it for my own domain -
|
|
the individual steps to get from nothing to valid DANE records weren't very
|
|
difficult; just not documented in a recipe-style guide anywhere. Hopefully,
|
|
this will help you get set up. I'm using Debian Squeeze or Wheezy throughout,
|
|
depending on host, but the instructions should be similar for most Linux
|
|
distributions.
|
|
|
|
#### DNSSEC
|
|
|
|
This is the part that provides the hierarchical trust model, enabling a random
|
|
user of your site to trust (more or less, anyway) that when they ask for a
|
|
record that tells them which certificates are valid for their site, they
|
|
get the same record that you're going to upload later.
|
|
|
|
|
|
##### Resolving nameserver
|
|
|
|
Firstly, the user needs to be able to make DNSSEC-validatable DNS queries to
|
|
begin with. This requires that their caching (also known as resolving) nameserver
|
|
supports DNSSEC queries. This is easy enough to test:
|
|
|
|
lupine@den:~$ dig +dnssec mozilla.org
|
|
|
|
; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +dnssec mozilla.org
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25143
|
|
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 4, ADDITIONAL: 7
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags: do; udp: 4096
|
|
;; QUESTION SECTION:
|
|
;mozilla.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
mozilla.org. 60 IN A 63.245.217.105
|
|
mozilla.org. 60 IN RRSIG A 7 2 60 20131013124658 20130913125405 17933 mozilla.org. k2LOpTkl35qIPmFKVQix87mItL2ycPFTymx0yoZoIt+jpsGhEbQWgiiV FXndEwOKap/RsXdHtzWWWI4vcDdQgES0X/XInAxRKTadceapQ34Nyb0w TN9CpYidxpI35MY9cseZVu9eCKXq0M7VxpSBKSHshby2A/hymJntq1lD sSI=
|
|
mozilla.org. 60 IN RRSIG A 7 2 60 20131013125201 20130913125405 63920 mozilla.org. N/dNbs71T0oEAJ0ulqeVPg4ty7UwG02QKOFr3tRy0kDpnRsPvIKX8E0e lVxCU/TCEckfS8QQv3JytoOrIwKt/Y1lOI//NuxLIZT8RndMvWaROkrt Ncs3moQAsD6w0sT+Yn7wx1AimVO4udQ8dh3lyYCKHdRq8VfxyK6/5Lws tzQ=
|
|
|
|
;; AUTHORITY SECTION:
|
|
mozilla.org. 60 IN NS ns2.mozilla.org.
|
|
mozilla.org. 60 IN NS ns1.mozilla.org.
|
|
mozilla.org. 60 IN RRSIG NS 7 2 60 20131013125024 20130913125405 17933 mozilla.org. MlltXDEKazn80b3mMqGSOhCCqeQhuiIsgMXI+kaAABnwXyxzHsli+BEL f1AC3Grog3p9DLtRUPbAm3RWIF6HWgd5gJJ5rcw+50ihWVEwQceWniKD Sl/13G7V8pKR0P4GZjpTg//Go4H6xYZAThhU544zjxis5ytupM+rAW0I +ho=
|
|
mozilla.org. 60 IN RRSIG NS 7 2 60 20131013125355 20130913125405 63920 mozilla.org. KnOTFZRq6f3K6wbfa6YMjVROHc6kr+RzvthX531H7AQjejB0yAc6ttyI q9J3u/cDg2sdsmROJ91JXkmU7Kjq+LJKrRedQPwY0xLr57ODK/87D3Kv Z9icf5HxarvdN4FlPb7j/uI8EIN4jKXb08976KtPu7BT+6o+1b+rwUWf Ccc=
|
|
|
|
;; ADDITIONAL SECTION:
|
|
ns1.mozilla.org. 60 IN A 63.245.215.5
|
|
ns2.mozilla.org. 60 IN A 63.245.218.7
|
|
ns1.mozilla.org. 60 IN RRSIG A 7 3 60 20131013124618 20130913125405 63920 mozilla.org. e1mdvK7ERSuaNIxSf1O+8vyFJWoGBGGPSFt20KLiF+KBU1siDlywTTBr /UT5cNBB4prqcZ0DdFagnmWE2OploEqof0Nl/IiSPwVGy8eGksGmS0Qf zK78emWv4nQmVkiVokcZqIHiAXPxG9ZafJaTo/BGtnThILmatdnk2xuI JdY=
|
|
ns1.mozilla.org. 60 IN RRSIG A 7 3 60 20131013125230 20130913125405 17933 mozilla.org. 1wWdtXpmOk9oOwzl8j8Jvz2IyqfVXIMfB9kDRC0AUKQNvUDk85Xp6AfE 2i4vaupFRa5RTKKj4gBTYRqfObhdrJHLNIRx1BMb/mb/B/8IF0HuxXeU IlGU8Wu/GbDHOHrS42Z3i2w9Y+DVUI1JQQlPHapDtD20kzKnClIN9iSa FRo=
|
|
ns2.mozilla.org. 60 IN RRSIG A 7 3 60 20131013125059 20130913125405 17933 mozilla.org. WcnS3dw6gQ6gM5dP6tKGK+Gwkd3u8AMco2WCU3WzLoK0ADeJo9qjYGzd pSnJLRRMfiKBeWZJvm6g89sS+gPQh1IlncPp6AaGQdAAyl+OtwIswA/n qPQLlWBdJQrfAnzLKDXbOjTH2K9vXxNSUyAL5QzUgLIAB16oTvREbL42 bIc=
|
|
ns2.mozilla.org. 60 IN RRSIG A 7 3 60 20131013125237 20130913125405 63920 mozilla.org. V2xTFK6cG9v+mBKbZP7a5yXFJUaXKAt1qOP0VmHWrP1n5lNfvcOMrKLc g4vpaxdbA0M1B7xMhX4ps2IYljAUZdzkBCMXp+bYKPKXdkxKRmXsnspF 7Fii5N9q7FKyhLEbsW8G9MRTScE0ohu5s8db6hOGmkcbyvZJmk5+R1Qd aAk=
|
|
|
|
;; Query time: 285 msec
|
|
;; SERVER: 213.138.102.177#53(213.138.102.177)
|
|
;; WHEN: Sat Sep 14 16:54:58 2013
|
|
;; MSG SIZE rcvd: 1492
|
|
|
|
lupine@den:~$
|
|
|
|
If you see RRSIG records, as above, then you don't need to do anything. If you
|
|
don't, then your resolver doesn't support DNSSEC. This is fairly common. As a
|
|
first resort, ask your provider (normally your ISP) to fix it. If that doens't
|
|
bear fruit, or if you're impatient, you can install and use the
|
|
[Unbound](http://unbound.net/][Unbound) resolver.
|
|
|
|
I was in the latter situation, and my router happens to run a hacked-up version
|
|
of Debian Squeeze, so I installed Unbound on it and configured the DHCP server
|
|
to refer to it when configuring clients; so every machine on my home network
|
|
now has access to a DNSSEC-capable resolver. You can also install and use it
|
|
locally, which might look like this:
|
|
|
|
root@den:~# apt-get install unbound # unbound-anchor # for wheezy
|
|
root@den:~# echo "nameserver 127.0.0.1" > /etc/resolv.conf
|
|
root@den:~# chattr +i /etc/resolv.conf
|
|
|
|
The resolv.conf file can be managed and altered in a number of ways - I can't
|
|
actually recommend altering it to point to the Unbound instance you just
|
|
installed and making it immutable. If your desktop environment manages DHCP
|
|
for you, then you should investigate options for providing the DNS manually.
|
|
Debian also has the `resolveconf` package which would allow you to specify
|
|
static fragments to go into resolv.conf. If you're old-fashioned and are
|
|
using static configuation + /etc/network/interfaces, then the dns-nameservers
|
|
directive will let you specify 127.0.0.1 - your local Unbound instance.
|
|
|
|
** Browser (and other application) support
|
|
|
|
Now that you can get DNSSEC records from your resolver, through means fair or
|
|
foul, you need client application support. Firefox has a
|
|
[plugin](https://os3sec.org/) or [two](https://www.dnssec-validator.cz/)
|
|
that also support DANE; the equivalent
|
|
[Chrome plugin](https://chrome.google.com/webstore/detail/dnssec-validator/hpmbmjbcmglolhjdcbicfdhmgmcoeknm)
|
|
only supports DNSSEC. Internet Explorer is probably Right Out, and I have no
|
|
idea about Opera, Safari, and the rest. Another option is to install the
|
|
[Bloodhound](https://www.dnssec-tools.org/wiki/index.php/Bloodhound) browser.
|
|
Apparently.
|
|
|
|
Web browsers aren't the only applications that could make use of DNSSEC and
|
|
DANE, of course. Mail and XMPP are two other important protocols; Thunderbird
|
|
has no DNSSEC plugin at the moment, as far as I'm aware, and neither does Gajim
|
|
or Pidgin. Let me know if you're aware of any replacements that do - there's
|
|
obviously work to be done when it comes to client support. The more servers
|
|
support DNSSEC, the more pressure there is on client applications to support
|
|
it, of course. For now, open this web page on your DNSSEC-capable browser and
|
|
ensure that the DNSSEC plugin is happy.
|
|
|
|
##### Domain
|
|
|
|
Now that you've got a client environment that can handle DNSSEC records, it's
|
|
time to look at getting your own domain DNSSEC-signed. I'll be using lupine.me.uk
|
|
as an example throughout; you need to pick (or register) a domain from a
|
|
[DNSSEC-supporting registry](http://dnssec-deployment.org/), and you should
|
|
ensure that it's with a registrar that allows you to upload so-called DNSKEY
|
|
records to that registry. For me, the answers were ".me.uk" (now ".gs") and
|
|
"gandi" - they may be different for you.
|
|
|
|
##### Authoritative nameserver
|
|
|
|
Once you've got your domain, you need to decide how you're going to serve DNS
|
|
with it, in general. I was lazy and just set up my DNS server on the same machine
|
|
as the website - that's not generally appropriate for production, but a common
|
|
deployment is to have a DNS master on the same machine as the website, with
|
|
geographically-diverse slave servers doing zone transfers over AXFR. I'll just
|
|
look at sorting out one nameserver - a.ns.lupine.me.uk - though.
|
|
|
|
The best authoritative nameserver - by far - for DNSSEC support is
|
|
[PowerDNS](https://www.powerdns.com/][PowerDNS).
|
|
It handles all the difficult details that, if I'm quite honest, I don't really
|
|
understand. Debian Squeeze includes version 2.9, and DNSSEC support comes in
|
|
the 3.x series, so I installed the 3.3 static package available on the
|
|
[website](https://www.powerdns.com/downloads.html) and installed it.
|
|
Wheezy backports, and Debian Jessie, are both easier to deal with.
|
|
|
|
PowerDNS is fairly configurable, particularly for backends; I used its sqlite3
|
|
backend, and setting it up for that looks like this:
|
|
|
|
root@oak:/etc/powerdns/pdns.d# cat 00-sqlite3-backend.conf
|
|
launch=gsqlite3
|
|
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
|
|
gsqlite3-dnssec=yes
|
|
|
|
The pdns.sqlite3 file is autogenerated when you restart PowerDNS, but it lacks
|
|
certain schema elements that are necessary for DNSSEC. You can add them by
|
|
running the commands detailed
|
|
[here](http://doc.powerdns.com/html/gsqlite.html#idp36763616)
|
|
- for completeness, they're duplicated below.
|
|
|
|
root@oak:~# sqlite3 /var/lib/powerdns/pdns.sqlite3
|
|
sqlite> alter table records add ordername VARCHAR(255);
|
|
sqlite> alter table records add auth bool;
|
|
sqlite> create index orderindex on records(ordername);
|
|
sqlite> create table domainmetadata (
|
|
id INTEGER PRIMARY KEY,
|
|
domain_id INT NOT NULL,
|
|
kind VARCHAR(16) COLLATE NOCASE,
|
|
content TEXT
|
|
);
|
|
sqlite> create index domainmetaidindex on domainmetadata(domain_id);
|
|
sqlite> create table cryptokeys (
|
|
id INTEGER PRIMARY KEY,
|
|
domain_id INT NOT NULL,
|
|
flags INT NOT NULL,
|
|
active BOOL,
|
|
content TEXT
|
|
);
|
|
sqlite> create index domainidindex on cryptokeys(domain_id);
|
|
sqlite> create table tsigkeys (
|
|
id INTEGER PRIMARY KEY,
|
|
name VARCHAR(255) COLLATE NOCASE,
|
|
algorithm VARCHAR(50) COLLATE NOCASE,
|
|
secret VARCHAR(255)
|
|
);
|
|
sqlite> create unique index namealgoindex on tsigkeys(name, algorithm);
|
|
|
|
Now add some ordinary DNS records for PowerDNS to serve:
|
|
|
|
sqlite> insert into domains (name, type) VALUES('lupine.me.uk', 'NATIVE');
|
|
sqlite> select id from domains where name = 'lupine.me.uk';
|
|
1 # This may be different for you - I set domain_id below to it
|
|
# Set your own SOA serial value according to what you prefer
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, 'lupine.me.uk', 'SOA', 'a.ns.lupine.me.uk nick.lupine.me.uk 1378936223', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, 'lupine.me.uk', 'NS', 'a.ns.lupine.me.uk', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, 'a.ns.lupine.me.uk', 'A', '213.138.100.8', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, 'lupine.me.uk', 'MX', 'lupine.me.uk', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, 'www.lupine.me.uk', 'CNAME', 'lupine.me.uk', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, '*.chat.lupine.me.uk', 'CNAME', 'lupine.me.uk', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, '_xmpp-client._tcp.lupine.me.uk', 'SRV', '0 5222 lupine.me.uk', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES(
|
|
1, '_xmpp-server._tcp.lupine.me.uk', 'SRV', '0 5269 lupine.me.uk', 3600
|
|
);
|
|
|
|
At this point, the PowerDNS server will respond to DNS requests, but they're
|
|
not DNSSEC-signed. Enabling DNSSEC for the domain is as simple as:
|
|
|
|
root@oak:~# pdnssec secure-zone lupine.me.uk
|
|
Securing zone with rsasha256 algorithm with default key size
|
|
Zone lupine.me.uk secured
|
|
root@oak:~# pdnssec set-nsec3 lupine.me.uk
|
|
NSEC3 set, please rectify-zone if your backend needs it
|
|
root@oak:~# pdnssec rectify-zone lupine.me.uk
|
|
Adding NSEC3 hashed ordering information for 'lupine.me.uk'
|
|
root@oak:~# pdnssec check-zone lupine.me.uk
|
|
Checked 14 records of 'lupine.me.uk', 0 errors, 0 warnings.
|
|
root@oak:~# pdnssec show-zone lupine.me.uk
|
|
Zone is not presigned
|
|
Zone has hashed NSEC3 semantics, configuration: 1 0 1 ab
|
|
keys:
|
|
ID = 1 (KSK), tag = 7450, algo = 8, bits = 2048 Active: 1 ( RSASHA256 )
|
|
KSK DNSKEY = lupine.me.uk IN DNSKEY 257 3 8 [...] ; ( RSASHA256 )
|
|
DS = lupine.me.uk IN DS 7450 8 1 [...] ; ( SHA1 digest )
|
|
DS = lupine.me.uk IN DS 7450 8 2 [...] ; ( SHA256 digest )
|
|
DS = lupine.me.uk IN DS 7450 8 3 [...] ; ( GOST R 34.11-94 digest )
|
|
DS = lupine.me.uk IN DS 7450 8 4 [...] ; ( SHA-384 digest )
|
|
ID = 2 (ZSK), tag = 15433, algo = 8, bits = 1024 Active: 1 ( RSASHA256 )
|
|
root@oak:~#
|
|
|
|
Now we have a signed DNSSEC zone. If you check the SQLite3 database, you'll
|
|
see new records have been generated to match the DNSKEY and DS records displayed
|
|
by the show-zone command, and the records you've added will have had various
|
|
bits of mysterious glue added. The finer points of DNSSEC are still lost on
|
|
me, but the important thing to note is that the "KSK DNSKEY" is the important
|
|
record that allows the chain of trust to be developed; this record is given
|
|
to the upstream zone via your registry (the ".me.uk" zone for me), who sign
|
|
it with their key. It is rotated every year or so, and you need to inform
|
|
the registry whenever it changes; you can have multiple active ones at once.
|
|
PowerDNS has some documentation on key management best practices
|
|
[here](http://doc.powerdns.com/html/dnssec-operational-doctrine.html),
|
|
but I've not needed to fuss with any of this, yet.
|
|
|
|
So, take your DNSKEY record (or possibly DS record - different registrars
|
|
apparently might ask you for different things) and give it to your registrar.
|
|
Gandi has a neat "Enable DNSSEC" form you can use; others may vary.
|
|
|
|
Once they have the record, you're ready to change the nameservers for the
|
|
domain to point to the DNS server you've just set up. I did this in gandi's
|
|
panel, and additional hoops I needed to jump through (because the nameserver
|
|
was in the lupine.me.uk zone) included notifying Nominet of the "a.ns.lupine.me.uk"
|
|
name, as well as notifying them of the "glue" between the name and its IP
|
|
addresses. This varies quite considerably by registry and registrar, so I'll
|
|
leave it as an exercise to the reader.
|
|
|
|
#### DANE
|
|
|
|
Now that we have a DNSSEC-signed zone, we can add records to it, as defined by
|
|
RFC 6698. Unless someone is able to compromise the DNS trust anchor, your
|
|
registry's keys, or your keys, anyone looking these records up can be confident
|
|
that they are the ones you uploaded.
|
|
|
|
##### Getting a certificate
|
|
|
|
If you already have a self-signed or CA-issued certificate that you intend to
|
|
use, then great. If not, you can either buy one from a CA, or become your own
|
|
mini-CA and issue one for yourself. I'm sticking with a CA-issued one for the
|
|
next few months, because although DNSSEC has poor client support, DANE support
|
|
is entirely non-existent; so the value of a non-CA-certified certificate is
|
|
still almost nil. Using a CA-issued certificate (mine is from StartSSL, and
|
|
was free) in conjunction with DANE is OK - DANE-aware clients will detect
|
|
traditionally-MitM'd certificates from such a record - but you miss out on
|
|
a couple of benefits. Specifically, you're still dependent on the CA to support
|
|
sensible (or new/experimental) key types, and if you let the CA generate the
|
|
private key rather than going the CSR route (don't do this, ever) then you're
|
|
trusting them not to keep a record of what it was.
|
|
|
|
I may talk about how to generate a self-signed certificate here in the future.
|
|
|
|
##### Generating records
|
|
|
|
Once you've got your certificate and configured your various services to use
|
|
it (HTTPS especially, but also XMPP, IMAPS, SSMTP, etc), it's time to link
|
|
it all together in the DNS. Generating the records (which are known as TLSA
|
|
records) is a pain, but there is a tool - called [swede](https://github.com/pieterlexis/swede][swede) -
|
|
to do it for you. It's Python, only works against HTTPS, and you'd get and
|
|
use it like this:
|
|
|
|
lupine@den:~/Development$ git clone https://github.com/pieterlexis/swede
|
|
Cloning into 'swede'...
|
|
remote: Counting objects: 116, done.
|
|
remote: Compressing objects: 100% (55/55), done.
|
|
remote: Total 116 (delta 67), reused 107 (delta 59)
|
|
Receiving objects: 100% (116/116), 21.83 KiB, done.
|
|
Resolving deltas: 100% (67/67), done.
|
|
lupine@den:~/Development$ cd swede
|
|
lupine@den:~/Development/swede$ sudo apt-get install python-unbound python-argparse python-ipaddr python-m2crypto
|
|
# [...]
|
|
lupine@den:~/Development/swede$ ./swede create --output rfc lupine.me.uk
|
|
No certificate specified on the commandline, attempting to retrieve it from the server lupine.me.uk.
|
|
Attempting to get certificate from 213.138.100.8
|
|
M2Crypto does not support SNI: services using virtual-hosting will show the wrong certificate!
|
|
Got a certificate with Subject: /description=z3YBHiV5NCKOeIZs/C=GB/CN=www.lupine.me.uk/emailAddress=postmaster@lupine.me.uk
|
|
_443._tcp.lupine.me.uk. IN TLSA 1 0 1 9730ccc0952f3150bc3c640aedb364bd628bc1738ada89826624d9442589eb06
|
|
|
|
That last line is the TLSA record that identfies your certificate. Even though
|
|
swede only supports HTTPS, you can change _443 to _5222 and you've got an XMPP
|
|
record - so let's add a sensible set of TLSA records for this certificate to
|
|
DNS.
|
|
|
|
root@oak:~# sqlite3 /var/lib/powerdns/pdns.sqlite3
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES (
|
|
1, '_443._tcp.lupine.me.uk', 'TLSA', '1 0 1 9730ccc0952f3150bc3c640aedb364bd628bc1738ada89826624d9442589eb06', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES (
|
|
1, '_993._tcp.lupine.me.uk', 'TLSA', '1 0 1 9730ccc0952f3150bc3c640aedb364bd628bc1738ada89826624d9442589eb06', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES (
|
|
1, '_5222._tcp.lupine.me.uk', 'TLSA', '1 0 1 9730ccc0952f3150bc3c640aedb364bd628bc1738ada89826624d9442589eb06', 3600
|
|
);
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES (
|
|
1, '_5269._tcp.lupine.me.uk', 'TLSA', '1 0 1 9730ccc0952f3150bc3c640aedb364bd628bc1738ada89826624d9442589eb06', 3600
|
|
);
|
|
sqlite> .exit
|
|
root@oak:~# pdnssec increase-serial lupine.me.uk && pdnssec rectify-all-zones
|
|
|
|
|
|
Now when you visit your website in a DANE-enabled browser, you'll see the
|
|
certificate is considered valid; you could remove all CA certificates from it
|
|
or use a self-signed certificate to the same end. Success!
|
|
|
|
|
|
#### SSHFP
|
|
|
|
As a fillip, now that you've done all that work, you can also add SSHFP records
|
|
to smooth SSH access. That looks like this:
|
|
|
|
root@oak:~# sshfp --scan lupine.me.uk
|
|
WARNING: Ignoring -k option, -s was passwd
|
|
# lupine.me.uk SSH-2.0-OpenSSH_5.5p1 Debian-6+squeeze3
|
|
# lupine.me.uk SSH-2.0-OpenSSH_5.5p1 Debian-6+squeeze3
|
|
|
|
lupine.me.uk IN SSHFP 1 1 08C614DAF69DA62937FEFFA025607569B54B8D08
|
|
lupine.me.uk IN SSHFP 2 1 67B596A0A593A931DAD21C83F6E7B9F02CBFE6F5
|
|
|
|
root@oak:~# sqlite3 /var/lib/powerdns/pdns.sqlite3
|
|
sqlite> insert into records (domain_id, name, type, content, ttl) VALUES (
|
|
1, 'lupine.me.uk', 'SSHFP', '1 1 08C614DAF69DA62937FEFFA025607569B54B8D08', 3600
|
|
);
|
|
sqlite> # ...
|
|
sqlite> .exit
|
|
root@oak:~# pdnssec increase-serial lupine.me.uk && pdnssec rectify-all-zones
|
|
|
|
To make use of this, you'll also need to alter your ssh_config:
|
|
|
|
lupine@den:~$ echo "\n\nVerifyHostKeyDNS yes" >> ~/.ssh/config
|
|
|
|
The outcome is that when logging into your machines over SSH from a new
|
|
location, your SSH client can check the presented host key fingerprints
|
|
against the ones in DNS, and warn you if they don't match for any reason -
|
|
a man-in-the-middle attack, for instance. Or a server reinstall, of course.
|
|
|