From f53b18ebb9b1c4c9aba95b3a26bee2be85f8002f Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Sun, 1 Dec 2019 17:49:36 -0500 Subject: [PATCH] Upgrade TLS settings --- CHANGELOG.md | 4 ++++ conf/nginx-ssl.conf | 2 +- security.md | 6 +++--- setup/mail-dovecot.sh | 11 +++++------ setup/mail-postfix.sh | 30 ++++++++++++++++++++---------- setup/web.sh | 7 ++++++- 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 779f13d..f7e1e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ CHANGELOG Under Development ----------------- +System: + +* TLS settings have been upgraded following Mozilla's recommendations for servers. TLS1.2 and 1.3 are now the only supported protocols for web, IMAP, and SMTP (submission). + WebMail: * Set the default Roundcube skin to the new "Elastic" theme. diff --git a/conf/nginx-ssl.conf b/conf/nginx-ssl.conf index 1aba45c..621973d 100644 --- a/conf/nginx-ssl.conf +++ b/conf/nginx-ssl.conf @@ -1,7 +1,7 @@ # We track the Mozilla "intermediate" compatibility TLS recommendations. # Note that these settings are repeated in the SMTP and IMAP configuration. # ssl_protocols has moved to nginx.conf in bionic, check there for enabled protocols. -ssl_ciphers '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'; +ssl_ciphers 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; ssl_dhparam STORAGE_ROOT/ssl/dh2048.pem; # as recommended by http://nginx.org/en/docs/http/configuring_https_servers.html diff --git a/security.md b/security.md index b8dc35a..bc98080 100644 --- a/security.md +++ b/security.md @@ -39,9 +39,9 @@ These services are protected by [TLS](https://en.wikipedia.org/wiki/Transport_La The services all follow these rules: * TLS certificates are generated with 2048-bit RSA keys and SHA-256 fingerprints. The box provides a self-signed certificate by default. The [setup guide](https://mailinabox.email/guide.html) explains how to verify the certificate fingerprint on first login. Users are encouraged to replace the certificate with a proper CA-signed one. ([source](setup/ssl.sh)) -* Only TLSv1, TLSv1.1 and TLSv1.2 are offered (the older SSL protocols are not offered). -* HTTPS, IMAP, and POP track the [Mozilla Intermediate Ciphers Recommendation](https://wiki.mozilla.org/Security/Server_Side_TLS), balancing security with supporting a wide range of mail clients. Diffie-Hellman ciphers use a 2048-bit key for forward secrecy. For more details, see the [output of SSLyze for these ports](tests/tls_results.txt). -* SMTP (port 25) uses the Postfix medium grade ciphers and SMTP Submission (port 587) uses the Postfix high grade ciphers ([more info](http://www.postfix.org/postconf.5.html#smtpd_tls_mandatory_ciphers)). +* Only TLSv1.2+ are offered (the older SSL protocols are not offered). +* We track the [Mozilla Intermediate Ciphers Recommendation](https://wiki.mozilla.org/Security/Server_Side_TLS), balancing security with supporting a wide range of mail clients. Diffie-Hellman ciphers use a 2048-bit key for forward secrecy. For more details, see the [output of SSLyze for these ports](tests/tls_results.txt). +* SMTP port 25 (inbound) follows similar rules. Outbound SMTP (i.e. the server is the client) uses more relaxed settings. Additionally: diff --git a/setup/mail-dovecot.sh b/setup/mail-dovecot.sh index d0498ab..0926ce9 100755 --- a/setup/mail-dovecot.sh +++ b/setup/mail-dovecot.sh @@ -78,16 +78,15 @@ tools/editconf.py /etc/dovecot/conf.d/10-auth.conf \ "auth_mechanisms=plain login" # Enable SSL, specify the location of the SSL certificate and private key files. -# Disable obsolete SSL protocols and allow only good ciphers per http://baldric.net/2013/12/07/tls-ciphers-in-postfix-and-dovecot/. -# Enable strong ssl dh parameters - +# Use Mozilla's "Intermediate" recommendations at https://ssl-config.mozilla.org/#server=dovecot&server-version=2.2.33&config=intermediate&openssl-version=1.1.1, +# except that the current version of Dovecot does not have a TLSv1.3 setting, so we only use TLSv1.2. tools/editconf.py /etc/dovecot/conf.d/10-ssl.conf \ ssl=required \ "ssl_cert=<$STORAGE_ROOT/ssl/ssl_certificate.pem" \ "ssl_key=<$STORAGE_ROOT/ssl/ssl_private_key.pem" \ - "ssl_protocols=!SSLv3" \ - "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" \ - "ssl_prefer_server_ciphers=yes" \ + "ssl_protocols=TLSv1.2" \ + "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" \ + "ssl_prefer_server_ciphers=no" \ "ssl_dh_parameters_length=2048" # Disable in-the-clear IMAP/POP because there is no reason for a user to transmit diff --git a/setup/mail-postfix.sh b/setup/mail-postfix.sh index 75e09a1..695884e 100755 --- a/setup/mail-postfix.sh +++ b/setup/mail-postfix.sh @@ -80,7 +80,6 @@ tools/editconf.py /etc/postfix/main.cf \ # OpenDKIM milter only. See dkim.sh. # * Even though we dont allow auth over non-TLS connections (smtpd_tls_auth_only below, and without auth the client cant # send outbound mail), don't allow non-TLS mail submission on this port anyway to prevent accidental misconfiguration. -# * Require the best ciphers for incoming connections per http://baldric.net/2013/12/07/tls-ciphers-in-postfix-and-dovecot/. # By putting this setting here we leave opportunistic TLS on incoming mail at default cipher settings (any cipher is better than none). # * Give it a different name in syslog to distinguish it from the port 25 smtpd server. # * Add a new cleanup service specific to the submission service ('authclean') @@ -93,7 +92,6 @@ tools/editconf.py /etc/postfix/master.cf -s -w \ -o syslog_name=postfix/submission -o smtpd_milters=inet:127.0.0.1:8891 -o smtpd_tls_security_level=encrypt - -o smtpd_tls_ciphers=high -o smtpd_tls_exclude_ciphers=aNULL,DES,3DES,MD5,DES+MD5,RC4 -o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 -o cleanup_service_name=authclean" \ "authclean=unix n - - - 0 cleanup -o header_checks=pcre:/etc/postfix/outgoing_mail_header_filters @@ -111,17 +109,23 @@ sed -i "s/PUBLIC_IP/$PUBLIC_IP/" /etc/postfix/outgoing_mail_header_filters # Enable TLS on these and all other connections (i.e. ports 25 *and* 587) and # require TLS before a user is allowed to authenticate. This also makes # opportunistic TLS available on *incoming* mail. -# Set stronger DH parameters, which via openssl tend to default to 1024 bits -# (see ssl.sh). +# Set stronger DH parameters, which via openssl tend to default to 1024 bits. +# Use Mozilla's "Intermediate" TLS recommendations from https://ssl-config.mozilla.org/#server=postfix&server-version=3.3.0&config=intermediate&openssl-version=1.1.1 +# (but use and override the "high" cipher list so we don't conflict with the +# more permissive settings for outgoing mail). tools/editconf.py /etc/postfix/main.cf \ smtpd_tls_security_level=may\ smtpd_tls_auth_only=yes \ smtpd_tls_cert_file=$STORAGE_ROOT/ssl/ssl_certificate.pem \ smtpd_tls_key_file=$STORAGE_ROOT/ssl/ssl_private_key.pem \ smtpd_tls_dh1024_param_file=$STORAGE_ROOT/ssl/dh2048.pem \ - smtpd_tls_protocols=\!SSLv2,\!SSLv3 \ - smtpd_tls_ciphers=medium \ - smtpd_tls_exclude_ciphers=aNULL,RC4 \ + smtpd_tls_protocols="!SSLv2,!SSLv3,!TLSv1,!TLSv1.1" \ + smtpd_tls_mandatory_protocols="!SSLv2,!SSLv3,!TLSv1,!TLSv1.1" \ + smtpd_tls_ciphers=high \ + smtpd_tls_mandatory_ciphers=high \ + smtpd_tls_exclude_ciphers= \ + 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 \ + tls_preempt_cipherlist=no \ smtpd_tls_received_header=yes # Prevent non-authenticated users from sending mail that requires being @@ -143,8 +147,12 @@ tools/editconf.py /etc/postfix/main.cf \ # offers it, otherwise it will transmit the message in the clear. Postfix will # accept whatever SSL certificate the remote end provides. Opportunistic TLS # protects against passive easvesdropping (but not man-in-the-middle attacks). +# Since we'd rather have poor encryption than none at all, we use Mozilla's +# "Old" recommendations at https://ssl-config.mozilla.org/#server=postfix&server-version=3.3.0&config=old&openssl-version=1.1.1 +# for opportunistic encryption but "Intermediate" recommendations when DANE +# is used (see next and above). + # DANE takes this a step further: -# # Postfix queries DNS for the TLSA record on the destination MX host. If no TLSA records are found, # then opportunistic TLS is used. Otherwise the server certificate must match the TLSA records # or else the mail bounces. TLSA also requires DNSSEC on the MX host. Postfix doesn't do DNSSEC @@ -157,11 +165,13 @@ tools/editconf.py /etc/postfix/main.cf \ # now see notices about trusted certs. The CA file is provided by the package `ca-certificates`. tools/editconf.py /etc/postfix/main.cf \ smtp_tls_protocols=\!SSLv2,\!SSLv3 \ - smtp_tls_mandatory_protocols=\!SSLv2,\!SSLv3 \ smtp_tls_ciphers=medium \ - smtp_tls_exclude_ciphers=aNULL,RC4 \ + tls_medium_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-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA \ + smtp_tls_exclude_ciphers= \ smtp_tls_security_level=dane \ smtp_dns_support_level=dnssec \ + smtp_tls_mandatory_protocols="!SSLv2,!SSLv3,!TLSv1,!TLSv1.1" \ + smtp_tls_mandatory_ciphers=high \ smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt \ smtp_tls_loglevel=2 diff --git a/setup/web.sh b/setup/web.sh index a572022..e6aac6e 100755 --- a/setup/web.sh +++ b/setup/web.sh @@ -31,14 +31,19 @@ sed "s#STORAGE_ROOT#$STORAGE_ROOT#" \ conf/nginx-ssl.conf > /etc/nginx/conf.d/ssl.conf # Fix some nginx defaults. +# # The server_names_hash_bucket_size seems to prevent long domain names! # The default, according to nginx's docs, depends on "the size of the # processor’s cache line." It could be as low as 32. We fixed it at # 64 in 2014 to accommodate a long domain name (20 characters?). But # even at 64, a 58-character domain name won't work (#93), so now # we're going up to 128. +# +# Drop TLSv1.0, TLSv1.1, following the Mozilla "Intermediate" recommendations +# at https://ssl-config.mozilla.org/#server=nginx&server-version=1.17.0&config=intermediate&openssl-version=1.1.1. tools/editconf.py /etc/nginx/nginx.conf -s \ - server_names_hash_bucket_size="128;" + server_names_hash_bucket_size="128;" \ + ssl_protocols="TLSv1.2 TLSv1.3;" # Tell PHP not to expose its version number in the X-Powered-By header. tools/editconf.py /etc/php/7.2/fpm/php.ini -c ';' \