From c737e92ab0d58358a93d071bfb47aaaeff307df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ba=CC=81lint=20Szekeres?= <balint.szekeres@feat.agency> Date: Mon, 17 Jun 2019 14:20:54 +0200 Subject: [PATCH] Mozilla SSL profiles (with TLSv1.3) --- README.md | 2 + public/assets/js/app.js | 133 +++++++++++++++++++++----- public/index.html | 32 +++---- public/templates/commands.html | 2 +- public/templates/conf/nginx.conf.html | 10 +- 5 files changed, 132 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index f3c54a9..196e802 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ Contributions are what make the open source community such an amazing place to b * [notie](https://jaredreich.com/notie/) - toast notifications ## 📚 Resources +* [Mozilla SSL Configuration Generator v5](https://ssl-config.mozilla.org) +* [Mozilla SSL Configuration Generator](https://mozilla.github.io/server-side-tls/ssl-config-generator/) * [OWASP TLS Cipher String Cheat Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/TLS_Cipher_String_Cheat_Sheet.md) * [Nginx Optimization: understanding sendfile, tcp_nodelay and tcp_nopush](https://thoughts.t37.net/nginx-optimization-understanding-sendfile-tcp-nodelay-and-tcp-nopush-c55cdd276765) * [NGINX Tuning For Best Performance](https://gist.github.com/denji/8359866) diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 3b09ac6..f485685 100644 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -65,7 +65,7 @@ }], // COMMON - HTTPS - ssl_profile: 'B', + ssl_profile: 'intermediate', resolver_cloudflare: true, resolver_google: true, resolver_opendns: true, @@ -404,26 +404,117 @@ 'pptx?|potx?|pptm|potm|ppsx?', }; + // https://github.com/mozilla/ssl-config-generator/blob/master/config/server-side-tls-conf-5.0.json $scope.sslProfiles = { - A: { - name: 'OWASP A (Advanced)', - protocols: 'TLSv1.2 TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256', + modern: { + name: 'Mozilla Modern', + protocols: [ + 'TLSv1.3', + ], + ciphers: [ + 'TLS_AES_256_GCM_SHA384', + 'TLS_AES_128_GCM_SHA256', + 'TLS_CHACHA20_POLY1305_SHA256', + ], + server_preferred_order: false, + dh_param_size: false, + oldest_clients: ['Firefox 63', 'Android 10.0', 'Chrome 70', 'Edge 75', 'Java 11', 'OpenSSL 1.1.1', 'Opera 57', 'Safari 12.1'], }, - B: { - name: 'OWASP B (Broad Compatibility)', - protocols: 'TLSv1.2 TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256: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', + intermediate: { + name: 'Mozilla Intermediate', + protocols: [ + 'TLSv1.2', + 'TLSv1.3', + ], + ciphers: [ + 'TLS_AES_256_GCM_SHA384', + 'TLS_AES_128_GCM_SHA256', + 'TLS_CHACHA20_POLY1305_SHA256', + 'ECDHE-ECDSA-AES256-GCM-SHA384', + 'ECDHE-RSA-AES256-GCM-SHA384', + 'ECDHE-ECDSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES128-GCM-SHA256', + 'ECDHE-ECDSA-CHACHA20-POLY1305', + 'ECDHE-RSA-CHACHA20-POLY1305', + 'DHE-RSA-AES256-GCM-SHA384', + 'DHE-RSA-AES128-GCM-SHA256', + ], + server_preferred_order: true, + dh_param_size: 2048, + oldest_clients: ['Firefox 27', 'Android 4.4.2', 'Chrome 31', 'Edge', 'IE 11 on Windows 7', 'Java 8u31', 'OpenSSL 1.0.1', 'Safari 9'], }, - C: { - name: 'OWASP C (Widest Compatibility)', - protocols: 'TLSv1 TLSv1.1 TLSv1.2 TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256: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:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA', - }, - D: { - name: 'OWASP D (Legacy)', - protocols: 'TLSv1 TLSv1.1 TLSv1.2 TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256: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:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA', + old: { + name: 'Mozilla Old', + protocols: [ + 'TLSv1', + 'TLSv1.1', + 'TLSv1.2', + 'TLSv1.3', + ], + ciphers: [ + 'TLS_AES_256_GCM_SHA384', + 'TLS_AES_128_GCM_SHA256', + 'TLS_CHACHA20_POLY1305_SHA256', + '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', + 'DHE-DSS-AES128-GCM-SHA256', + 'DHE-DSS-AES256-GCM-SHA384', + 'ECDHE-RSA-AES128-SHA256', + 'ECDHE-ECDSA-AES128-SHA256', + 'ECDHE-RSA-AES128-SHA', + 'ECDHE-ECDSA-AES128-SHA', + 'ECDHE-RSA-AES256-SHA384', + 'ECDHE-ECDSA-AES256-SHA384', + 'ECDHE-RSA-AES256-SHA', + 'ECDHE-ECDSA-AES256-SHA', + 'DHE-RSA-AES128-SHA256', + 'DHE-RSA-AES128-SHA', + 'DHE-DSS-AES128-SHA256', + 'DHE-RSA-AES256-SHA256', + 'DHE-DSS-AES256-SHA', + 'DHE-RSA-AES256-SHA', + 'ECDHE-RSA-DES-CBC3-SHA', + 'ECDHE-ECDSA-DES-CBC3-SHA', + 'EDH-RSA-DES-CBC3-SHA', + 'AES128-GCM-SHA256', + 'AES256-GCM-SHA384', + 'AES128-SHA256', + 'AES256-SHA256', + 'AES128-SHA', + 'AES256-SHA', + 'DHE-DSS-AES256-SHA256', + 'DHE-DSS-AES128-SHA', + 'DES-CBC3-SHA', + 'DHE-RSA-CHACHA20-POLY1305', + 'ECDHE-RSA-CAMELLIA256-SHA384', + 'ECDHE-ECDSA-CAMELLIA256-SHA384', + 'DHE-RSA-CAMELLIA256-SHA256', + 'DHE-DSS-CAMELLIA256-SHA256', + 'DHE-RSA-CAMELLIA256-SHA', + 'DHE-DSS-CAMELLIA256-SHA', + 'CAMELLIA256-SHA256', + 'CAMELLIA256-SHA', + 'ECDHE-RSA-CAMELLIA128-SHA256', + 'ECDHE-ECDSA-CAMELLIA128-SHA256', + 'DHE-RSA-CAMELLIA128-SHA256', + 'DHE-DSS-CAMELLIA128-SHA256', + 'DHE-RSA-CAMELLIA128-SHA', + 'DHE-DSS-CAMELLIA128-SHA', + 'CAMELLIA128-SHA256', + 'CAMELLIA128-SHA', + 'DHE-RSA-SEED-SHA', + 'DHE-DSS-SEED-SHA', + 'SEED-SHA', + ], + server_preferred_order: true, + dh_param_size: 1024, + oldest_clients: ['Firefox 1', 'Chrome 1', 'Opera 5', 'Safari 1', 'IE8 on Windows XP', 'Android 2.3', 'Java 7', 'OpenSSL 0.9.8'], }, }; @@ -948,11 +1039,7 @@ // COMMON - HTTPS $scope.isSSLDHRequired = function() { - return $scope.hasHTTPS() && $scope.sslProfiles[$scope.data.ssl_profile].ciphers.indexOf(':DHE') !== -1; - }; - - $scope.isSSLProfileLegacy = function() { - return $scope.hasHTTPS() && $scope.data.ssl_profile === 'D'; + return $scope.hasHTTPS() && $scope.sslProfiles[$scope.data.ssl_profile].dh_param_size; }; $scope.isResolverCloudflare = function() { diff --git a/public/index.html b/public/index.html index d880f9f..2068d64 100644 --- a/public/index.html +++ b/public/index.html @@ -605,28 +605,22 @@ <div class="row"> <legend class="col-sm-3 col-form-label col-form-label-sm">SSL profile</legend> <div class="col-sm-9"> - <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'A' }"> - <input class="form-check-input" type="radio" id="OWASP-A" ng-model="data.ssl_profile" value="A"> - <label class="form-check-label col-form-label-sm" for="OWASP-A"> - <span tooltips tooltip-template="<strong>Advanced</strong>, wide browser compatibility, e.g. to most newer browser versions<br><br>Oldest compatible clients:<ul><li>Android 4.4.2</li><li>Chrome 32/Win 7</li><li>Chrome 34/OS X</li><li>Edge 12/Win 10</li><li>Firefox 27/Win 8</li><li>IE11/Win 7 + MS14-066</li><li>Java8b132</li><li>OpenSSL 1.0.1e</li><li>Safari 9/iOS 9.</li></ul>" tooltip-side="top" tooltip-class="ssl">OWASP A</span> + <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'modern' }"> + <input class="form-check-input" type="radio" id="ssl-modern" ng-model="data.ssl_profile" value="modern"> + <label class="form-check-label col-form-label-sm" for="ssl-modern"> + <span tooltips tooltip-template="For services that don't need backward compatibility, the parameters below provide a higher level of security.<br><br>Oldest compatible clients:<ul><li>{{ sslProfiles.modern.oldest_clients.join('</li><li>') }}</li></ul>" tooltip-side="top" tooltip-class="ssl">Mozilla Modern</span> </label> </div> - <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'B' }"> - <input class="form-check-input" type="radio" id="OWASP-B" ng-model="data.ssl_profile" value="B"> - <label class="form-check-label col-form-label-sm" for="OWASP-B"> - <span tooltips tooltip-template="<strong>Broad</strong> compatibility to browsers, check the compatibility to other protocols before using it, e.g. IMAPS<br><br>Oldest compatible clients: <ul><li>Android 4.4.2</li><li>Chrome 30/Win 7</li><li>Chrome 34/OS X</li><li>Edge 12/Win 10</li><li>Firefox 27/Win 8</li><li>IE11/Win 7</li><li>IE 11/WinPhone 8.1</li><li>Java8b132</li><li>OpenSSL 1.0.1e</li><li>Opera 17/Win 7</li><li>Safari 5/iOS 5.1.1</li><li>Safari 7/OS X 10.9</li></ul>" tooltip-side="top" tooltip-class="ssl">OWASP B</span> + <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'intermediate' }"> + <input class="form-check-input" type="radio" id="ssl-intermediate" ng-model="data.ssl_profile" value="intermediate"> + <label class="form-check-label col-form-label-sm" for="ssl-intermediate"> + <span tooltips tooltip-template="For services that don't need compatibility with legacy clients, but still need to support a wide range of clients, this configuration is recommended.<br><br>Oldest compatible clients: <ul><li>{{ sslProfiles.intermediate.oldest_clients.join('</li><li>') }}</li></ul>" tooltip-side="top" tooltip-class="ssl">Mozilla Intermediate</span> </label> </div> - <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'C' }"> - <input class="form-check-input" type="radio" id="OWASP-C" ng-model="data.ssl_profile" value="C"> - <label class="form-check-label col-form-label-sm" for="OWASP-C"> - <span tooltips tooltip-template="<strong>Widest Compatibility</strong>, compatibility to most legacy browsers, legacy libraries (still patched) and other application protocols besides https, e.g. IMAPS<br><br>Oldest compatible clients: <ul><li>Android 2.3.7/4.0.4</li><li>Chrome 27/Win 7</li><li>Chrome 34/OS X</li><li>Edge 12/Win 10</li><li>Firefox 10.0.12 ESR/Win 7</li><li>Firefox 21/Win 7+Fedora 19</li><li>IE 7/Vista</li><li>IE 10/WinPhone 8.0</li><li>Java 7u25</li><li>OpenSSL 0.9.8y</li><li>Opera 12.15/Win 7</li><li>Safari 5/iOS 5.1.1</li><li>Safari 5.1.9/OS X 10.6.8</li></ul>" tooltip-side="top" tooltip-class="ssl">OWASP C</span> - </label> - </div> - <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'D' }"> - <input class="form-check-input" type="radio" id="OWASP-D" ng-model="data.ssl_profile" value="D"> - <label class="form-check-label col-form-label-sm" for="OWASP-D"> - <span tooltips tooltip-template="<strong>Legacy</strong>, widest compatibility to real old browsers and legacy libraries and other application protocols like SMTP" tooltip-side="top" tooltip-class="ssl">OWASP D</span> + <div class="form-check form-check-inline" ng-class="{ 'input-changed': data.ssl_profile !== defaultData.ssl_profile && data.ssl_profile === 'old' }"> + <input class="form-check-input" type="radio" id="ssl-old" ng-model="data.ssl_profile" value="old"> + <label class="form-check-label col-form-label-sm" for="ssl-old"> + <span tooltips tooltip-template="This is the old ciphersuite that works with all clients back to Windows XP/IE6. It should be used as a last resort only.<br><br>Oldest compatible clients: <ul><li>{{ sslProfiles.old.oldest_clients.join('</li><li>') }}</li></ul>" tooltip-side="top" tooltip-class="ssl">Mozilla Old</span> </label> </div> </div> @@ -655,7 +649,7 @@ <label class="col-sm-3 col-form-label col-form-label-sm"> Let's Encrypt webroot </label> - <div class="col-sm-9"> + <div class="col-sm-9 col-xl-7"> <input type="text" class="form-control form-control-sm" ng-model="data.directory_letsencrypt" diff --git a/public/templates/commands.html b/public/templates/commands.html index 4c7fa09..c0b61e3 100644 --- a/public/templates/commands.html +++ b/public/templates/commands.html @@ -23,7 +23,7 @@ --><!-- ✔ SSL DH required --><span ng-if="isSSLDHRequired()"><span class="hljs-comment"><span class="counter">.</span> Generate Diffie-Hellman keys:</span> - <span class="hljs-section">openssl</span> <span class="hljs-attribute">dhparam -dsaparam</span> <span class="hljs-attribute">-out</span> {{ data.directory_nginx }}dhparam.pem <span class="hljs-number">{{ isSSLProfileLegacy() ? 1024 : 2048 }}</span> + <span class="hljs-section">openssl</span> <span class="hljs-attribute">dhparam -dsaparam</span> <span class="hljs-attribute">-out</span> {{ data.directory_nginx }}dhparam.pem <span class="hljs-number">{{ sslProfiles[ data.ssl_profile ].dh_param_size }}</span> </span><!-- ✔ Let's Encrypt diff --git a/public/templates/conf/nginx.conf.html b/public/templates/conf/nginx.conf.html index 13a44be..2240037 100644 --- a/public/templates/conf/nginx.conf.html +++ b/public/templates/conf/nginx.conf.html @@ -52,7 +52,7 @@ http {<!-- # SSL ssl_session_timeout 1d; - ssl_session_cache shared:SSL:50m; + ssl_session_cache shared:SSL:10m; ssl_session_tickets off;<!-- ✔ SSL DH required --><span ng-if="isSSLDHRequired()"> @@ -61,9 +61,11 @@ http {<!-- ssl_dhparam {{ data.directory_nginx }}dhparam.pem;</span> # {{ sslProfiles[ data.ssl_profile ].name }} configuration - ssl_protocols {{ sslProfiles[ data.ssl_profile ].protocols }}; - ssl_ciphers {{ sslProfiles[ data.ssl_profile ].ciphers }}; - ssl_prefer_server_ciphers on; + ssl_protocols {{ sslProfiles[ data.ssl_profile ].protocols.join(' ') }}; + ssl_ciphers {{ sslProfiles[ data.ssl_profile ].ciphers.join(':') }};<!-- + + ✔ SSL server preferred order --><span ng-if="sslProfiles[ data.ssl_profile ].server_preferred_order"> + ssl_prefer_server_ciphers on;</span> # OCSP Stapling ssl_stapling on;