add DANE TLSA records to the PUBLIC_HOSTNAME's DNS
Postfix has a tls_security_level called "dane" which uses DNS-Based Authentication of Named Entities (DANE) to require, if specified in the DNS of the MX host, an encrpyted connection with a known certificate. This commit adds TLSA records.
This commit is contained in:
parent
699bccad80
commit
95e61bc110
|
@ -2,7 +2,7 @@
|
|||
# and mail aliases and restarts nsd.
|
||||
########################################################################
|
||||
|
||||
import os, os.path, urllib.parse, datetime, re
|
||||
import os, os.path, urllib.parse, datetime, re, hashlib
|
||||
import rtyaml
|
||||
|
||||
from mailconfig import get_mail_domains
|
||||
|
@ -126,11 +126,15 @@ def build_zone(domain, zonefile, env, with_ns=True):
|
|||
child_qname += "." + ph
|
||||
records.append((child_qname, child_rtype, child_value))
|
||||
|
||||
# In PUBLIC_HOSTNAME, also define ns1 and ns2.
|
||||
# In PUBLIC_HOSTNAME...
|
||||
if domain == env["PUBLIC_HOSTNAME"]:
|
||||
# Define ns1 and ns2.
|
||||
records.append(("ns1", "A", env["PUBLIC_IP"]))
|
||||
records.append(("ns2", "A", env["PUBLIC_IP"]))
|
||||
|
||||
# Add a TLSA record for SMTP.
|
||||
records.append(("_25._tcp", "TLSA", build_tlsa_record(env)))
|
||||
|
||||
def has_rec(qname, rtype):
|
||||
for rec in records:
|
||||
if rec[0] == qname and rec[1] == rtype:
|
||||
|
@ -175,6 +179,32 @@ def build_zone(domain, zonefile, env, with_ns=True):
|
|||
|
||||
########################################################################
|
||||
|
||||
def build_tlsa_record(env):
|
||||
# A TLSA record in DNS specifies that connections on a port, e.g.
|
||||
# the SMTP port, must use TLS and the certificate must match a
|
||||
# particular certificate.
|
||||
#
|
||||
# Thanks to http://blog.huque.com/2012/10/dnssec-and-certificates.html
|
||||
# for explaining all of this!
|
||||
|
||||
# Get the hex SHA256 of the DER-encoded server certificate:
|
||||
certder = shell("check_output", [
|
||||
"/usr/bin/openssl",
|
||||
"x509",
|
||||
"-in", os.path.join(env["STORAGE_ROOT"], "ssl", "ssl_certificate.pem"),
|
||||
"-outform", "DER"
|
||||
],
|
||||
return_bytes=True)
|
||||
certhash = hashlib.sha256(certder).hexdigest()
|
||||
|
||||
# Specify the TLSA parameters:
|
||||
# 3: This is the certificate that the client should trust. No CA is needed.
|
||||
# 0: The whole certificate is matched.
|
||||
# 1: The certificate is SHA256'd here.
|
||||
return "3 0 1 " + certhash
|
||||
|
||||
########################################################################
|
||||
|
||||
def write_nsd_zone(domain, zonefile, records, env):
|
||||
# We set the administrative email address for every domain to domain_contact@[domain.com].
|
||||
# You should probably create an alias to your email address.
|
||||
|
|
|
@ -81,12 +81,12 @@ def is_pid_valid(pid):
|
|||
else:
|
||||
return True
|
||||
|
||||
def shell(method, cmd_args, env={}, capture_stderr=False):
|
||||
def shell(method, cmd_args, env={}, capture_stderr=False, return_bytes=False):
|
||||
# A safe way to execute processes.
|
||||
# Some processes like apt-get require being given a sane PATH.
|
||||
import subprocess
|
||||
env.update({ "PATH": "/sbin:/bin:/usr/sbin:/usr/bin" })
|
||||
stderr = None if not capture_stderr else subprocess.STDOUT
|
||||
ret = getattr(subprocess, method)(cmd_args, env=env, stderr=stderr)
|
||||
if isinstance(ret, bytes): ret = ret.decode("utf8")
|
||||
if not return_bytes and isinstance(ret, bytes): ret = ret.decode("utf8")
|
||||
return ret
|
||||
|
|
Loading…
Reference in New Issue