mailcow / mailcow-dockerized

mailcow: dockerized - 🐮 + 🐋 = 💕
https://mailcow.email
GNU General Public License v3.0
8.73k stars 1.17k forks source link

Add ECDSA certificates #2426

Open OpenLarry opened 5 years ago

OpenLarry commented 5 years ago

Since dovecot, postfix, nginx and openssl all support dual-stack ECDSA and RSA certificates for quite some time, I would love to see mailcow also generating ECC certificates.

ECC certificates use shorter keys and require less computing power providing the same security as RSA. Because RSA certificates can be served as well, there should be no compatibility issues.

Acme-tiny seems to be capable of handling that, so the renewal script would have to be extended and dovecot's, postfix' and nginx' config files slightly changed.

I would like to support mailcow by creating a pull request for that, if you are interested. :-)

There is only one question that comes into my mind, which is still open:

What do you think of the idea? :-)

patschi commented 5 years ago

As far as I was able to find Postfix >=2.6 is also capable of having RSA and ECDSA keys at the same time for backwards-compatibility. See more in the documentation with options smtpd_tls_eccert_file and smtpd_tls_eckey_file.

However with Postfix >= 3.4 the option smtpd_tls_chain_files seems to be recommended, being able to specify multiple certificates at the same time.

christianbur commented 5 years ago

Interesting but in German https://www.kuketz-blog.de/postfix-tls-konfiguration-mit-ecdsa-rsa-zertifikaten/

OpenLarry commented 5 years ago

I'm aware of the dual-stack capabilities in Postfix (that's what I've hyperlinked in my original post).

But the problem I see with Postfix is that you have to modify the main.cf in order to disable the ECDSA certificate via e.g. mailcow.conf (which is important for users using their own RSA-only certificates). Therefore we would need to edit the main.cf (or make a local copy of it inside the docker container?) in order to remove the smtpd_tls_eccert_file and smtpd_tls_eckey_file lines. And editing this file directly is probably bad, because it could result in merge conflicts and unstaged changes in git during future mailcow updates?

@patschi Good point. The smtpd_tls_chain_files option could be an alternative to solve this problem. It looks like we could put either a RSA-only or an ECDSA+RSA-combined certificate into this file. This file could then be generated depending on a mailcow.conf option. Unfortunately mailcow doesn't have Postfix 3.4 yet :-(

mkuron commented 5 years ago

Then let‘s wait until Postfix 3.4 instead of introducing clumsy workarounds.

OpenLarry commented 5 years ago

I did some experimenting to find a good solution to enable or disable the feature easily. Both ways explained before have the drawback that we have to generate/modify config files (and/or postfix' cert chain) for nginx, dovecot and postfix on container start. That doesn't sound good to me as it increases the complexity and could be error-prone.

But I have another idea that seems a lot better to me: We usually have 4 files (cert.pem, key.pem, ecdsa-cert.pem, ecdsa-key.pem), which are passed to the config options of all services permanently. If a user has ECDSA certificates disabled in mailcow.conf, we just symlink ecdsa-cert.pem to cert.pem and ecdsa-key.pem to key.pem. That way we just provide the same (RSA) certificate twice to each service. No service complains about that as openssl just seems to ignore the duplicates and even testssl.sh doesn't complain about that and doesn't show duplicate certificates or something like that.

That would make enabling and disabling the feature very easy as we just have to provide a valid ECDSA certificate or symlink the file to the RSA one. That would avoid modifying config files at all.

If the idea is welcomed, I would submit a PR for that. 😃 I think it would be a nice improvement for Mailcow as Letsencrypt plans to generate ECDSA roots and intermediates as well in a few months. 👍

andryyy commented 5 years ago

I agree with @mkuron.

OpenLarry commented 5 years ago

In my opinion, Postfix 3.4 only solves half of the issue. Yes, we don't have to modify the config file anymore as we can provide one or two certificates in the chain dynamically.

But nginx and dovecot still would need config file adjustments as there doesn't exist a similar option to Postfix I'm aware of. It's just slighty easier here, because we could put the tls options into a separate config file and we do not need to edit the main one.

The symlink solution would avoid editing configs at all. But it's just an idea. :-)

mkuron commented 5 years ago

If a user has ECDSA certificates disabled in mailcow.conf, we just symlink ecdsa-cert.pem to cert.pem and ecdsa-key.pem to key.pem.

That sounds like a nice and simple solution. However, please check the respective documentation to ensure that providing the same certificate twice is officially supported and doesn't just happen to work coincidentally.

OpenLarry commented 5 years ago

The manuals of dovecot, postfix and nginx do not say anything about providing the same certificate twice. But I've checked the source code and all of them (postfix, dovecot, nginx) just forward the certificates to OpenSSL's SSL_CTX_use_certificate() and SSL_CTX_use_PrivateKey() functions regardless of the type.

And OpenSSL states in the doc:

All of the functions to set a new certificate will replace any existing certificate of the same type that has already been set. Similarly all of the functions to set a new private key will replace any private key that has already been set.

So in case ECDSA certificates are disabled and we symlink the file to the RSA one, the "duplicate" certificate overwrites the previous one. Sounds good to me and should work as expected. :-)

patschi commented 5 years ago

I partially agree with @mkuron that "hacky" workarounds are the wrong way. However waiting for years now until Postfix 3.4 is somewhen available in the Ubuntu repository isn't a better way, IMHO.

ECDSA is getting more and more popular and is a great RSA-replacement with noticable benefits, and also rspamd 1.9 (what mailcow now ships) now offers ECDSA support with DKIM keys.

That being said, I'm for a good-planned implementation for ECDSA with the current available options. This shouldn't be such a rocket science and we should be able to find a good-maintainable way where both maintainers and users are happy with.

After a short brainstorming of mine:

  1. Postfix container starts, postfix.sh is called.
  2. Checking if ECDSA certificate and key exists in mentioned bash script just before starting postfix:
    if [ -f "/etc/ssl/mail/cert_ecdsa.pem" ] && [ -f "/etc/ssl/mail/cert_ecdsa.key" ]; then
    postconf -e "smtpd_tls_eccert_file = /etc/ssl/mail/cert_ecdsa.pem"
    postconf -e "smtpd_tls_eckey_file = /etc/ssl/mail/cert_ecdsa.key"
    fi
  3. Done

This way we have following covered:

mkuron commented 5 years ago

Since it's documented OpenSSL functionality, I think @OpenLarry's suggestion is fine. That way we don't need to dynamically modify config files.

kmark commented 5 years ago

Do postfix, dovecot, and nginx document that they will accept the cert chain format OpenSSL documents? If they don't then relying on that behavior from postfix, etc., even though it's documented on OpenSSL's end, would still be relying on the specific implementation of postfix, etc. I would imagine this is a pretty solid assumption given the history of the three projects but wanted to bring this up in case it's considered a blocking issue.

mkuron commented 5 years ago

Do postfix, dovecot, and nginx document that they will accept the cert chain format OpenSSL documents?

I guess that doesn‘t matter. They call OpenSSL functions for all certificate handling. To break on @OpenLarry‘s change, they would need to (at least) implement their own PEM parser, which they are never going to do since they can just use OpenSSL‘s.

kmark commented 5 years ago

I agree that it's unlikely they would implement their own PEM parser. I was more considering they could eventually switch or optionally be built with another crypto lib without breaking their documented behavior.

mkuron commented 5 years ago

I was more considering they could eventually switch or optionally be built with another crypto lib without breaking their documented behavior.

That's also unlikely. Options like the cipher list format are also OpenSSL-specific, so that would get broken too. If they do one day decided to switch to PolarSSL or something else, we would need to install that other library in the Dockerfile and check every single TLS-related option anyway.

kmark commented 5 years ago

Good point. If they ripped out OpenSSL it doesn't sound like this would silently fail, which was my primary concern, since it'd involve a change in dependencies / build process.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.