add SSHFP records to DNS

This commit is contained in:
Joshua Tauberer 2014-08-27 12:56:17 +00:00
parent 684d9b3c70
commit 10a37cd033
3 changed files with 47 additions and 4 deletions

View File

@ -13,7 +13,7 @@ Why build this? Mass electronic surveillance by governments revealed over the la
The Box The Box
------- -------
Mail-in-a-Box turns a fresh Ubuntu 14.04 LTS 64-bit machine into a working mail server, including SMTP ([postfix](http://www.postfix.org/)), IMAP ([dovecot](http://dovecot.org/)), Exchange ActiveSync ([z-push](https://github.com/fmbiete/Z-Push-contrib)), webmail ([Roundcube](http://roundcube.net/)), spam filtering ([spamassassin](https://spamassassin.apache.org/)), greylisting ([postgrey](http://postgrey.schweikert.ch/)), CardDAV/CalDAV ([ownCloud](http://owncloud.org/)), DNS, [SPF](https://en.wikipedia.org/wiki/Sender_Policy_Framework), DKIM ([OpenDKIM](http://www.opendkim.org/)), [DMARC](https://en.wikipedia.org/wiki/DMARC), [DNSSEC](https://en.wikipedia.org/wiki/DNSSEC), [DANE TLSA](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities), and basic system services like a firewall, intrusion protection, and setting the system clock. Mail-in-a-Box turns a fresh Ubuntu 14.04 LTS 64-bit machine into a working mail server, including SMTP ([postfix](http://www.postfix.org/)), IMAP ([dovecot](http://dovecot.org/)), Exchange ActiveSync ([z-push](https://github.com/fmbiete/Z-Push-contrib)), webmail ([Roundcube](http://roundcube.net/)), spam filtering ([spamassassin](https://spamassassin.apache.org/)), greylisting ([postgrey](http://postgrey.schweikert.ch/)), CardDAV/CalDAV ([ownCloud](http://owncloud.org/)), DNS, [SPF](https://en.wikipedia.org/wiki/Sender_Policy_Framework), DKIM ([OpenDKIM](http://www.opendkim.org/)), [DMARC](https://en.wikipedia.org/wiki/DMARC), [DNSSEC](https://en.wikipedia.org/wiki/DNSSEC), [DANE TLSA](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities), [SSHFP](https://tools.ietf.org/html/rfc4255), and basic system services like a firewall, intrusion protection, and setting the system clock.
This setup is what has been powering my own personal email since September 2013. This setup is what has been powering my own personal email since September 2013.

View File

@ -4,7 +4,7 @@
# and mail aliases and restarts nsd. # and mail aliases and restarts nsd.
######################################################################## ########################################################################
import os, os.path, urllib.parse, datetime, re, hashlib import os, os.path, urllib.parse, datetime, re, hashlib, base64
import ipaddress import ipaddress
import rtyaml import rtyaml
@ -160,6 +160,10 @@ def build_zone(domain, all_domains, additional_records, env, is_zone=True):
# Add a DANE TLSA record for SMTP. # Add a DANE TLSA record for SMTP.
records.append(("_25._tcp", "TLSA", build_tlsa_record(env), "Recommended when DNSSEC is enabled. Advertises to mail servers connecting to the box that mandatory encryption should be used.")) records.append(("_25._tcp", "TLSA", build_tlsa_record(env), "Recommended when DNSSEC is enabled. Advertises to mail servers connecting to the box that mandatory encryption should be used."))
# Add a SSHFP records to help SSH key validation. One per available SSH key on this system.
for value in build_sshfp_records():
records.append((None, "SSHFP", value, "Optional. Provides an out-of-band method for verifying an SSH key before connecting. Use 'VerifyHostKeyDNS yes' (or 'VerifyHostKeyDNS ask') when connecting with ssh."))
# The MX record says where email for the domain should be delivered: Here! # The MX record says where email for the domain should be delivered: Here!
records.append((None, "MX", "10 %s." % env["PRIMARY_HOSTNAME"], "Required. Specifies the hostname (and priority) of the machine that handles @%s mail." % domain)) records.append((None, "MX", "10 %s." % env["PRIMARY_HOSTNAME"], "Required. Specifies the hostname (and priority) of the machine that handles @%s mail." % domain))
@ -289,6 +293,41 @@ def build_tlsa_record(env):
# 1: The certificate is SHA256'd here. # 1: The certificate is SHA256'd here.
return "3 0 1 " + certhash return "3 0 1 " + certhash
def build_sshfp_records():
# The SSHFP record is a way for us to embed this server's SSH public
# key fingerprint into the DNS so that remote hosts have an out-of-band
# method to confirm the fingerprint. See RFC 4255 and RFC 6594. This
# depends on DNSSEC.
#
# On the client side, set SSH's VerifyHostKeyDNS option to 'ask' to
# include this info in the key verification prompt or 'yes' to trust
# the SSHFP record.
#
# See https://github.com/xelerance/sshfp for inspiriation.
algorithm_number = {
"ssh-rsa": 1,
"ssh-dss": 2,
"ecdsa-sha2-nistp256": 3,
}
# Get our local fingerprints by running ssh-keyscan. The output looks
# like the known_hosts file: hostname, keytype, fingerprint.
keys = shell("check_output", ["ssh-keyscan", "localhost"])
for key in keys.split("\n"):
if key.strip() == "" or key[0] == "#": continue
try:
host, keytype, pubkey = key.split(" ")
yield "%d %d ( %s )" % (
algorithm_number[keytype],
2, # specifies we are using SHA-256 on next line
hashlib.sha256(base64.b64decode(pubkey)).hexdigest().upper(),
)
except:
# Lots of things can go wrong. Don't let it disturb the DNS
# zone.
pass
######################################################################## ########################################################################
def write_nsd_zone(domain, zonefile, records, env, force): def write_nsd_zone(domain, zonefile, records, env, force):
@ -497,7 +536,7 @@ def sign_zone(domain, zonefile, env):
# Remove our temporary file. # Remove our temporary file.
for fn in files_to_kill: for fn in files_to_kill:
os.unlink(fn) os.unlink(fn)
######################################################################## ########################################################################
def write_opendkim_tables(zonefiles, env): def write_opendkim_tables(zonefiles, env):

View File

@ -22,8 +22,12 @@ else
fi fi
# Okay now install the packages. # Okay now install the packages.
#
# nsd: The non-recursive nameserver that publishes our DNS records.
# ldnsutils: Helper utilities for signing DNSSEC zones.
# openssh-client: Provides ssh-keyscan which we use to create SSHFP records.
apt_install nsd ldnsutils apt_install nsd ldnsutils openssh-client
# Prepare nsd's configuration. # Prepare nsd's configuration.