From 14e10f40e5cabc3377e49385871b347f5723c8b2 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Fri, 2 Aug 2019 12:25:40 -0700 Subject: [PATCH] Follow Mozilla recs for Nginx ssl_protocols, ssl_ciphers, and ssl_prefer_server_ciphers (#7274) * Follow Mozilla recs for Nginx ssl_protocols, ssl_ciphers, and ssl_prefer_server_ciphers * Add tests and fix if statement * Update CHANGELOG.md Co-Authored-By: Brad Warren * Test that the hashes of all of the current configuration files are in ALL_SSL_OPTIONS_HASHES * Remove conditioning on OpenSSL version, since Nginx behaves cleanly if its linked OpenSSL doesn't support TLS1.3 --- CHANGELOG.md | 3 +- certbot-nginx/certbot_nginx/configurator.py | 2 ++ certbot-nginx/certbot_nginx/constants.py | 12 ++++++-- .../certbot_nginx/options-ssl-nginx-old.conf | 6 ++-- .../options-ssl-nginx-tls12-only.conf | 14 ++++++++++ .../certbot_nginx/options-ssl-nginx.conf | 6 ++-- .../certbot_nginx/tests/configurator_test.py | 28 ++++++++++++++++++- 7 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 certbot-nginx/certbot_nginx/options-ssl-nginx-tls12-only.conf diff --git a/CHANGELOG.md b/CHANGELOG.md index 0960eb4a1..9715d8ad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Changed -* +* Follow updated Mozilla recommendations for Nginx ssl_protocols, ssl_ciphers, + and ssl_prefer_server_ciphers ### Fixed diff --git a/certbot-nginx/certbot_nginx/configurator.py b/certbot-nginx/certbot_nginx/configurator.py index 0c6eabf57..4fd5056a3 100644 --- a/certbot-nginx/certbot_nginx/configurator.py +++ b/certbot-nginx/certbot_nginx/configurator.py @@ -127,6 +127,8 @@ class NginxConfigurator(common.Installer): config_filename = "options-ssl-nginx.conf" if self.version < (1, 5, 9): config_filename = "options-ssl-nginx-old.conf" + elif self.version < (1, 13, 0): + config_filename = "options-ssl-nginx-tls12-only.conf" return pkg_resources.resource_filename("certbot_nginx", config_filename) @property diff --git a/certbot-nginx/certbot_nginx/constants.py b/certbot-nginx/certbot_nginx/constants.py index 3f22000eb..c90b6b52f 100644 --- a/certbot-nginx/certbot_nginx/constants.py +++ b/certbot-nginx/certbot_nginx/constants.py @@ -23,10 +23,17 @@ UPDATED_MOD_SSL_CONF_DIGEST = ".updated-options-ssl-nginx-conf-digest.txt" """Name of the hash of the updated or informed mod_ssl_conf as saved in `IConfig.config_dir`.""" SSL_OPTIONS_HASHES_NEW = [ + '108c4555058a087496a3893aea5d9e1cee0f20a3085d44a52dc1a66522299ac3', +] +"""SHA256 hashes of the contents of versions of MOD_SSL_CONF_SRC for nginx >= 1.13.0""" + +SSL_OPTIONS_HASHES_MEDIUM = [ '63e2bddebb174a05c9d8a7cf2adf72f7af04349ba59a1a925fe447f73b2f1abf', '2901debc7ecbc10917edd9084c05464c9c5930b463677571eaf8c94bffd11ae2', + '30baca73ed9a5b0e9a69ea40e30482241d8b1a7343aa79b49dc5d7db0bf53b6c', ] -"""SHA256 hashes of the contents of versions of MOD_SSL_CONF_SRC for nginx >= 1.5.9""" +"""SHA256 hashes of the contents of versions of MOD_SSL_CONF_SRC for nginx >= 1.5.9 + and nginx < 1.13.0""" ALL_SSL_OPTIONS_HASHES = [ '0f81093a1465e3d4eaa8b0c14e77b2a2e93568b0fc1351c2b87893a95f0de87c', @@ -36,7 +43,8 @@ ALL_SSL_OPTIONS_HASHES = [ '394732f2bbe3e5e637c3fb5c6e980a1f1b90b01e2e8d6b7cff41dde16e2a756d', '4b16fec2bcbcd8a2f3296d886f17f9953ffdcc0af54582452ca1e52f5f776f16', 'c052ffff0ad683f43bffe105f7c606b339536163490930e2632a335c8d191cc4', -] + SSL_OPTIONS_HASHES_NEW + '02329eb19930af73c54b3632b3165d84571383b8c8c73361df940cb3894dd426', +] + SSL_OPTIONS_HASHES_MEDIUM + SSL_OPTIONS_HASHES_NEW """SHA256 hashes of the contents of all versions of MOD_SSL_CONF_SRC""" def os_constant(key): diff --git a/certbot-nginx/certbot_nginx/options-ssl-nginx-old.conf b/certbot-nginx/certbot_nginx/options-ssl-nginx-old.conf index 627bafadb..a678b0507 100644 --- a/certbot-nginx/certbot_nginx/options-ssl-nginx-old.conf +++ b/certbot-nginx/certbot_nginx/options-ssl-nginx-old.conf @@ -7,7 +7,7 @@ ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_timeout 1440m; -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_prefer_server_ciphers on; +ssl_protocols TLSv1.2; +ssl_prefer_server_ciphers off; -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"; diff --git a/certbot-nginx/certbot_nginx/options-ssl-nginx-tls12-only.conf b/certbot-nginx/certbot_nginx/options-ssl-nginx-tls12-only.conf new file mode 100644 index 000000000..1933cbc4f --- /dev/null +++ b/certbot-nginx/certbot_nginx/options-ssl-nginx-tls12-only.conf @@ -0,0 +1,14 @@ +# This file contains important security parameters. If you modify this file +# manually, Certbot will be unable to automatically provide future security +# updates. Instead, Certbot will print and log an error message with a path to +# the up-to-date file that you will need to refer to when manually updating +# this file. + +ssl_session_cache shared:le_nginx_SSL:10m; +ssl_session_timeout 1440m; +ssl_session_tickets off; + +ssl_protocols TLSv1.2; +ssl_prefer_server_ciphers off; + +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"; diff --git a/certbot-nginx/certbot_nginx/options-ssl-nginx.conf b/certbot-nginx/certbot_nginx/options-ssl-nginx.conf index 3cc2b9b28..978e6e8ab 100644 --- a/certbot-nginx/certbot_nginx/options-ssl-nginx.conf +++ b/certbot-nginx/certbot_nginx/options-ssl-nginx.conf @@ -8,7 +8,7 @@ ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_timeout 1440m; ssl_session_tickets off; -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_prefer_server_ciphers on; +ssl_protocols TLSv1.2 TLSv1.3; +ssl_prefer_server_ciphers off; -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"; diff --git a/certbot-nginx/certbot_nginx/tests/configurator_test.py b/certbot-nginx/certbot_nginx/tests/configurator_test.py index 06c8c53c9..35113aa98 100644 --- a/certbot-nginx/certbot_nginx/tests/configurator_test.py +++ b/certbot-nginx/certbot_nginx/tests/configurator_test.py @@ -963,13 +963,39 @@ class InstallSslOptionsConfTest(util.NginxTest): "Constants.ALL_SSL_OPTIONS_HASHES must be appended" " with the sha256 hash of self.config.mod_ssl_conf when it is updated.") - def test_old_nginx_version_uses_old_config(self): + def test_ssl_config_files_hash_in_all_hashes(self): + """ + It is really critical that all TLS Nginx config files have their SHA256 hash registered in + constants.ALL_SSL_OPTIONS_HASHES. Otherwise Certbot will mistakenly assume that the config + file has been manually edited by the user, and will refuse to update it. + This test ensures that all necessary hashes are present. + """ + from certbot_nginx.constants import ALL_SSL_OPTIONS_HASHES + import pkg_resources + all_files = [pkg_resources.resource_filename("certbot_nginx", x) for x in ( + "options-ssl-nginx.conf", + "options-ssl-nginx-old.conf", + "options-ssl-nginx-tls12-only.conf" + )] + self.assertTrue(all_files) + for one_file in all_files: + file_hash = crypto_util.sha256sum(one_file) + self.assertTrue(file_hash in ALL_SSL_OPTIONS_HASHES, + "Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 " + "hash of {0} when it is updated.".format(one_file)) + + def test_nginx_version_uses_correct_config(self): self.config.version = (1, 5, 8) self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), "options-ssl-nginx-old.conf") self._call() self._assert_current_file() self.config.version = (1, 5, 9) + self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), + "options-ssl-nginx-tls12-only.conf") + self._call() + self._assert_current_file() + self.config.version = (1, 13, 0) self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), "options-ssl-nginx.conf")