Skip to content

WIP: Feat: Use best practice ciphers in 2020/21#1475

Closed
polarathene wants to merge 7 commits intodocker-mailserver:masterfrom
polarathene:feat/use-best-practice-ciphers-2020
Closed

WIP: Feat: Use best practice ciphers in 2020/21#1475
polarathene wants to merge 7 commits intodocker-mailserver:masterfrom
polarathene:feat/use-best-practice-ciphers-2020

Conversation

@polarathene
Copy link
Copy Markdown
Member

This PR updates the cipherlists based on the guidance from Mozilla and OWASP best practices.

I've referenced this Feb 2018 discussion and PR for guidance on what needed to be updated.

Modern TLS_LEVEL

OWASP cipherlists(github repo) last updated April 2019 according to git blame, commit. OWASP B (Broad Compatibility) has been chosen.

  • Includes solely the strongest Perfect Forward Secrecy (PFS) ciphers.
  • Protocols: TLSv1.2 (and newer or better).
OWASP B - Cipherlist TLS 1.2
DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256

Multi-line for better scanning over:

DHE-RSA-AES256-GCM-SHA384:
DHE-RSA-AES128-GCM-SHA256:
ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-RSA-AES128-GCM-SHA256:
DHE-RSA-AES256-SHA256:
DHE-RSA-AES128-SHA256:
ECDHE-RSA-AES256-SHA384:
ECDHE-RSA-AES128-SHA256

Mozilla cipherlists last updated Jan 2020 (guidelines 5.4). Intermediate configuration has been chosen:

  • All cipher suites are forward secret and authenticated
  • Protocols: TLS 1.2, TLS 1.3
  • Certificate type: ECDSA (P-256) (recommended), or RSA (2048 bits)
  • While the goal is to support a broad range of clients, we reasonably disable a number of ciphers that have little support (such as ARIA, Camellia, 3DES, and SEED)
Mozilla Intermediate - Cipherlist TLS 1.2
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

Multi-line for better scanning over:

ECDHE-ECDSA-AES128-GCM-SHA256:
ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-GCM-SHA384:
ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-CHACHA20-POLY1305:
ECDHE-RSA-CHACHA20-POLY1305:
DHE-RSA-AES128-GCM-SHA256:
DHE-RSA-AES256-GCM-SHA384

See the links for more details about the advised cipherlists and compatibility / rationale.


Breakdown of changes to the `modern` cipherlist Moved to the front of the list:
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256

AES128-GCM-SHA256 may be weaker but is still considered quite secure, thus has been positioned to the front of the list for performance reasons according to mozilla. If clients were permitted to select the cipher preference, they could ask for something stronger(or chacha if no AES-NI support?).

Neither OWASP or Mozilla include the following two ciphers, so they've been removed. I think they may have been in a previous cipherlist from Mozilla when this list was last updated?

ECDHE-ECDSA-AES256-SHA384
ECDHE-ECDSA-AES128-SHA256

Mozilla ends its list with these two:

DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384

OWASP B adds non-GCM DHE variants, and retains the last two ciphers in the current list. These are the only difference between OWASP A and B grades, so could be dropped if choosing to opt for grade A instead:

DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA384
ECDHE-RSA-AES128-SHA256

OWASP B also lists 3 TLS 1.3 ciphers, but these rarely need to be specified for most software, as such they're not included:

TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256

If any reviewer is not confident about understanding the cipher suite names, this is a good article on the topic, Wikipedia also has a table on ciphers, which are apparently all covered through TLS 1.0-1.2?

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Apr 28, 2020

Reduced excludes in smtpd_tls_exclude_ciphers

# From:
smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
# To (with no apparent change in cipher support):
smtpd_tls_exclude_ciphers = aNULL, SEED, CAMELLIA, RSA+AES

Mozilla doesn't include smtpd_tls_exclude_ciphers with their postfix config generator. While it's possible to find relatively recent blogs / guides making use of cipher excludes, they often don't explain any useful reasoning for the choices.

I think it has just become a bit of parroting of information and a "better safe than sorry if I don't understand this" approach. Looking at the postfix docs we have:

List of ciphers or cipher types to exclude from the SMTP server cipher list at all TLS security levels.

Excluding valid ciphers can create interoperability problems. DO NOT exclude ciphers unless it is essential to do so.

Cipher types listed in smtpd_tls_mandatory_exclude_ciphers or smtpd_tls_exclude_ciphers are excluded from the base definition of the selected cipher grade.

The underlying cipherlists for grades other than null include anonymous ciphers, but these are automatically filtered out if the server is configured to ask for remote SMTP client certificates. You are very unlikely to need to take any steps to exclude anonymous ciphers, they are excluded automatically as required.

Additionally aNULL also excludes ADH.

I have verified parity of the current excluded ciphers with this reduced set. It should be clear which ciphers listed are now responsible for, except for MEDIUM which handled two SEED ciphers. Since MEDIUM is ambiguous to what ciphers it covers (the other exclusions are still required for achieving parity), I have swapped MEDIUM to SEED.

For anyone curious, MEDIUM as an exclude, does not appear to exclude medium cipherlist, which I was initially concerned about that emptying out port 25 inbound cipherlist for STARTTLS, which would have meant never using TLS , thankfully that's not the case 😅

In my testing these excluded ciphers are still graded as A, only the anon ciphers that aNULL excludes provide a lower F grade, but the postfix docs have stated it's a non-issue when dealing with remote connections. (TODO: only verified on the docker host, need to check remotely to confirm)

If we followed the mozilla generator config, and used tls_medium_cipherlist instead of tls_high_cipherlist, having excludes would not be necessary(they don't seem to be for our modern TLS_LEVEL, but still relevant with the current intermediate TLS_LEVEL unless we share the mandatory high cipherlist as medium instead). (EDIT: Sharing the same cipher list seems valid, unless there was a desire to relax port 25 STARTLS or be stricter with 587/465 cipher suites)

Testing the reduced cipher excludes for parity

nmap used to scan on port 25(mapped to docker-mailserver container), command ran on the docker host(0.0.0.0 being all interfaces on IPv4):

nmap --script ssl-enum-ciphers -p 25 0.0.0.0

I went with what I saw first and worked for me based on this answer, which now viewing comments may suggest some further testing should be done with other tooling. My nmap package (Manjaro) included the mentioned script, I did notice no TLSv1.3 results, happy to test more with another tool if desired.

Results for current DockerHub image:
PORT   STATE SERVICE
25/tcp open  smtp
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

Using the user-patches.sh support, I've tested some modifications. For anyone reproducing, note that at least with docker-compose, CTRL+C to stop the container after docker-compose up is insufficient, the main.cf file will still remain with the modifications (which prevents some other snippets shown here from working as they can no longer find the target line that got replaced), you need to make use of docker-compose down before the next up run.

Results (diff) with `smtpd_tls_exclude_ciphers` removed:
# user-patches.sh
sed -i "s/^smtpd_tls_exclude_ciphers.*/# nope/" /etc/postfix/main.cf
5a6,11
> |       TLS_DH_anon_WITH_AES_256_GCM_SHA384 - F
> |       TLS_DH_anon_WITH_AES_256_CBC_SHA256 - F
> |       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 - F
> |       TLS_ECDH_anon_WITH_AES_256_CBC_SHA - F
> |       TLS_DH_anon_WITH_AES_256_CBC_SHA - F
> |       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA - F
15a22,23
> |       TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (ecdh_x25519) - A
> |       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 2048) - A
17a26,29
> |       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
> |       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
18a31,40
> |       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
> |       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
> |       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
> |       TLS_DH_anon_WITH_AES_128_GCM_SHA256 - F
> |       TLS_DH_anon_WITH_AES_128_CBC_SHA256 - F
> |       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 - F
> |       TLS_ECDH_anon_WITH_AES_128_CBC_SHA - F
> |       TLS_DH_anon_WITH_AES_128_CBC_SHA - F
> |       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA - F
26a49,50
> |       TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (ecdh_x25519) - A
> |       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (dh 2048) - A
28a53,56
> |       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
> |       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
29a58,64
> |       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
> |       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
> |       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
> |       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
> |       TLS_DH_anon_WITH_SEED_CBC_SHA - F
> |       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
> |       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
33c68
< |_  least strength: A
---
> |_  least strength: F

Note in the diff that the only ciphers that were rated below A were the anonymous ciphers which aNULL excludes. We've already learned from postfix docs that they shouldn't be a concern. Thus it may be fine to just not exclude any ciphers when the server chooses?(EDIT: smtpd_tls_exclude_ciphers applies to both explicit and implicit TLS cipher lists, but is mostly only useful at filtering out cipher suites you have not explicitly defined as allowed, such as MEDIUM that is a group of cipher suites where you may not trust all in that group, the nmap grades are to be taken with a grain of salt)

Mozilla excludes some with the following reasoning:

While the goal is to support a broad range of clients, we reasonably disable a number of ciphers that have little support (such as ARIA, Camellia, 3DES, and SEED)

Results for current DockerHub image when testing the high cipherlist:
# user-patches.sh
sed -i "s/^smtpd_tls_exclude_ciphers.*/# nope/" /etc/postfix/main.cf
sed -i "s/^tls_high_cipherlist/tls_medium_cipherlist/" /etc/postfix/main.cf
PORT   STATE SERVICE
25/tcp open  smtp
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

Current tls_high_cipherlist (split to individual lines for readability):

ECDHE-ECDSA-AES256-GCM-SHA384:
ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-CHACHA20-POLY1305:
ECDHE-RSA-CHACHA20-POLY1305:
ECDHE-ECDSA-AES128-GCM-SHA256:
ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-SHA384:
ECDHE-RSA-AES256-SHA384:
ECDHE-ECDSA-AES128-SHA256:
ECDHE-RSA-AES128-SHA256

Note that ECDSA ciphers are not listed, despite being in the cipherlist override. I don't know this stuff that well, postfix docs seem to suggest such support is dependent on user supplied certs, but that RSA is typically what will be encountered:

RSA, DSA and ECDSA (Postfix ≥ 2.6) certificates are supported. Typically you will only have RSA certificates issued by a commercial CA. In addition, the tools supplied with OpenSSL will by default issue RSA certificates. You can configure all three at the same time, in which case the cipher used determines which certificate is presented. For Netscape and OpenSSL clients without special cipher choices, the RSA certificate is preferred.

Most clients will not be ECDSA capable, so you will likely also need an RSA or DSA certificate and private key.

That mentions Netscape as a client... so how accurate the information in those postfix docs are today is uncertain.. Mozilla does have some modern docs mentioning similar(EDIT: The docs are old, ECDSA support shouldn't be that uncommon anymore, postfix and dovecot do support dual certificates such that an RSA one could also be provided as fallback. RSA is still valid and a common default from CAs and tools however):

  • We recommend ECDSA certificates using P-256, as P-384 provides negligable improvements to security and Ed25519 is not yet widely supported
  • Certificate type: ECDSA (P-256) (recommended), or RSA (2048 bits)
  • ECDSA certificates are recommended over RSA certificates, as they allow the use of ECDHE with Windows 7 clients using Internet Explorer 11, as well as allow connections from IE11 on Windows Server 2008 R2
  • Administrators needing to provide access to IE 11 on Windows Server 2008 R2 and who are unable to switch to or add ECDSA certificates can add TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

Thus I assume the omission of ECDSA ciphers in my results is due to docker-mailserver generating an RSA cert when none is provided? Which means nmap is not able to query the full support(or rather postfix needs to be tested with an ECDSA cert provided as well? (EDIT: This is correct, at the time of the PR, Postfix only supports one full key+certificate chain, the self-signed mode generates an RSA private key to sign certificates with. nmap thus receives no ECDSA results as there is no ECDSA private key + certificates using it supplied from the server to support that)

Not that it matters.. with the current excludes, as they specifically have an exclude for ECDSA which I believe ignores any in the cipherlist override tls_high_cipherlist.. (EDIT: verified, ECDSA in excludes prevented Postfix from supporting any cipher suites using ECDSA as the signature algorithm, aka ECDSA private key for the certificate rather than the more common/default RSA)

`smtpd_tls_exclude_ciphers` does affect `tls_high_cipherlist`
# user-patches.sh
sed -i "s/^smtpd_tls_exclude_ciphers.*/smtpd_tls_exclude_ciphers = AES128/" /etc/postfix/main.cf
sed -i "s/^tls_high_cipherlist/tls_medium_cipherlist/" /etc/postfix/main.cf
PORT   STATE SERVICE
25/tcp open  smtp
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

For completeness (kinda), to no surprise each of these ports return the same output(default modern TLS_LEVEL):

Ports 587, 465, 993 - Default DockerHub
PORT    STATE SERVICE
587/tcp open  submission
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

PORT    STATE SERVICE
465/tcp open  smtps
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

PORT    STATE SERVICE
993/tcp open  imaps
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

Intermediate TLS_LEVEL

The intermediate TLS_LEVEL has had it's cipherlist truncated. None of these cipher suites appear to remain available after applying the excludes list (smtpd_tls_exclude_ciphers) on them. If the excludes list is empty/disabled, each TLS level presents ciphers(when the allowed cipher suites are only set to those this PR has removed) with the warning:

Forward Secrecy not supported by any cipher

This is misleading when associating them with a high grade list intended for mandatory TLS support. Despite the warning, the nmap tool grades them all with with A for encryption strength(if that's at all trustworthy of a metric). (EDIT: Those nmap results below are cipher suites that were excluded, TLS_RSA_* use RSA for key exchange, not ephemeral key exchanges (DHE and ECDHE). The A grade should be ignored in that if the private key were acquired by an attacker, they could decrypt any recorded encrypted exchanges, thus it's not a cipher suite you want to support as FS is not provided, the warning is very much valid)

The intermediate cipherlist still produces the same cipher support with the new reduced list and exclusions. (EDIT: For clarity it seems the assigned list in user-patches.sh below is from cipher suites for intermediate set in start-mailserver.sh that this PR removes. The results are meant to illustrate that without any excludes, when they are the only supported ciphers, none are presented to a client as negotiable? That is clearly not true since the results return insecure cipher suites, the excludes that have been kept should however remove these. Possibly what I tried to communicate was that the list of cipher suites in the results below are not present in prior results when the excludes are applied?)

Removed `intermediate` TLS_LEVEL ciphers as cipherlist (no excludes)
# user-patches.sh
sed -i "s/^smtpd_tls_exclude_ciphers.*/# nope/" /etc/postfix/main.cf
sed -i "s/^tls_high_cipherlist.*/tls_medium_cipherlist = ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS/" /etc/postfix/main.cf
PORT   STATE SERVICE
25/tcp open  smtp
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       Forward Secrecy not supported by any cipher
|   TLSv1.1: 
|     ciphers: 
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       Forward Secrecy not supported by any cipher
|   TLSv1.2: 
|     ciphers: 
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       Forward Secrecy not supported by any cipher
|_  least strength: A

@polarathene
Copy link
Copy Markdown
Member Author

Changes to Consider

Change smtpd_tls_mandatory_ciphers from high to medium?

I'm having some trouble getting information about smtpd_tls_ciphers (opportunistic STARTTLS or the mandatory variant that only applies to implicit TLS).

We have it set to high while Mozilla is using medium, this could just be a lack of trust with their postfix template that was contributed, as their project is mostly focused on adding the cipher advice configs while relying on contributors for the various templates in their generator website afaik(eg, they've presently got an obsolete postfix config parameter smtpd_use_tls).

Do note what the postfix docs have to say(unsure of when those were last updated, some of the docs do seem to have outdated information, eg port 465):

The default grade ("medium") is sufficiently strong that any benefit from globally restricting TLS sessions to a more stringent grade is likely negligible, especially given the fact that many implementations still do not offer any stronger ("high" grade) ciphers, while those that do, will always use "high" grade ciphers.

So insisting on "high" grade ciphers is generally counter-productive. No known SMTP clients fail to support at least one "medium" or "high" grade cipher.

medium describes itself as "These use 128-bit or longer symmetric bulk-encryption keys.". All available cipher grades have the warning "you are strongly encouraged to not change.". Changing them based on OWASP and Mozilla advice and keeping them in sync between Postfix and Dovecot is probably fine..

There isn't much information what the default grades provide (needs to be inspected via CLI command afaik?). (EDIT: Used nmap to inspect, not sure if this is the best way)

This change would really only affect port 25 inbound traffic with STARTTLS. Ports 465 and 587 are submission ports where users are more likely to be using capable clients, TLS is mandatory for these by default, as is Dovecot(TODO: Confirm this) ports (110, 143, 993, 995) for retrieval via those same clients.

Enforcing stricter ciphers via high makes sense here, while leaving port 25 for more compatibility to receive email.

Statistics / info if useful
  • Google provides a transparency report about inbound/outbound traffic of their SMTP service. They don't break down encryption by protocol or ciphers however. Presently outbound is at 90%+, dropping down to 80% in a recurring monthly pattern(automated bulk, less important to worry about). Inbound is at ~93%. In the ranking section, there are some well known domains sending inbound email with low or 0% encryption, eg adobe(80%), samsung(60%), aliexpress / aol / yahoo japan all at 0%.
  • There is a July 2019 SMTP TLS report, which reports TLS 1.2 being negotiated 90% of the time, lower protocols were only < 3%. How likely those emals are not spam is unclear, the blog did not continue to post anymore SMTP stat updates and the twitter account no longer exists.
  • TLS 1.2 is the minimum supported protocol, as recommended by RFC 7525, PCI DSS, and others. RFC 7525 has declared this since 2015, any SMTP service that is legitimate should really have caught up by now as their service would be increasing in rejections(or sadly favoring plain text via STARTTLS as is required to be supported for inbound traffic on port 25).
  • The retirement of insecure protocols from the list of supported protocols was announced by all major browser makers including Microsoft, Google, Apple, and Mozilla back in October 2018. They all aim to accomplish that by mid 2020, but Microsoft and Mozilla have both announced delays due to covid-19. While that is browsers, still worth noting.

Allow client to choose cipher?

When allowing the client to choose the cipher from the list instead, which mozilla advises for their intermediate and modern profiles, the client can opt for what would suit it best, all ciphers the server advertises from this list are considered strong, so selection isn't a concern.

tls_preempt_cipherlist controls server/client preference in postfix. Mozilla has set it to no, which is the default in postfix docs. I have not changed it to no, as that would require port 25 inbound STARTTLS to also use the same high cipherlist to follow Mozilla's advice(or just modify cipherlist for medium and prefer that over high).

Probably a good idea to allow client cipher selection for modern profile at least?

@polarathene
Copy link
Copy Markdown
Member Author

TL;DR

  • The modern TLS_LEVEL cipherlist is updated to accommodate OWASP B and Mozilla Intermediate ciphers.
  • The intermediate TLS_LEVEL cipherlist has only received housekeeping. Removing ciphers that are presently excluded by smtpd_tls_exclude_ciphers anyway.
  • smtpd_tls_exclude_ciphers has also received housekeeping. It has been reduced to only the relevant excludes, matching the same cipher support presently offered - except for ECDSA, which is no longer excluded.
  • ECDSA, despite having ciphers for it in the cipherlist, has not been supported by this image afaik. It seems to require a user supplied ECDSA cert(RSA is default), however the exclude list ignored these ciphers from what I can tell. I've not kept it excluded as that seems like it was a bug.

@youtous
Copy link
Copy Markdown
Contributor

youtous commented Apr 28, 2020

Thank you for the detailed justification. For this kind of changes we should be relying on an auditing tool such as https://github.com/drwetter/testssl.sh.

@polarathene
Copy link
Copy Markdown
Member Author

For this kind of changes we should be relying on an auditing tool such as https://github.com/drwetter/testssl.sh.

Yes, that'd be a good idea. I came across that yesterday while working on this PR. It flags some features as negative, when they shouldn't be, but isn't always practical for it to know better. The linked issue is about allowing client preference for the cipher, which should be allowed when strong ciphers are only available to choose from.

@youtous
Copy link
Copy Markdown
Contributor

youtous commented Apr 28, 2020

Additionally, often browsers are better maintained than web servers updated. So the client's preferences are probably not bad.

I don't think this can be applied to mail clients.

Server preferred cipher order is a good practice. Mail clients are not always choosing the best cipher (android applications 👀 ).

While some false positive could happened when using this kind of tool, this image should stick to "security first, optimization as fine tuning".
The optimizations such as disabling server cipher preference by default order can decrease security and should be let as a fine-tuning done by the user (knowing what he's doing).

PS: I'll try to integrate testssl to the tests :) If you know other auditing tools, I could be great to have different analyses.

@polarathene
Copy link
Copy Markdown
Member Author

Server preferred cipher order is a good practice. Mail clients are not always choosing the best cipher

Define "best" cipher. If the OWASP ciphers are ignored, Mozilla states that all ciphers in their cipherlist are strong ciphers such that it doesn't matter which one is chosen by the client.

In that case the client can choose the cipher that is best suited for it. If they're all strong, it doesn't matter if it chooses one that it can be processed more quickly. Especially when it comes to hardware encryption support (AES-NI), chacha is said to be better here in that case, the server would not know if the client has AES-NI though would it?

this image should stick to "security first, optimization as fine tuning".

It does? Security isn't being compromised by this PR to the best of my knowledge (albeit I'm not a security professional).

The optimizations such as disabling server cipher preference by default order can decrease security

Is this referring to Mozilla's advice to push the AES128-GCM ciphers in front of the AES256-GCM ones? They do that with server preference in mind, stating it's still safe, but when the client doesn't have preference, it's best to offer up a more performant cipher(out of a list where all are considered to be fine).


I cannot say the same for the intermediate TLS_LEVEL setting in this image. That has support for ciphers less than TLS 1.2. Thus I would not advise leniency to let the client pick, only for modern.

OWASP B can drop the four non-GCM variants it adds, and we'd be using OWASP A instead. Really depends on the decision to allow modern to enable client preference and tighten up the ciphers more, possibly updating intermediate to be more strict(not sure about this for mail servers, I'm aware they lag more in support).

Do note under the statistics section in this PR notes(3rd post):

  • TLS 1.2 is the minimum supported protocol, as recommended by RFC 7525, PCI DSS, and others. RFC 7525 has declared this since 2015.

Granted, all modern browsers are only starting to enforce that later this year.

Other statistics show TLS 1.2 is negotiated for 90% of secured inbound traffic, where about 90%+ of inbound traffic is encrypted. Some is from valid big tech names, but as it's arriving on port 25, it will be delivered without encryption(this is on Googles SMTP servers).

Mozilla omits some of the ciphers in TLS 1.2, even though they may be still fine (postfix docs encourages not altering the cipherlist defaults it provides):

While the goal is to support a broad range of clients, we reasonably disable a number of ciphers that have little support (such as ARIA, Camellia, 3DES, and SEED)

For MUAs (users submitting / retrieving email from the mail server), we can expect stronger support, and do so via the current cipherlist override and enforcing mandatory TLS.

Client software won't necessarily improve unless it's required to, users that need broader compatibility need to choose a better client or understand the risks of poor support, and downgrade to intermediate TLS_LEVEL which should still support them fine.

Our modern is with SMTP in mind, so it's not matching Mozilla's modern which is TLS 1.3 only.

@youtous
Copy link
Copy Markdown
Contributor

youtous commented Apr 28, 2020

Mozilla states that all ciphers in their cipherlist are strong ciphers such that it doesn't matter which one is chosen by the client.

I Agree. Considering the cipher list is only containing sufficiently secured ciphers, allowing the client to choose the cipher permits him to choose the most efficient cipher for his architecture, it also prevents the client to be forced to use an unadapted cipher (e.g., the server has a weaker cipher in the top its the list). source

Review in progress

  • 🔲 Reduced excludes in smtpd_tls_exclude_ciphers
  • 🔲 Intermediate TLS_LEVEL
  • 🔲 Change smtpd_tls_mandatory_ciphers from high to medium?
  • ✔️ Allow client to choose cipher?

@polarathene
Copy link
Copy Markdown
Member Author

✔️ Allow client to choose cipher?

Needs confirmation on when that should be acceptable.

Presently, we only use our modern and intermediate cipherlists for smtpd_tls_mandatory_ciphers = high, that excludes inbound email on port 25 which uses smtpd_tls_ciphers = medium.

Especially on the intermediate TLS_LEVEL, where <TLSv1.2 is allowed, it may be best to go with the cipher order postfix medium default cipherlist, the first cipher that the client(another mail server) supports from that list would then be chosen. Postfix defaults to letting the client choose though, and the postfix docs state

While server cipher selection may in some cases lead to a more secure or performant cipher choice, there is some risk of interoperability issues. In the past, some SSL clients have listed lower priority ciphers that they did not implement correctly. If the server chooses a cipher that the client prefers less, it may select a cipher whose client implementation is flawed.

But then goes on to say:

Most notably Windows 2003 Microsoft Exchange servers have flawed implementations of DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA.

Neither of those ciphers should be used these days IIRC, that particular client is 17 years old, but I think the ciphers still are present in intermediate TLS_LEVEL.

However, since we're talking about only inbound port 25 (other ports are fine, they use our restricted cipherlist), flawed / insecure ciphers don't matter much, the client could always choose plain text anyway..

So just allow the client to choose ciphers? When considering users submitting / retrieving email, this is over mandatory TLS and unclear how intermediate TLS_LEVEL should be treated. I have not compared Mozilla's old configuration, but their generator will prefer server cipher selection. Thus it's probably best to follow that, or tighten mandatory protocols for intermediate TLS_LEVEL to use TLS 1.2 as a minimum there too(port 25 inbound can remain relaxed).

@erik-wramner
Copy link
Copy Markdown
Contributor

Good discussion and nice work. From my point of view there are two points to consider. One is backwards compatibility for the low security installations. Change those and there are immediately issues about ancient clients that no longer work. The other is good security and best practices for the high security (default) option.

I would generally let the server select the cipher. At least when it comes to browsers it is dangerous to let the client select as it can be used for attacks. We do not control the client; the attacker does. I haven't heard of that kind of attack for mail servers, but that doesn't mean it doesn't exist.

I would also prefer to have high scores in the TLS tests. Some organizations depend on getting good marks in those tests, so a top score with the default configuration is a win. Experts can change the settings, but when you don't know it is nice to get an official stamp.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Apr 29, 2020

One is backwards compatibility for the low security installations. Change those and there are immediately issues about ancient clients that no longer work.

Yes, that is taken into consideration. I've only modified the support for modern TLS_LEVEL.

Those using intermediate should not experience any difference, beyond the possibility of using ECDSA certificates now(assuming the exclude for that prevented ECDSA cipher suites, I would need to verify to confirm).

Other than that, the intermediate cipherlist has just removed ciphers that afaik get removed from the exclude list, so were never available in the present image(only verified via nmap as detailed in the 2nd post).

Cipher excludes were reduced, but parity checked. I may not have checked this correctly, as I've only tested locally on my machine(Manjaro, rolling release distro), if it's possible my local setup/openssl as a client would prevent nmap showing certain cipher support, then I may have made a mistake here.

I've not looked into yet if excludes like MD5 have any relevance in TLS protocols, I know MD5 is insecure, but I'm assuming that must be from SSL protocols which are prohibited. I did test with no excludes and received many other ciphers listed as supported / insecure, so I just ensured based on that, the support with the reduced excludes was the same as what the image presently was showing as supported ciphers for modern and intermediate levels.


The other is good security and best practices for the high security (default) option.

This is mostly placing trust in the linked resources while I gain a better understanding myself to establish more confidence. I'm still doing some research on this and will share findings here for anyone to review.

Perhaps this PR should be changed to a draft with WIP prefix for now? I had amassed a fair amount and wanted to share it here for review / discussion in the meantime.


I would generally let the server select the cipher. At least when it comes to browsers it is dangerous to let the client select as it can be used for attacks.

As discussed with @youtous and earlier in this PRs details(it's lengthy, so I don't blame anyone for not reading through all that), mandatory TLS cipherlist (at least with Mozilla's list, unsure about additions from OWASP B) is considered that all ciphers are strong, thus it doesn't matter how they're ordered/selected (order has still been respected based on OWASP/Mozilla lists), there is no risk allowing the client to choose from the mandatory list, if anything it's considered more compatible/secure (see justification response to @youtous for details).

Mozilla is generic though, so it's also applied to port 25 inbound, using the same cipherlist as mandatory TLS. We don't do that here, as we opt for broader cipher support with third-party mail servers for receiving/delivering email. I believe it's still safe for clients to choose, at least on medium, and postfix docs also encourage it regardless.

There is no enforced TLS for receiving, nor authentication on port 25, so regardless of client cipher selection, the risk may not be there? The ports the user will interact with (465, 587, 110, 143, 993, 995), is more important for strong cipher selection.


Some organizations depend on getting good marks in those tests, so a top score with the default configuration is a win.

Feel free to list what tests you want to see run.

I don't see this PR lowering the score, other than if client selection is enabled. Some of these tests have false positives, so good scores don't necessarily indicate confidence in better security, but in passing compliance. Still they are useful as a guide.

@erik-wramner
Copy link
Copy Markdown
Contributor

Right. I'll be happy to merge this; however, you mentioned WIP. Is there something you want to complete first? If not I'll merge.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Apr 30, 2020

@erik-wramner I haven't finished any mentioned TODO parts, I've only tested from my docker host(so no remote connection), and I'm still doing some more research before I'm more confident about this change.

It should mostly be fine but I don't think there is an immediate need to merge it, I'll ping you when I've moved on to other things and happy with this PR :)

I am aware this doesn't include updating the ciphers for the dovecot test config, I should probably do that before merging.

@erik-wramner erik-wramner changed the title Feat: Use best practice ciphers in 2020 WIP: Feat: Use best practice ciphers in 2020 Apr 30, 2020
@erik-wramner
Copy link
Copy Markdown
Contributor

Good. I've changed the title to WIP, change it back when you're done please. That way I can see that it is pending.

@Kiina
Copy link
Copy Markdown

Kiina commented Jun 27, 2020

Maybe adding smtpd_tls_eckey_file and smtpd_tls_eccert_file as an option would also be a good idea? I'm currently running my mailserver with an ECDSA cert as traefik has some issues with RSA for my use case and currently it doesn't seem to be possible to select the cert you want on a per-host basis (so i'm stuck with ECDSA for everything). However it seems like some mail servers don't like that and you get warning: TLS library problem: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol:../ssl/statem/statem_srvr.c:1661: (to be fair most of these seem to come from spam servers from india, but I can't rule out that it affects any legitimate servers).

smtpd_tls_eckey_file in addition to smtpd_tls_key_file allows you to have an ECDSA and RSA cert as a fallback.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Jun 28, 2020

According to the Postfix docs, those two parameters are obsoleted by smtpd_tls_chain_files. I can look into that for you when I have some time to come back to this(hopefully sometime in July September).

Copy link
Copy Markdown
Member Author

@polarathene polarathene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brief review over my PR, it's been a while so memory of all this is hazy, thankfully I documented this PR heavily ;)

I've been going over some TLS and server config stuff elsewhere recently, and should have some time in the near future to allocate to wrapping up this PR while that related TLS is knowledge is still fresh.


As recently requested by @Kiina I'll be checking into ECDSA support, I've learned that you're most likely to encounter clients not supporting ECDSA as mostly software from 2008 or earlier. These can be catered to with RSA as a fallback using hybrid certificates, which Postfix supports (unclear if Dovecot does, but that would be less of an issue as those clients are more likely to be modern, EDIT: It does have support for this).

These old legacy clients may not like RSA certificates either if the key size is >2048-bit, or possibly many other compatibility issues (I think SNI extension support is another, but not sure if it applies here). Any legitimate client today AFAIK should really be ok with ECDSA certs. Technically, they should still deliver to your MTA, just over an unencrypted line if the TLS handshake could not be established successfully?

Comment thread target/dovecot/10-ssl.conf Outdated

# SSL ciphers to use
ssl_cipher_list = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl_cipher_list = EECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self, typo at the start of the cipher list, EECDHE should be ECDHE.

Review PR notes on list precedence order, the last two ECDHE-RSA should have priority over DHE-RSA.

Everything seems to provide PFS, ECDSA priority over RSA is good.

Comment thread target/postfix/main.cf
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
smtpd_tls_exclude_ciphers = aNULL, SEED, CAMELLIA, RSA+AES
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding inline comment note about this, or just rely on git blame to look up the PR? Probably has related commit message, but once merged may be more of a hassle to look up. Check PR notes or commit message.

This should only affect TLS <=1.2, removed exclusions would have been explained in PR notes with some command and output to confirm the removed ones were no longer needed or shouldn't have been excluding (eg ECDSA makes little sense why that was being excluded before?)

Comment thread target/start-mailserver.sh Outdated
Comment on lines +1003 to +1007
sed -i -r 's/^tls_high_cipherlist =.*$/tls_high_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256/' /etc/postfix/main.cf

# Dovecot configuration (secure by default though)
sed -i -r 's/^ssl_min_protocol =.*$/ssl_min_protocol = TLSv1.2/' /etc/dovecot/conf.d/10-ssl.conf
sed -i -r 's/^ssl_cipher_list =.*$/ssl_cipher_list = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256/' /etc/dovecot/conf.d/10-ssl.conf
sed -i -r 's/^ssl_cipher_list =.*$/ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256/' /etc/dovecot/conf.d/10-ssl.conf
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lists are identical, move them into a single variable instead of duplicate content.

Comment thread target/start-mailserver.sh Outdated
Comment on lines +1016 to +1020
sed -i -r 's/^tls_high_cipherlist =.*$/tls_high_cipherlist = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA/' /etc/postfix/main.cf

# Dovecot configuration
sed -i -r 's/^ssl_min_protocol = .*$/ssl_min_protocol = TLSv1/' /etc/dovecot/conf.d/10-ssl.conf
sed -i -r 's/^ssl_cipher_list = .*$/ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS/' /etc/dovecot/conf.d/10-ssl.conf
sed -i -r 's/^ssl_cipher_list = .*$/ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA/' /etc/dovecot/conf.d/10-ssl.conf
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lists are identical, move them into a single variable instead of duplicate content.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Aug 22, 2020

Hybrid/Dual cert support

Note: ECDSA support requires OpenSSL 1.0.0 or later and may not be available on your system. Not all client systems will support ECDSA, so you'll generally want to deploy both RSA and ECDSA certificates to make use of ECDSA with compatible clients and RSA with the rest.
If you want to deploy certificate chains with intermediate CAs for both RSA and ECDSA, you'll want at least OpenSSL 1.0.2, as earlier versions may not handle multiple chain files correctly. - Source (Postfix docs)

2015 article about hybrid/dual cert support in postfix, mentions a slight compatibility issue with an earlier openssl version, but that shouldn't matter AFAIK. Provides this config snippet (with the requirement to put ECDSA cipher suites upfront ahead of RSA):

# RSA key and certificate chain
smtpd_tls_key_file = /etc/ssl/private/smtpd-key.pem
smtpd_tls_cert_file = /etc/ssl/certs/smtpd-cert.pem
# ECDSA key and certificate chain
smtpd_tls_eckey_file = /etc/ssl/private/smtpd-key-ecdsa.pem
smtpd_tls_eccert_file = /etc/ssl/certs/smtpd-cert-ecdsa.pem

As mentioned earlier in this thread though, newer postfix (>=3.4) uses smtpd_tls_chain_files instead. It's postfix docs covers configuration pretty well, with two examples of each cert type having it's own PEM file in the chain, or all certs being provided via single PEM file.


Dovecot has support as well:

Since v2.2.31+ you can specify alternative ssl certificate that will be used if the algorithm differs from the primary certificate. This is useful when migrating to e.g. ECDSA certificate.

Presumably RSA would be provided there.


A related mail server project has had a similar discussion on dual-cert support. They have a related PR that points out concerns for TLSA records when DNSSEC/DANE is in use.

I think this feature should be implemented separately to this PR which should just focus on the cipher suite update.

@georglauterbach
Copy link
Copy Markdown
Member

This is great work @polarathene - hearing you were thinking about wrapping this PR up. What's the current status?

@polarathene
Copy link
Copy Markdown
Member Author

@aendeavor if I don't have anything else come up over the next week, I should have time to allocate to wrapping this up finally :)

It's mostly good, just need to follow through with my review changes and do some testing. Sorry for the delay, I didn't expect to be so busy elsewhere.

@georglauterbach
Copy link
Copy Markdown
Member

georglauterbach commented Sep 10, 2020

Awesome. I will try getting the refactoring of start-mailserver.sh out of the way beforehand. This will probably mean resolving a conflict more, but is significantly less work on my side. Reach back to me when you're ready.

EDIT: The PR introducing the refactoring is #1605

@erik-wramner I noticed the build on master, especially the elk build is not passing. What's up with that? And if these changes are in, is the code automatically built on DockerHub into the latest-image?

@erik-wramner
Copy link
Copy Markdown
Contributor

Yes, your changes should make it into latest automatically. As for elk, I think we dropped that one in 7.0 when we upgraded Debian version. The elk build should be from the 6.x release, so it is quite old. Ideally we should stop building it.

Related is the `smtpd_tls_exclude_ciphers` parameter. Mozilla doesn't include it, and while it's possible to find relatively recent blogs / guides making use of it, they often don't explain any useful reasoning for the choices. I think it has just become a bit of parroting of information and a "better safe than sorry if I don't understand this" approach. Looking at the [postfix docs](http://www.postfix.org/postconf.5.html#smtpd_tls_exclude_ciphers) we have:

> List of ciphers or cipher types to exclude from the SMTP server cipher list at all TLS security levels. 

> Excluding valid ciphers *can create interoperability problems*. **DO NOT** exclude ciphers unless it is essential to do so.

> Cipher types listed in `smtpd_tls_mandatory_exclude_ciphers` or `smtpd_tls_exclude_ciphers` are excluded from the base definition of the selected cipher grade. 

> The underlying cipherlists for grades other than "null" include anonymous ciphers, but these are automatically filtered out if the server is configured to ask for remote SMTP client certificates. You are very unlikely to need to take any steps to exclude anonymous ciphers, **they are excluded automatically as required**. 

Additionally [`aNULL` also excludes `ADH`](https://community.letsencrypt.org/t/using-lets-encrypt-certs-with-postfix/18957/8). 

I have verified parity of the current excluded ciphers with this reduced set. They should be clear which ciphers they're responsible for, except for `MEDIUM` which handled the two `SEED` ciphers. Since `MEDIUM` is ambiguous to what it's covering(the others are still required for parity), I have switched `MEDIUM` to `SEED`. In my testing these excluded ciphers are still graded an `A`, only anon certs that `aNULL` excludes provide a lower `F` grade, but the docs state it's a non-issue with remote connections.

We could also change the `high` cipherlist to `medium` like mozilla does or keep the expanded coverage for inbound mail. Should be possible to have submission ports be considered more trustworthy and better cipher support, allowing the client to choose the cipher from the high list would be a good improvement.
`modern` TLS_LEVEL has had it's cipherlist updated to match the postfix `main.cf`change in the related prior commit. See that commit message for more details about the change.

`intermediate` TLS_LEVEL has had it's cipherlist truncated. None of these appear to remain available after applying the excludes on them. If the excludes are removed, each TLS level presents ciphers(when the cipherlist is only set to this removed list) with the warning:

> Forward Secrecy not supported by any cipher

This is misleading when associating them with a `high` grade list intended for mandatory TLS support. Despite the warning, the nmap tool grades them all with with A for encryption strength(if that's at all trustworthy of a metric).

The `intermediate` cipherlist still produces the same cipher support with the reduced list and exclusions from the previous commit.
Same changes to cipherlist as communicated in the related postfix `main.cf` commit.
There was an extra `E` accidentally in the first `ECDHE`.
This was the same content for the most part. Shared content was moved into a function call and dynamic content passed in as variables from each TLS_LEVEL case.
@polarathene polarathene force-pushed the feat/use-best-practice-ciphers-2020 branch from 8d38108 to 7a264b6 Compare September 26, 2020 13:32
@georglauterbach
Copy link
Copy Markdown
Member

georglauterbach commented Sep 26, 2020

Already had a look at the tests. The infamous 260 checking setup.sh: setup.sh email add and login failed. There is already an issue for this (#1459) - the easiest solution is pushing another commit to trigger a rebuild.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Sep 26, 2020

Now failing with:

The command "make generate-accounts run generate-accounts-after-run fixtures tests" exited with 2.


I'll make a commit in future then. I was hoping to get the TLS tests sorted today but had a minor setback get in the way. Once those are run if all goes well I think we only need to drop the CBC ciphers.

Port 587 should be mandatory STARTTLS? testssl.sh seemed to flag it as opportunistic like port 25 (which isn't a real issue for that port) for some reason. IIRC, Postfix doesn't exchange credentials on 587 unless a secure connection is established, so should still be safe.

@georglauterbach
Copy link
Copy Markdown
Member

Port 587 should be mandatory STARTTLS? testssl.sh seemed to flag it as opportunistic like port 25 (which isn't a real issue for that port) for some reason. IIRC, Postfix doesn't exchange credentials on 587 unless a secure connection is established, so should still be safe.

Sounds very good to me.

@erik-wramner
Copy link
Copy Markdown
Contributor

I'm pretty sure that 587 is mandatory STARTTLS in the released version as that question has come up before several times? Could be a false alarm. Anyway, good work on this.

@polarathene
Copy link
Copy Markdown
Member Author

polarathene commented Sep 30, 2020

I'm pretty sure that 587 is mandatory STARTTLS in the released version as that question has come up before several times? Could be a false alarm.

Yep, false alarm 👍

The testssl.sh results just treat any connection using STARTTLS as not fit for grading under the assumption that TLS isn't mandatory. The test still works well and provides plenty of information, you just can't gauge much from the rating section which becomes void.

It doesn't matter for us much as the rating is only about what protocols you're allowing, DH param size and cipher strength (only deemed it's size in bits), our supported protocols don't change, nor does DH params, and I don't see anything wrong with 128-bit ciphers like AES128-GCM, which will prevent the score improving over what we have currently, despite improvements.


I'm currently running my mailserver with an ECDSA cert as traefik has some issues with RSA for my use case and currently it doesn't seem to be possible to select the cert you want on a per-host basis (so i'm stuck with ECDSA for everything). However it seems like some mail servers don't like that and you get warning: TLS library problem: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol:../ssl/statem/statem_srvr.c:1661: (to be fair most of these seem to come from spam servers from india, but I can't rule out that it affects any legitimate servers).

@Kiina I have tested ECDSA certs and confirmed that Postfix is presently configured to exclude all ECDSA ciphers. testssl.sh was unable to produce any results for Postfix SMTP ports (25, 587, 465) when using an ECDSA certificate instead of RSA.

Unless the mail servers sending mail to your instance are using TLS 1.3, they'd all be opting for plain text as they likely couldn't establish any TLS negotiation otherwise, as your Postfix is configured to exclude ECDSA ciphers and you're not serving an RSA cert... hence the error I believe? (I get that plenty with testssl.sh when testing all ciphers, not just the ones the server reports as available)

Good news is I've implemented dual cert support so you can provide the RSA fallback, Dovecot will use it too(Dovecot isn't excluding ECDSA ciphers so any MUA should already be fine securely retrieving mail). You'll still need this PR as well for ECDSA to be supported with Postfix (or remove the ECDSA from smtpd_tls_exclude_ciphers in main.cf).

@polarathene
Copy link
Copy Markdown
Member Author

I am still actively working on this, apologies for the delay. I've been collecting and documenting a rather large amount of information regarding TLS version history, usage and cipher suite compatibility.

I'll be sharing it here once it's ready as a rather comprehensive resource on the topic. It should be useful to anyone else that needs to make such a decision with confidence. If there's a need to get this PR wrapped up sooner, do let me know, otherwise I'm estimating 1-2 weeks at the latest (depending on free time I can allocate).


We may want to discuss deprecating intermediate / legacy client support. There's an RFC in progress since 2018 and expected to be completed next year that officially advise no longer supporting these protocol versions with any usage of TLS.

OpenSSL 3.0 (expected to be released early 2021H1) is said to be removing TLS 1.0 & 1.1 cipher suites by default, we would need to explicitly lower the security level with :@SECLEVEL=0 appended to the end of our cipherlists (assuming Postfix/Dovecot continue to release with support for using these TLS versions once that RFC is published).

Perhaps something to consider for 8.0. My full report will provide more details to support the decision, the only client that seems to be a valid concern is macOS/iOS releases prior to Sep 2016 which use Apple Mail instead of an alternative like Mozilla ThunderBird. Servers (for which it matters less with port 25 deliveries) should be good from 2014 onwards (as-in the majority of deployments should have no issues for TLS 1.2 support by then).

@georglauterbach
Copy link
Copy Markdown
Member

georglauterbach commented Nov 6, 2020

I've marked it for 7.3, so there is no need to hurry, since the next release, i.e. 7.2, comes in two weeks. Therefore, 7.3 has a big amount of time, and if you need more, I'll mark it for later :D

We may want to discuss deprecating intermediate / legacy client support. There's an RFC in progress since 2018 and expected to be completed next year that officially advise no longer supporting these protocol versions with any usage of TLS.

If you ask me, I'm all for it. I know there is a never-ending debate on supporting old clients and versions, but I'm a supporter of having servers and clients up-to-date. I'd go for it.

OpenSSL 3.0 (expected to be released early 2021H1) is said to be removing TLS 1.0 & 1.1 cipher suites by default, we would need to explicitly lower the security level with :@SECLEVEL=0 appended to the end of our cipherlists (assuming Postfix/Dovecot continue to release with support for using these TLS versions once that RFC is published).

That's one of the reasons I'd like to be up-to-date withut support for outdated versions.

@polarathene
Copy link
Copy Markdown
Member Author

I know there is a never-ending debate on supporting old clients and versions

Yes, this is usually due to mail clients (MUA and MTA) lagging behind browsers TLS support.

Often I only ever saw the concern expressed for legacy clients without much knowledge as to what fell under that umbrella and when, so I've looked into that with references for the majority of cases where that'd have been a concern, be that support for TLS version, cipher suites or ECC (ECDSA / ECDHE).

I'm rather confident we can issue a deprecation notice to drop legacy support from 8.0 release and require anyone wanting to support legacy to use 7.x or a user-patches script (we could document an example in the wiki). Should I add a deprecation notice in this PR when intermediate is used? (in addition to a changelog mention)

@georglauterbach
Copy link
Copy Markdown
Member

I'd strongly recommend doing so, yes.

@erik-wramner
Copy link
Copy Markdown
Contributor

Sorry for barging in late, but I feel we should keep support for old clients using an option, but use best practice ciphers by default. I tried to change this and there were users having problems. You can control the server, but it is not always possible to control the clients. Relegating installations to old versions that won't be patched and supported because they need to support mail clients they cannot upgrade seems less than ideal.

It would be another thing if this stopped us from adopting something, but as far as I can see it doesn't. We can use whatever we like with the default modern setting and still support old clients with the legacy setting, right?

@polarathene
Copy link
Copy Markdown
Member Author

I feel we should keep support for old clients using an option, but use best practice ciphers by default. I tried to change this and there were users having problems.

I'm aware. When I've completed the report it'll detail everything needed to make such a decision. The only likely clients that come to mind are macOS 10.11 and iOS 9 users (prior to sep 2016 release), neither receives security updates since mid 2018.

You can control the server, but it is not always possible to control the clients. Relegating installations to old versions that won't be patched and supported because they need to support mail clients they cannot upgrade seems less than ideal.

That's understandable. I'm not going to push for it other than provide the information and references towards making that decision. TLS 1.1 for most updates came with TLS 1.2 support. So you're supporting TLS 1.0 from 1999 with a few CBC cipher suites.

A new RFC advising against supporting such an old TLS version is expected to be published out of draft status sometime next year. OpenSSL 3.0 will also drop support by default, so when upgrading Debian base image at some point when it adopts the new version expect TLS 1.0 support to require additional effort to support.

It would be another thing if this stopped us from adopting something, but as far as I can see it doesn't. We can use whatever we like with the default modern setting and still support old clients with the legacy setting, right?

Yes, I don't see any issues supporting a legacy profile (might be better to call it "legacy" rather than "intermediate").

OpenSSL 3.0 just requires us to lower the security level via cipher list string, we might have to explicitly define the cipher suites for port 25 though (presently we use postfix defaults for that port and exclude some ciphers). Unless a future update of Postfix/Dovecot drops support.


macOS users that for whatever reason are unable to upgrade (systems older than year 2010) are only affected by mail apps that use Secure Transport (Apple TLS), such as Apple Mail. They could use web mail clients or alternatives that use a different TLS implementation like Thunderbird and be ok.

iOS users unable to upgrade to iOS 10 seems to be devices from 2012 and earlier? Support for iOS 9 ended in 2019.

It really depends how long you want to officially support that vs direct admins towards a wiki entry for legacy deployments to handle themselves (user patch). Since both macOS and iOS versions affected no longer receive updates, they've reached EOL status? I already know of one mail host that's only offering TLS 1.2 as a minimum since this year, I've not checked support on popular services yet.


@erik-wramner So are we leaving "intermediate" as-is and not logging a deprecation notice about TLS 1.0/1.1 being dropped in a future release?

@erik-wramner
Copy link
Copy Markdown
Contributor

@polarathene as long as it works I don't mind the warning. As you say it will be removed by upstream eventually and I certainly don't plan on supporting it at that point. However, as long as it is supported by upstream I would ideally not want to rock the boat for those admins who have to manage old clients.

When you mention it I think iOS devices were the main source of problems last time.

@georglauterbach georglauterbach changed the title WIP: Feat: Use best practice ciphers in 2020 WIP: Feat: Use best practice ciphers in 2020/21 Jan 1, 2021
@georglauterbach
Copy link
Copy Markdown
Member

@polarathene I will close this PR in this repository as we just migrated to docker-mailserver/docker-mailserver. Please re-open your PR over there. This PR is very much awaited :D

@polarathene
Copy link
Copy Markdown
Member Author

Yes sorry, been a busy month, I still intend to complete this.

Heads up that very soon default renewals of LetsEncrypt will be on a new root certificate that older devices without will fail to trust it. May possibly affect some older macOS / iOS clients from connecting to a mailserver.

Just in case you get reports all of a sudden of breakage, it's possibly due to that switch over. They can use Thunderbird or install a new root certificate directly into their affected devices.

@georglauterbach
Copy link
Copy Markdown
Member

Just FYI: Please do not re-open this PR, but open a new one. That's because of (ugly) merge conflicts that would appear as some files have moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants