Hands-on: implementing DANE in Postfix
Cryptographic security for mail transport
Cryptographic security for mail transport
This hands-on guide describes the installation and configuration of the DANE internet security standard in the Postfix mail server. DANE is designed to frustrate mail traffic snooping by requiring the use of TLS encryption wherever possible during transport. The set-up described in this guide involves a CentOS 8.2 Linux server running a fully functional standard installation of the mail server, and a straightforward zone file for the DNSSEC-enabled domain example.nl. We describe how to extend that set-up with the following: • Configuration of (Start)TLS • Publication of TLSA records • Specification of cryptographic algorithms • Validation of DANE for mail For the basic set-up of the mail servers themselves, see our hands-on guide to the implementation of SPF, DKIM and DMARC in Postfix . Like that guide, this hands-on guide combines specimen configurations with explanations of how the DANE standard works.
DANE is designed to frustrate mail traffic snooping by requiring the use of TLS encryption wherever possible during transport. Although we strongly recommend the implementation of SPF, DKIM and DMARC — indeed, implementation is mandatory for government organisations in the Netherlands — DANE is entirely separate from those three standards. While SPF, DKIM and DMARC provide for the authentication and authorisation of an e-mail message's sender and sending host (at the SMTP-protocol level), DANE focuses on the security (confidentiality) of the transport (at the StartTLS-connection level). There is no interdependency between the SPF-DKIM-DMARC trio and DANE for mail. It doesn't therefore matter whether the trio is implemented first, or DANE for mail. However, the use of DNSSEC is mandatory with DANE, whereas it's merely recommended with SPF, DKIM and DMARC. On our DNSSEC page you'll find hands-on guides to the implementation of DNSSEC signing and validation in Unbound, Infoblox, PowerDNS and BIND. If you prefer to configure SPF, DKIM and DMARC first, see our hands-on guides to implementation in Postfix and Exim, respectively. This hands-on guide assumes a set-up as described in the latter two guides.
DANE, short for DNS-based Authentication of Named Entities, is a protocol for the secure publication of public keys and certificates. The standard utilises the cryptographically secured DNS infrastructure provided by DNSSEC. Although DANE therefore has various possible applications, the main growth in the standard's use is currently in mail transport (SMTP). DANE's use in connection with web certificates (HTTPS) has yet to catch on, partly because of the boom in the popularity of (free) Let's Encrypt certificates, and partly because DNSSEC is not always available everywhere. To enable DANE, the DNS protocol has been extended by the addition of a TLSA record. That can be used to link key information — in the form of a hash code (digital extract) — to an address-protocol-port combination. In principle, the authenticity of any encrypted internet service's server certificate can then be verified (validated) via the DNS. If the hash code of the server certificate doesn't match the hash code in the TLSA record, the client knows that the connection is not trustworthy, despite the encryption. DANE is standardised in RFC 6698, with clarifications in RFC 7671 and RFC 7673. DANE for mail is separately specified in RFC 7672.
In order to understand how the exchange of e-mail works, it's important to distinguish between, on the one hand, communication between end user and mail server, and, on the other, communication between mail servers. User-server communication primarily involves the user fetching mail from the server and reading it. The user's mail client (Mail User Agent, MUA) handles that by using the POP and IMAP protocols to communicate with the server (the Mail Delivery Agent, MDA). The conventional TCP ports for those two protocols are 110 and 143, respectively. For TLS-secured connections, the respective port numbers are 995 (POP3S) and 993 (IMAPS). The client can upgrade connections to non-secure ports (110/pop and 143/imap) to encrypted connections by using the STARTTLS command. However, the normal approach nowadays is to state explicitly in the client configuration that you want to use IMAPS on port 993. To send messages, the mail client uses the SMTP protocol. Nowadays, that normally involves the use of a private SMTP gateway for the server's own users on TCP port 587, with password-controlled access to exclude spammers. Port number 465 used to be reserved for TLS-secured gateways (SMTPS), but has since been assigned to another protocol. Cryptographic security of those SMTP connections is therefore always based on StartTLS (following authentication).
In order to deliver the user's messages, the SMTP gateway (now acting as a client) similarly uses the SMTP protocol. That's done on the mail server's TCP port 25, which is specified as the input port in the receiving domain's MX record. Again, no separate port is available for TLS-secured connections. And, like a user's mail client, a client mail server can upgrade its connection with an MX gateway by using the STARTTLS command. Despite the many similarities, there is a crucial difference between the SMTP connection used by an end user's mail client to send mail and the SMTP connection used by a mail server to transmit mail to another mail server (Message Transfer Agent or MTA). Whereas SMTP gateway operators can require their own users to use StartTLS when sending mail, MX gateways cannot require other servers to use the protocol. Because an MX gateway is a public message delivery portal, it currently has to be accessible to SMTP clients (mail servers) that don't support StartTLS. In that sense, the SMTP service is like the web, where visitors can generally choose whether to access a server via TCP port 80 (HTTP) or port 443 (HTTPS). However, for a web user who enters a URL starting 'https', there is no automatic fallback from the secure port 443 to the insecure port 80. Whereas an SMTP client that attempts to deliver a message to port 25 can be 'forced' to use an insecure port instead, simply by disabling StartTLS capability on the server. The problem is that a man-in-the-middle (MITM) can also disable secure transport by filtering out the StartTLS capability during the insecure SMTP handshake (StartTLS stripping). In fact, it seems that downgrade (STRIPTLS) attacks are often performed by internet access providers on users who opt to utilise their own SMTP gateways.
Whereas a web user explicitly states a preference for TLS ('https') and is notified if an attempted TLS connection fails, a mail client can't (yet) insist on the use of secure transport and no provision exists for providing feedback to the client (except in the form of a bounce message). Neither the mail address used nor the associated MX records indicate anything about the security of transport. Nevertheless, the presence of a TLSA record does imply that the MX gateway supports TLS, so a downgrade attack on the gateway's StartTLS capability is prevented. Not all mail clients support TLS, however. Its use by a client is therefore optional, meaning that DANE for mail is a so-called 'opportunistic protocol'. In other words, an SMTP client that supports DNSSEC, DANE and StartTLS is 'required' to encrypt its connections with a server for which DNSSEC-signed TLSA records have been published (indicating that it offers StartTLS). However, if any of those elements is missing, client and server fall back to TLS without DANE or even to insecure transport. The system works that way to ensure that message delivery can proceed without human intervention wherever possible.
However, since the publication of RFC 8314 in 2018, unencrypted transport by means of SMTP, POP and IMAP has been formally classed as 'obsolete'.
A TLSA record does not contain much more than a hash and information about the cryptographic protocols used. The only parameter that requires some explanation is the so-called 'usage'. The 'usage' parameter indicates how the hash should be interpreted:
0: PKIX-TA: Certificate Authority Constraint: anchors a particular CA certificate in the chain of trust (in addition to conventional PKI validation)
1: PKIX-EE: Service Certificate Constraint: anchors a particular server certificate (in addition to conventional PKI validation)
2: DANE-TA: Trust Anchor Assertion: anchors a particular CA certificate in the chain of trust, which then acts as a trust anchor
3: DANE-EE: Domain Issued Certificate: anchors a particular server certificate, which has to match the certificate offered by the server
Usages 0 and 1 anchor the certificate of, respectively, a CA and a server, to supplement conventional PKI anchoring on the basis of trust anchors provided in the client (or, on the web, the browser). The effect of usage 0 is to localise a hacked CA problem, while usage 1 completely neutralises it. Both usages also highlight any discrepancies between the two chains of trust. However, as explained below, that should be regarded as a bug rather than a feature: DANE was really developed to supersede and replace the existing PKI anchor system, and usages 0 and 1 were intended merely to accommodate that legacy. Usages 2 and 3 operate entirely independently from conventional PKI anchoring, making them suitable for self-signed certificates. They also make it possible to serve clients without installed trust anchors, such as SMTP clients (mail servers).
The DANE standard stipulates that, with usages 0 and 1, both chains of trust must be validated. That can be problematic if one chain can be validated but the other cannot. In a web browser, the problem can be resolved the same way as the problem of a conventional PKI certificate that can't be validated for whatever reason: a pop-up that warns the user and asks whether they want to proceed. However, SMTP clients have never had PKI trust anchors installed, which is why the standard says usages 0 and 1 are inappropriate with DANE for mail. After all, the client's (browser's) built-in PKI certificates, which we still use for the web, are now regarded as an outdated and demonstrably insecure legacy. Although it would be better to replace them with self-signed certificates plus TLSA records for local assurance, that solution depends on the use of DNSSEC, whose adoption in many parts of the world lags far behind that in the Netherlands [1, 2].
Before your mail server can offer StartTLS as an option (SMTP capability), the server needs to be provided with a cryptographic key pair. The key pair can then be used for the certificate (self-signed public key) that is offered to clients for encryption of the connection (following a StartTLS request).
With Postfix, a TLS key pair is generated when the software package is installed. The public and private keys are recorded in the files '/etc/pki/tls/certs/postfix.pem' and '/etc/pki/tls/private/postfix.key', respectively. In the Postfix configuration file '/etc/postfix/main.cf', the locations are specified using the following two options:
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
However, we prefer to use our own key pair. Another consideration is that we want to support not only the RSA-based encryption algorithms, but also the efficient ECDSA-based algorithms. The advantages of the latter modern cryptographic algorithm are explained here in relation to DNSSEC. We therefore need to delete the existing keys, and then generate two new key pairs, as follows:
trash /etc/pki/tls/certs/postfix.pem /etc/pki/tls/private/postfix.key
[root@mail ~]# cd /etc/pki/tls/private/ [root@mail private]# openssl req -newkey rsa:4096 -sha512 -x509 -nodes -days 3650 \ -keyout postfix-rsa.key -out postfix-rsa.cert Generating a RSA private key ......................................................++++ ...........................++++ writing new private key to 'postfix-rsa.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:NL State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Gepermuiden Organization Name (eg, company) [Default Company Ltd]:Acme Corporation Organizational Unit Name (eg, section) []:Postfix TLS key Common Name (eg, your name or your server's hostname) []:mail.example.nl Email Address []:postmaster@example.nl [root@mail private]# chmod 640 postfix-rsa.key postfix-rsa.cert [root@mail private]# chown root:postfix postfix-rsa.key postfix-rsa.cert [root@mail private]# mv postfix-rsa.cert ../certs/ [root@mail ~]# cd /etc/pki/tls/private/ [root@mail private]# openssl ecparam -out postfix-ecdsa.key -name prime256v1 -genkey [root@mail private]# openssl req -new -sha512 -key postfix-ecdsa.key -out postfix-ecdsa.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:NL State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Gepermuiden Organization Name (eg, company) [Default Company Ltd]:Acme Corporation Organizational Unit Name (eg, section) []:Postfix TLS key Common Name (eg, your name or your server's hostname) []:mail.example.nl Email Address []:postmaster@example.nl Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: [root@mail private]# openssl req -x509 -sha512 -days 3650 -key postfix-ecdsa.key \ -in postfix-ecdsa.csr -out postfix-ecdsa.cert [root@mail private]# chmod 640 postfix-ecdsa.key postfix-ecdsa.cert [root@mail private]# chown root:postfix postfix-ecdsa.key postfix-ecdsa.cert [root@mail private]# mv postfix-ecdsa.cert ../certs/
Once that's done, we can add the new key files to the Postfix configuration (in the file '/etc/postfix/main.cf'):
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix-rsa.cert smtpd_tls_eccert_file = /etc/pki/tls/certs/postfix-ecdsa.cert smtpd_tls_key_file = /etc/pki/tls/private/postfix-rsa.key smtpd_tls_eckey_file = /etc/pki/tls/private/postfix-ecdsa.key
Next, we need to verify that TLS is properly configured. The '/etc/postfix/main.cf' file includes the global option 'smtpd_tls_security_level = may', whose effect is to make TLS optional (opportunistic) for inbound connections on the basis of StartTLS. In the '/etc/postfix/master.cf' file, you'll see the following option settings for the submission service. Their effect is to make StartTLS-based TLS mandatory for local users who, after logging in, want to send messages via TCP port 587.
-o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_tls_auth_only=yes
After restarting, the Postfix server, with the new key pairs installed, will be on standby for incoming connections. The new configuration can be tested using the 'ssltest' command. In the following example, you can see that our mail server does indeed now offer two self-signed certificates: one based on RSA, the other on ECDSA.
systemctl restart postfix.service systemctl status postfix.service
testssl -t smtp localhost:25
The SMTP gateway on port 587 can be checked in a similar way:
testssl -t smtp localhost:587
By sending another telnet command to port 587, we can verify that login is not permitted until the connection has been upgraded using StartTLS:
[root@system ~]# telnet localhost 587 Trying ::1... Connected to localhost. Escape character is '^]'. 220 mail.example.nl ESMTP Postfix ehlo verzender.example.nl 250-mail.example.nl 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8 auth 530 5.7.0 Must issue a STARTTLS command first quit 221 2.0.0 Bye Connection closed by foreign host.
The following command can be used to test interaction with the mail server via a TLS connection:
openssl s_client -connect localhost:587 -tls1_3
We will return to the configuration of TLS shortly, when we give detailed consideration to the cryptographic algorithms we do and don't want to use to encrypt our traffic.
There are various ways of generating a TLSA record for your MX gateway. One is to use an OpenSSL command, with your server certificate as the basis. Where an RSA-based certificate is concerned, that approach results in the following:
[root@mail postfix]$ openssl x509 -in /etc/pki/tls/certs/postfix-rsa.cert -outform DER | openssl sha256 (stdin)= f61bf58d20d9a3898a02a2ff031e6103d267c9e86e05fccba73b5de109b1032f
The output is the hash (based on the SHA-256 algorithm) of the (self-signed) certificate that your mail server offers to clients for connection encryption (following a StartTLS request). The alternative to SHA-256 is the much stronger SHA-512 algorithm. SHA-512 was developed for use on 64-bit systems, but has also become the norm on mobile devices. The hash value given above can be incorporated directly into your TLSA records:
# DANE for mail _25._tcp.mx.example.nl IN TLSA 3 0 1 f61bf58d20d9a3898a02a2ff031e6103d267c9e86e05fccba73b5de109b1032f _587._tcp.smtp.example.nl IN TLSA 3 0 1 f61bf58d20d9a3898a02a2ff031e6103d267c9e86e05fccba73b5de109b1032f _465._tcp.smtp.example.nl IN TLSA 3 0 1 f61bf58d20d9a3898a02a2ff031e6103d267c9e86e05fccba73b5de109b1032f
The first field above (whose value is 3 in our example) specifies the usage, as described earlier. The second field (whose value is 0) specifies the selector: when the value is 0, the hash is taken from the entire certificate (as a blob); when it's 1 the DER format is used. And the final field (the matching type, which has the value 1 in our example) indicates which hash algorithm is used: 0 for an exact match, 1 for the SHA-256 hash, and 2 for the SHA-512 hash. As you'll see, in the interest of completeness, the TLSA records for TCP ports 587 and 465 are included. However, to the best of our knowledge, no mail clients currently perform DANE validation on the SMTP gateway (or on the POP/IMAP/POPS/IMAPS ports). We do exactly the same for the ECDSA-based certificate, resulting in a second set of TLSA records.
Various tools are also available for generating TLSA records. One is hash-slinger, developed by Paul Wouters. The package is no longer included in the Fedora/CentOS/RHEL distributions. Nevertheless, once manually installed, the software (and the 'python3-m2crypto' package) can be used to generate TLSA records on the basis of the offered certificate as follows:
[root@mail hash-slinger-master]# ./tlsa --create --port 25 --starttls smtp --output rfc mail.example.nl Got a certificate with Subject: /C=NL/ST=/L=Gepermuiden/O=Acme Corporation/OU=Postfix TLS key/ CN=mail.example.nl/emailAddress=postmaster@example.nl _25._tcp.mail.example.nl. IN TLSA 3 0 1 f61bf58d20d9a3898a02a2ff031e6103d267c9e86e05fccba73b5de109b1032f
Note that the hash value has to be generated using the certificate offered online by the mail server via TCP port 25. That normally involves running the hash-slinger on the same system that the server is running on, or on another trusted network. Otherwise, you run the (very small) risk of a man-in-the-middle (MITM) replacing the server's real certificate with a fake certificate. A better option (which does require you to be on the same system) is to specify the certificate yourself using the following option statement:
--certificate /etc/pki/tls/certs/postfix-rsa.cert
Anyone who prefers to use an online tool to generate a TLSA record is likely to find Shumon Huque's tool handy.
On this page, you can also check that your TLSA record does indeed match the certificate being offered.
TLSRPT (defined in RFC 8460) is a mechanism that enables a mail domain operator to receive error messages from clients (sending mail servers) in the event of TLS encryption failures when connecting to the operator's MX gateway. The TLSRPT mechanism works in a similar way to the DMARC mechanism.
Although TLSRPT was defined together with MTA-STS and by the same actors, it works just as well with DANE for mail.
In order to receive TLSRPT reports, a mail domain operator publishes a special TXT record (in parallel with the MX records), as follows:
_smtp._tls.example.nl IN TXT "v=TLSRPTv1; rua=mailto:tls-rua@example.nl"
As you can see, the record consists of little more than an e-mail address to which standardised error messages can be sent for automated processing.
Automated TLSRPT report processing services are provided by the same organisations that offer DMARC report processing.
Having a fully functional and properly anchored TLS configuration doesn't necessarily mean that your connections are adequately secured. The reason being that, to a significant extent, security depends on the version of the TLS protocol used and on the associated cryptographic algorithms. If outdated protocols and/or algorithms are used, security will be inadequate by modern standards. However, if only the latest and most secure options are supported, some older SMTP clients may not be able to interact securely with the server and will be obliged to fall back on an insecure connection. The NCSC has drawn up guidelines for both TLS connections in general and for the encryption of mail transport in particular. Their recommendations relate not only to the TLS protocol itself, but also to the various cryptographic primitives (which together form the cipher suite). In the latest update to the 'ICT Security Guidelines for Transport Layer Security (TLS)' (dated 19 January 2021), the NCSC downgraded TLS version 1.2 from 'Good' to 'Satisfactory'. This article has been revised in line with the update.
The various cryptographic algorithms that can be used for TLS (amongst other things) are listed below, grouped by function.
Algorithms for the exchange of private keys: ECDHE, DHE, RSA
Public key algorithms (asymmetric cryptography algorithms) for X.509 certificates (chains of signed public keys): RSA, ECDSA
(Symmetric) cryptography for the bulk encryption of traffic (for which public key cryptography is too slow/inefficient): 3DES, AES
Hash function algorithms for use in connection with the creation of digital signatures: SHA-1, SHA-256, SHA-512
In chapter 4 of the ICT Security Guidelines for Transport Layer Security (TLS), the NCSC advises using only TLS version 1.2 or 1.3, preferably the latter. The recommended cryptographic algorithms are listed in the following table; the support situation differs from one version of TLS to another.
For the certificates, EdDSA can also be used, but that algorithm isn't yet supported by the certificate authorities. Be aware that the SHA-1 hash function algorithm is suitable for use only in the context of bulk encryption (MAC); it should definitely not be used for hashes in digital signatures. Where the encryption algorithms are concerned, it's also worth noting that RSA keys should be at least 2048 bits, and preferably 3072 or 4096 bits. Also, the Elliptic-Curve Cryptography (ECC)-based algorithms (ECDHE, ECDSA and EdDSA) should use only the secp384r1, secp256r1, x448 and x25519 curves as their underlying mathematical functions. Similarly, if you want to continue supporting the (less efficient) DHE algorithm, use only the variants based on the finite field groups ffdhe4096 and ffdhe3072 (as discussed in RFC 7919). Later in this guide we'll explain how to set the parameters for such algorithms.
Having decided which of the (dozens of) available algorithms we want to use, a corresponding specification string has to be inserted into our mail server's configuration. The mail server then communicates the specification (in some cases literally) to the underlying cryptographic library (typically OpenSSL). The settings that we use for Postfix (in the file '/etc/postfix/main.cf') are set out below. Although the format of the crypto-specification strings is similar to that used for OpenSSL, the format is defined by Postfix itself. Postfix translates the strings to OpenSSL-specific settings when consulting the library. For details, therefore, see the OpenSSL documentation. Later in this article, we explain how you can use the command line to ask OpenSSL what valid cipher suites remain available when a given specification is used.
# TLS hardening tls_ssl_options = NO_COMPRESSION, 0x40000000 # NOTE: NO_RENEGOTIATION option supported from Postfix version 3.4; # use OpenSSL option value '0x40000000' for older versions tls_preempt_cipherlist = yes # enforce server's cipher preference order over client's order for incoming connections
# SMTP from other servers to yours smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 # disable SSLv2, SSLv3, TLSv1, TLSv1.1, leaving only TLSv1.2 and TLSv1.3 enabled smtpd_tls_ciphers = high smtpd_tls_mandatory_ciphers = high smtpd_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, DH, kRSA, DHE, DSS, RC4, DES, IDEA, SEED, ARIA, CAMELLIA, AESCCM8, 3DES, ECDHE-ECDSA-AES256-SHA384, ECDHE-ECDSA-AES128-SHA256, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES128-SHA256, MD5, SHA # NCSC: good #smtpd_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5 # NCSC: sufficient # use 'smtpd_tls_mandatory_exclude_ciphers' to set additional exclusions for mandatory TLS connections smtpd_tls_eecdh_grade = ultra # set up EECDH parameters for 192-bits security level (ignored from Postfix version 3.6) smtpd_tls_dh1024_param_file = /etc/postfix/dh4096.pem # strong DHE parameters smtpd_tls_loglevel = 1 smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache
# SMTP from your server to others smtp_tls_note_starttls_offer = yes smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 # disable SSLv2, SSLv3, TLSv1, TLSv1.1, leaving only TLSv1.2 and TLSv1.3 enabled smtp_tls_ciphers = high smtp_tls_mandatory_ciphers = high smtp_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, DH, kRSA, DHE, DSS, RC4, DES, IDEA, SEED, ARIA, CAMELLIA, AESCCM8, 3DES, ECDHE-ECDSA-AES256-SHA384, ECDHE-ECDSA-AES128-SHA256, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES128-SHA256, MD5, SHA # NCSC: good #smtp_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5 # NCSC: sufficient # use 'smtp_tls_mandatory_exclude_ciphers' to set additional exclusions for mandatory TLS connections smtp_tls_loglevel = 1 smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache
# LMTP from your server to others lmtp_tls_note_starttls_offer = yes lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 # disable SSLv2, SSLv3, TLSv1, TLSv1.1, leaving only TLSv1.2 and TLSv1.3 enabled lmtp_tls_ciphers = high lmtp_tls_mandatory_ciphers = high lmtp_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, DH, kRSA, DHE, DSS, RC4, DES, IDEA, SEED, ARIA, CAMELLIA, AESCCM8, 3DES, ECDHE-ECDSA-AES256-SHA384, ECDHE-ECDSA-AES128-SHA256, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES128-SHA256, MD5, SHA # NCSC: good #lmtp_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5 # NCSC: sufficient # use 'lmtp_tls_mandatory_exclude_ciphers' to set additional exclusions for mandatory TLS connections lmtp_tls_loglevel = 1 lmtp_tls_session_cache_database = btree:/var/lib/postfix/lmtp_tls_session_cache
As you can see, we always use the same settings for inbound and outbound connections (the options beginning with 'smtpd_tls_' and 'smtp_tls_'/'lmtp_tls_', respectively). The settings for the options beginning 'smtpd_tls_mandatory_' and 'smtp_tls_mandatory_'/'lmtp_tls_mandatory_' are the same as well. There, the first set of settings applies to all opportunistic TLS connections and the second to all mandatory TLS connections (e.g. for TCP port 587, enforced using the '-o smtpd_tls_security_level=encrypt' option). In relation to the latter, note that Postfix handles the various 'mandatory' options differently: whereas 'smtpd_tls_mandatory_protocols' and 'smtpd_tls_mandatory_ciphers' specify the settings for mandatory TLS connections, the 'smtpd_tls_mandatory_exclude_ciphers' option applies in addition to the 'smtpd_tls_exclude_ciphers' option.
Let's now consider the configuration itself. First of all, we use only TLS versions 1.2 and 1.3, and we explicitly exclude the outdated SSL protocols and TLS versions 1 and 1.1. However, it should be noted that the remaining protocols should always result in a series of consecutive versions. The setting '*_tls_ciphers = high' is used to make a preliminary selection from the available cryptographic algorithms. We permit only the strongest algorithms (with a security level of at least 128 bits, as defined in the option 'tls_high_cipherlist'). Then, with the '*_exclude_ciphers' options, we specify the algorithms we definitely don't want to use. That involves first repeating everything under the gradation 'HIGH'. Other algorithms that we explicitly exclude are:
SRP, PSK, (k)DH, (k)RSA and DHE for key exchange (aRSA can, however, be used for certificates; DHE may be used, but only if based on the ffdhe4096 or ffdhe3072 functions)
RC4, DES, IDEA, SEED, ARIA, CAMELLIA, AES/CCM8, 3DES and AES/CBC for bulk encryption (AES/GCM is permitted)
As you'll see, our settings are quite strict: we support only the algorithms that the NCSC has rated 'Good', not those that are rated 'Adequate'. Note also that the list of exceptions presented above includes algorithms (e.g. RC4, DES and MD5) that have already been excluded. The reason for nevertheless explicitly specifying them at this point is to prevent their accidental activation in the event of combinations of crypto-primitives being added at a later date. For the same reason, our configuration includes an aNULL and an eNULL (NULL operators for authentication and encryption, respectively).
Now, if we re-run the 'testssl' command, we see that our mail server offers eight cipher suites, all based on the 'ECDHE-ECDSA-' and 'ECDHE-RSA-' algorithms. The most recent versions of testssl list four additional cipher suites, but they are merely abbreviated notations for the combinations entered with TLS version 1.3.
By revising our crypto-configuration string slightly, we can also ask OpenSSL what valid cipher suites remain:
[user@system ~]$ openssl ciphers -s -tls1_2 \ 'HIGH, !EXP, !LOW, !MEDIUM, !aNULL, !eNULL, \ !SRP, !PSK, !kDH, !DH, !kRSA, !DHE, !DSS, !RC4, !DES, !IDEA, !SEED, !ARIA, !CAMELLIA, !AESCCM8, !3DES, \ !ECDHE-ECDSA-AES256-SHA384, !ECDHE-ECDSA-AES128-SHA256, !ECDHE-RSA-AES256-SHA384, !ECDHE-RSA-AES128-SHA256, \ !MD5, !SHA' ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-CCM ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-CCM
If you want to additionally allow the combinations that the NCSC classes as 'Adequate', the crypto-specification string needs to be as follows:
smtpd_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5
Checking with OpenSSL then yields the following list:
[user@system ~]# openssl ciphers -s -tls1_2 \ 'HIGH, !EXP, !LOW, !MEDIUM, !aNULL, !eNULL, \ !SRP, !PSK, !kDH, !ADH, !AECDH, !kRSA, !DSS, !RC4, !DES, !IDEA, !SEED, !ARIA, !AESCCM8, !3DES, !MD5' ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-CCM DHE-RSA-AES256-CCM ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-CCM DHE-RSA-AES128-CCM ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES256-SHA256 ECDHE-ECDSA-CAMELLIA256-SHA384 ECDHE-RSA-CAMELLIA256-SHA384 DHE-RSA-CAMELLIA256-SHA256 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 DHE-RSA-AES128-SHA256 ECDHE-ECDSA-CAMELLIA128-SHA256 ECDHE-RSA-CAMELLIA128-SHA256 DHE-RSA-CAMELLIA128-SHA256 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-AES256-SHA DHE-RSA-CAMELLIA256-SHA ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES128-SHA DHE-RSA-AES128-SHA DHE-RSA-CAMELLIA128-SHA
In addition to the 'Good' cipher suites, the list now includes suites based on DHE, AES/CCM(16), CAMELLIA and SHA(-1) (for HMAC).
As you will see below, OpenSSL for TLS 1.3 supports only four cipher suites:
user@system ~]$ openssl ciphers -s -tls1_3 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 TLS_AES_128_CCM_SHA256
If we combine our earlier selection for cipher suites classed as 'Good' with TLS version 1.3 – recommended as the most secure option in the latest NCSC guidance – you will see that all four suites are selected:
[user@system ~]$ openssl ciphers -s -tls1_3 \ 'HIGH, !EXP, !LOW, !MEDIUM, !aNULL, !eNULL, \ !SRP, !PSK, !kDH, !DH, !kRSA, !DHE, !DSS, !RC4, !DES, !IDEA, !SEED, !ARIA, !CAMELLIA, !AESCCM8, !3DES, \ !ECDHE-ECDSA-AES256-SHA384, !ECDHE-ECDSA-AES128-SHA256, !ECDHE-RSA-AES256-SHA384, !ECDHE-RSA-AES128-SHA256, \ !MD5, !SHA' TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 TLS_AES_128_CCM_SHA256
The reason why we (NCSC) restrict approval to ECDHE and DHE for key exchange is that those two algorithms provide 'forward secrecy'. A completely new (symmetrical) session key is exchanged for each message — hence the 'E' for 'ephemeral' in the algorithms' names — with the result that other encrypted information remains secure in the event of a session key being leaked. The option 'smtpd_tls_eecdh_grade = ultra' is used to set the parameters for the EECDH algorithm so that its security level is 192 bits (128 bits being the current minimum security requirement). The option 'smtpd_tls_dh1024_param_file = /etc/postfix/ssl/ffdhe4096.pem' refers to a file containing the parameters for strong encryption on the basis of the (less efficient) DHE algorithm. The file is generated as follows:
openssl dhparam -out /etc/postfix/dh4096.pem 4096
The option 'smtp_tls_note_starttls_offer'/'lmtp_tls_note_starttls_offer' has the effect that a message is sent to the log whenever a remote server offers StartTLS (on an as yet unencrypted connection). The global TLS/SSL options 'tls_ssl_options = NO_COMPRESSION, NO_RENEGOTIATION' have the effect that, first, labour-intensive (and sometimes insecure) compression of data traffic is disabled, and, second, once a particular cryptographic protocol has been negotiated, the choice cannot be changed midway through the message exchange. Bear in mind that Postfix supports the 'NO_RENEGOTIATION' option only from version 3.4. With older versions, the OpenSSL option value '0x40000000' should be used. Finally, the option 'tls_preempt_cipherlist = yes' has the effect that (from SSL version 3) the SMTP server enforces its own cryptographic algorithm sequence instead of accepting the sequence of algorithms preferred by the remote client.
Use the 'postconf (-d)' command to retrieve Postfix's full (default) configuration.
Of course, when you change your key pair and therefore your certificate, the hash in the TLSA record needs to be changed as well. Consequently, when you make a change, you have to perform a minor rollover, as described in Appendix A.4 to RFC 6698. The new TLSA record has to be published alongside the old one before the certificate is replaced. The new certificate cannot be activated on the server until the TTL has expired and the old TLSA information has been flushed from all DNS caches. If the new certificate is activated too soon, you run the risk that validating clients will not accept it due to a mismatch with the old information. As soon as you've activated the new server certificate, the old TLSA record can be deleted.
Our emphasis on cryptographic algorithms and settings is in line with what the NCSC, the Forum for Standardisation and the Platform for Internet Standards recommend: implementation of DANE as soon as possible and in the most secure manner possible, on the basis of the latest technical insights. The drawback of this approach is that, if an older client does not support the latest standards, it will fall back on a completely unencrypted connection because continued mail delivery must be enabled. An alternative school of thought therefore favours the principle that "something is better than nothing". An encrypted connection always offers some degree of protection, even if server authentication isn't performed or if an outdated cryptographic cipher suite is used. That pragmatic interpretation of opportunistic security is described in RFC 7435. According to Viktor Dukhovni, author of RFC 7435 and a strong advocate of STARTTLS and DANE, the client and server will normally select the best possible security protocol for their connection, meaning that there is no need to tweak the cryptographic settings. Outdated and insecure algorithms disappear from the internet organically, as software and hardware are upgraded. Dukhovni takes the view that it's much more important to focus on the operational aspects: using up-to-date software and setting up an effective monitoring system and a smooth rollover process. While we agree on the importance of such operational aspects, they are outside the scope of this article. We also maintain the view that structural support for weak cypher suites is inadvisable. Poorly secured connections provide a misleading semblance of security against active attacks.
Just as other sending mail servers can check our DANE record and thus validate our certificate (self-signed public TLS key), our server (when acting as a client) can validate other servers' TLS certificates when initiating mail transport.
Configuration of Postfix for opportunistic TLS (StartTLS) involves little more than setting a switch in the file '/etc/postfix/main.cf', where it is enabled by default:
# Use TLS if this is supported by the remote SMTP server, otherwise use # plaintext (opportunistic TLS outbound). # smtp_tls_security_level = may
DANE validation is supported from version 2.11. You can add this feature to your system by increasing the security level in the configuration above to 'dane':
# validate DANE smtp_dns_support_level = dnssec smtp_tls_security_level = dane
Your connections will then be protected against MITM downgrade attacks as described above. An even higher level of security can be achieved by using the 'dane-only' option, which makes DANE-validated authentication mandatory. Mail delivery is then 'deferred' (at least temporarily) if the would-be recipient's MX gateway can't be positively validated with DANE. However, use of the 'dane-only' option is impractical for general mail delivery on the internet. As explained above, DNSSEC is required for the implementation of DANE. The reason being that, if your DNS records are not signed, there is no cryptographic chain of trust to anchor your TLSA records. Because DNSSEC validation is not enabled by default, the configuration presented above includes the option 'smtp_dns_support_level = dnssec'. Make sure that the system running your sending mail server is actually performing DNSSEC validation independently. If your server relies on a validating resolver on a different/external system for validation (utilising AD flag), then the final link in the chain of trust is not cryptographically secured. That unprotected 'last mile', as it is known, makes you vulnerable to downgrade attacks and TLSA certificate falsification by a man in the middle.
Delivery of a message over a DANE-validated StartTLS connection will be recorded in the logs as follows:
mail postfix/smtp[2512590]: Trusted TLS connection established to mail.externdomein.nl[203.0.113.109]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Our DANE set-up is now complete! You can test your mail configuration on internet.nl.
In combination with the EPEL repository, CentOS version 8.2 provides everything needed to support a fully featured, scalable and secure Postfix-based mail infrastructure. As described in an earlier hands-on guide, the implementation of SPF, DKIM and DMARC does nevertheless involve a significant amount of extension and integration work. The implementation of DANE described in this guide is much less involved. In this hands-on guide, we have explained how to realise the comprehensive implementation of the DANE mail security standard. Combining the set-up described with support for IPv6 and SPF/DKIM/DMARC should ensure a 100 per cent score on internet.nl, implying that your mail systems are completely up-to-date and consistent with the latest requirements and guidance of the Forum for Standardisation, the NCSC and others. What's more, domain-level mail security is an important enabler for transitioning from IPv4 to IPv6, because IP address-based filtering isn't possible with IPv6. If and when new DANE functionality for Postfix becomes available, we will update this guide accordingly. In the meantime, we're pleased to hear any feedback you may have on this guide.