OpenSSL Ciphers

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…

Scroll to Top