Yet another article about why my cipher string is better than yours
(updated: Nov 2020)
There are several very good articles about hardening OpenSSL ciphers. Over the years I’ve combined lessons learned from others, my own research of standards and best practices, and my own real-life experiences to come up with the OpenSSL cipher string that I’ve found works best. My goal with this string is to provide the best security while minimizing the number of ciphers to maximize handshake performance. Only TLS1.2 and TLS1.3 should be support with mostly AES ciphers in GCM mode. Prime Diffie-Hellman (DHE) ciphers are no longer necessary as all modern browsers prefer Elliptic-curve Diffie-Hellman (ECDHE) over DHE. Also, DHE is significantly slower than ECDHE and prone to vulnerable configuration using weak prime numbers.
The String
ECDH+AESGCM+AES128:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES128:ECDH+AES:!aNULL:!SHA1:!AESCCM
You can test is on your OpenSSL installation
openssl ciphers -v 'ECDH+AESGCM+AES128:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES128:ECDH+AES:!aNULL:!SHA1:!AESCCM'
It should result in the following cipher suites in the following order. You notice that the TLSv1.3 ciphers (the first three) do not follow the priority we defined to put AES128 above AES256.
TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 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 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384
Prioritization Logic
- AESGCM ciphers are preferred over everything else.
- AES-128 is preferred to AES-256. AES-256 provides little improvement to security, while AES-128 is faster making it less taxing in virtual server environments and more resistant to timing attacks.
- SHA1 ciphers are no longer used since it is not support by TLSv1.2+.
- While AESCCM is safe, it is also slow and not commonly used so we will disable it for now.
Apache
You will notice for Apache there is a separate config entry for TLSv1.3 cipher suite order.
SSLEngine on SSLProtocol -All +TLSv1.2 +TLSv1.3 SSLCipherSuite ECDH+AESGCM+AES128:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES128:ECDH+AES:!aNULL:!SHA1:!AESCCM SSLCipherSuite TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 SSLHonorCipherOrder On
Nginx
Currently, Nginx does not have a way to define cipher order for the TLSv1.3 ciphers.
ssl_prefer_server_ciphers On; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDH+AESGCM+AES128:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES128:ECDH+AES:!aNULL:!SHA1:!AESCCM;
Ubuntu Support for OpenSSL 1.1.1
In order to use OpenSSL 1.1.1 on Ubuntu prior to version 18.10, you will need to add a 3rd-party repository for the service you want that supports the latest OpenSSL version. Ondřej Surý is a Debian developer and an important figure in the DNS community. He maintains many packages for Debian repository, including Apache, BIND, MariaDB, PHP etc. He is also one of the maintainers of the official certbot PPA.
If you are using Apache2 web server, for example, you can upgrade Apache2 to his repository, which includes OpenSSL 1.1.1, with the following commands:
add-apt-repository ppa:ondrej/apache2 apt update apt upgrade
more to come…