tested with OpenSSL 1.1.1i, 3.0.0-dev and LibreSSL 3.3.1
Here, we’re setting-up a white-list of ciphers to be used, which is a better policy than a black-list. We are trying to get a scalable policy, so we are using blacklists by enabling any new ciphers that would get into library’s update and avoid the need to update NGINX’s ssl_ciphers
. Besides, if you were to use whitelists, beware the cipher suites are not the same whether you have an ECDSA vs. RSA certificate(s).
Note it is possible to have dual/hybrid ECDSA+RSA key pairs available, so you got more available cipher suites the client can choose from. NGINX allows to serve multiple certificates, by simply iterating the configuration lines pointing to the cert and privkey.
To get an A+ grade on ssllabs we need:
To get 100/100 on key exchange we need:
To get 100/100 on key strength we need:
note some CBC modes can remain, you can have WEAK tagged ciphers there while still getting 100/100 for cipher strength.
Check out LibreSSL’s filters (w/o -s
). The default is
openssl ciphers -V openssl ciphers -V 'ALL:!aNULL:!eNULL'
To see it all
openssl ciphers -V ALL openssl ciphers -V ALL:COMPLEMENTOFALL
To get some cathegorizations
openssl ciphers -V LOW openssl ciphers -V MEDIUM openssl ciphers -V HIGH
We could start with ALL
and negate non-PFS ciphers one by one
openssl ciphers -V 'ALL:!aNULL:!eNULL:!RC4:!MD5:!3DES' | grep -v Kx=RSA openssl ciphers -V 'ALL:!aNULL:!eNULL:!RC4:!MD5:!3DES' | grep Kx=RSA | awk '{print $3}'
but it is much more adequate to filter-in PFS-capable exchanges anyhow
openssl ciphers -V 'ECDHE:DHE:kGOST:!aNULL:!eNULL:!RC4:!MD5:!3DES'
let’s also filter out 128-bit ciphers to get 100% key strength
!AES128:!CAMELLIA128
Also Chrome 49 / XP SP3
and Firefox 47 / Win 7 R
we get
Server negotiated HTTP/2 with blacklisted suite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA | ECDH secp384r1 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA | ECDH secp384r1 ==> !ECDHE-RSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA
As a result we got
ECDHE:DHE:kGOST:!aNULL:!eNULL:!RC4:!MD5:!3DES:!AES128:!CAMELLIA128:!ECDHE-RSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA
which gives, with LibreSSL 3.3.1
0x13,0x02 - AEAD-AES256-GCM-SHA384 TLSv1.3 Kx=TLSv1.3 Au=TLSv1.3 Enc=AESGCM(256) Mac=AEAD 0x13,0x03 - AEAD-CHACHA20-POLY1305-SHA256 TLSv1.3 Kx=TLSv1.3 Au=TLSv1.3 Enc=ChaCha20-Poly1305 Mac=AEAD 0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD 0xC0,0x2C - ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD 0xC0,0x28 - ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 0xC0,0x24 - ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 0xCC,0xA9 - ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=ECDSA Enc=ChaCha20-Poly1305 Mac=AEAD 0xCC,0xA8 - ECDHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=RSA Enc=ChaCha20-Poly1305 Mac=AEAD 0x00,0x9F - DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD 0x00,0x6B - DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256 0x00,0x39 - DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 0xCC,0xAA - DHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=DH Au=RSA Enc=ChaCha20-Poly1305 Mac=AEAD 0x00,0xC4 - DHE-RSA-CAMELLIA256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=Camellia(256) Mac=SHA256 0x00,0x88 - DHE-RSA-CAMELLIA256-SHA SSLv3 Kx=DH Au=RSA Enc=Camellia(256) Mac=SHA1 0xFF,0x85 - GOST2012256-GOST89-GOST89 SSLv3 Kx=GOST Au=GOST01 Enc=GOST-28178-89-CNT Mac=GOST89IMIT 0x00,0x81 - GOST2001-GOST89-GOST89 SSLv3 Kx=GOST Au=GOST01 Enc=GOST-28178-89-CNT Mac=GOST89IMIT
Define sane defaults for SMTP (TLS v1.0 but only 256-bit ciphers), even though we define them yet again in Postfix
cp -pi /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.dist vi /etc/ssl/openssl.cnf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.0 MinProtocol = DTLSv1.0 CipherString = ECDHE:DHE:kGOST:!aNULL:!eNULL:!RC4:!MD5:!3DES:!AES128:!CAMELLIA128 Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
and further tune protocols and cipher strings per daemon and overriding the defaults
acceptance tests should return
And if you really want 100/100 for key exchange
openssl dhparam 4096 > /etc/ssl/dhparam2.pem cat /etc/ssl/dhparam2.pem #-rand /dev/urandom vi nginx.conf ssl_dhparam /etc/ssl/dhparam2.pem; ssl_ecdh_curve secp384r1; #ssl_ecdh_curve secp384r1:secp521r1; # prime256v1, secp384r1, secp521r1, X25519, X448
We can affort to have a few WEAK tagged ciphers – we still get 100/100 cipher strength anyway.
# TLS 1.2 (server has no preference) TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39) DH 4096 bits FS WEAK 256 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (0x88) DH 4096 bits FS WEAK 256 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x6b) DH 4096 bits FS WEAK 256 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f) DH 4096 bits FS 256 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (0xc4) DH 4096 bits FS WEAK 256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024) ECDH secp384r1 (eq. 7680 bits RSA) FS WEAK 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028) ECDH secp384r1 (eq. 7680 bits RSA) FS WEAK 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) ECDH secp384r1 (eq. 7680 bits RSA) FS 256 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) ECDH secp384r1 (eq. 7680 bits RSA) FS 256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) ECDH secp384r1 (eq. 7680 bits RSA) FS 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) ECDH secp384r1 (eq. 7680 bits RSA) FS 256 TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa) DH 4096 bits FS 256
You can also check yourself remotely
nmap -sV --script ssl-enum-ciphers -p 443 nethence.com PORT STATE SERVICE VERSION 443/tcp open ssl/http nginx 1.19.6 |_http-server-header: nginx/1.19.6 | ssl-enum-ciphers: | TLSv1.2: | ciphers: | TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 4096) - A | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 4096) - A | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 4096) - A | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 4096) - A | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 4096) - A | TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 4096) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp384r1) - A | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp384r1) - A | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp384r1) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp384r1) - A | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp384r1) - A | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp384r1) - A | compressors: | NULL | cipher preference: client |_ least strength: A
tested with OpenSSL 1.1.1i
in case you absolutely want to disregard the 128-bit cipher with tls13
, you need to tune it there for now
vi /etc/ssl/openssl.cnf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.2 MinProtocol = DTLSv1.2 CipherString = ECDHE:DHE:kGOST:!aNULL:!eNULL:!RC4:!MD5:!3DES:!AES128:!CAMELLIA128 Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 # Options = ServerPreference,NoRenegotiation # CipherString = ALL:!aNULL:!eNULL # PROFILE=SYSTEM # DEFAULT@SECLEVEL=2
and you need to FULLY RESTART NGINX for this to take action
ps auxfww | grep nginx | grep -v grep pkill nginx && nginx ps auxfww | grep nginx | grep -v grep
Cipher suite https://en.wikipedia.org/wiki/Cipher_suite
SSL Server Rating Guide https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide
SSL Labs: Stricter Security Requirements for 2014 https://blog.qualys.com/product-tech/2014/01/21/ssl-labs-stricter-security-requirements-for-2014
RSA and ECDSA hybrid Nginx setup with LetsEncrypt certificates generated through Docker image https://medium.com/hackernoon/rsa-and-ecdsa-hybrid-nginx-setup-with-letsencrypt-certificates-ee422695d7d3
Official portable version of LibreSSL https://github.com/libressl-portable/portable
tls13 API not available yet https://github.com/libressl-portable/portable/blob/master/ChangeLog
SSL Server Test https://www.ssllabs.com/ssltest/
CryptCheck https://tls.imirhil.fr/
testssl.sh https://github.com/drwetter/testssl.sh
SSLyze https://github.com/nabla-c0d3/sslyze
HTTPS Cheat Sheet https://scotthelme.co.uk/https-cheat-sheet/
Cipherli.st Strong Ciphers for Apache, nginx and Lighttpd https://cipherli.st/
Applied Crypto Hardening https://bettercrypto.org/
SSL Configuration Generator https://ssl-config.mozilla.org/
File ssl-enum-ciphers https://nmap.org/nsedoc/scripts/ssl-enum-ciphers.html
openssl-ciphers, ciphers - SSL cipher display and cipher list tool https://www.openssl.org/docs/man1.1.1/man1/ciphers.html
SSL and TLS Deployment Best Practices https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices#23-use-secure-cipher-suites
TLS Cipher String ยท OWASP Cheat Sheet Series https://cheatsheetseries.owasp.org/cheatsheets/TLS_Cipher_String_Cheat_Sheet.html
Mapping OpenSSL Cipher Suite Names to Official Names and RFCs https://www.woolie.co.uk/article/mapping-openssl-ciphers-to-iana-cipher-suite-registy/
A list of recommended cipher suites for TLS 1.2 https://www.peerlyst.com/posts/a-list-of-recommended-cipher-suites-for-tls-1-2-guurhart
SSL Labs Grading Update: Forward Secrecy, Authenticated Encryption and ROBOT https://blog.qualys.com/ssllabs/2018/02/02/forward-secrecy-authenticated-encryption-and-robot-grading-update
[stunnel-users] STUNNEL — How to chose the AES cipher with TLS v1.2 https://www.stunnel.org/pipermail/stunnel-users/2013-February/004112.html
Cipher Security: How to harden TLS and SSH https://www.linuxjournal.com/content/cipher-security-how-harden-tls-and-ssh
ciphers https://www.openssl.org/docs/manmaster/man1/ciphers.html
Security/Server Side TLS https://wiki.mozilla.org/Security/Server_Side_TLS
Recommendations for TLS/SSL Cipher Hardening https://securityboulevard.com/2018/04/recommendations-for-tls-ssl-cipher-hardening/
Recommendations: SSL/TLS Protocols and Cipher Suites https://grok.lsu.edu/Article.aspx?articleid=17596
Recommendations for TLS/SSL Cipher Hardening https://www.acunetix.com/blog/articles/tls-ssl-cipher-hardening/ SSL!
cloudflare’s nginx ssl setup https://github.com/cloudflare/sslconfig/blob/master/conf
ciphers - SSL cipher display and cipher list tool. https://github.com/libressl/libressl/blob/master/src/doc/apps/ciphers.pod
Cipher String Syntax in nginx https://serverfault.com/questions/635189/cipher-string-syntax-in-nginx
CIPHER LIST FORMAT https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT
CIPHER LIST FORMAT https://www.openssl.org/docs/man1.1.1/man1/ciphers.html#CIPHER-LIST-FORMAT
SSL_CONF_cmd_value_type, SSL_CONF_cmd - send configuration command https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html
config - OpenSSL CONF library configuration files https://www.openssl.org/docs/man1.1.1/man5/config.html
x509v3_config - X509 V3 certificate extension configuration format https://www.openssl.org/docs/man1.1.1/man5/x509v3_config.html
we’re better than that https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/TLS_Cipher_String_Cheat_Sheet.md
Transport Layer Security (TLS) Parameters https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
Mapping OpenSSL cipher suite names to IANA names https://testssl.sh/openssl-iana.mapping.html
Security/Cipher Suites https://wiki.mozilla.org/Security/Cipher_Suites
Authenticated encryption https://en.wikipedia.org/wiki/Authenticated_encryption
https://serverfault.com/questions/981397/perfect-ssl-labs-score-with-nginx-and-tls-1-3
https://stanislas.blog/2018/11/how-to-enable-tls-13-nginx/
https://bugs.archlinux.org/task/61871
https://serverfault.com/questions/1023766/nginx-with-only-tls1-3-cipher-suites
https://trac.nginx.org/nginx/ticket/1901
Undocumented openssl.cnf options and PrioritizeChaCha https://blog.germancoding.com/2020/05/30/undocumented-openssl-cnf-options-and-prioritizechacha/
Using TLS1.3 With OpenSSL https://www.openssl.org/blog/blog/2018/02/08/tlsv1.3/
Prefer ChaCha20-Poly1305 in TLS 1.3 with nginx https://blog.pinterjann.is/chacha20-tls13-openssl.html
Unable to configure or disable TLS 1.3 via openssl.cnf https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/1832370
Could not configure TLS1.3 ciphers in OpenSSL 1.1.1 pre4 https://trac.nginx.org/nginx/ticket/1529
Set ciphersuite list order for TLS 1.3 https://trac.nginx.org/nginx/ticket/1878
Guide to Deploying Diffie-Hellman for TLS https://weakdh.org/sysadmin.html