Nginx with only TLS1.3 cipher suites
I am trying to configure Nginx to use only TLS1.3 with 2 ciphers: TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256.
So, I tried this configuration:
ssl_protocols TLSv1.3;
ssl_ciphers TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256;
But nginx -s reload errors out with
nginx: [emerg] SSL_CTX_set_cipher_list("TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256") failed (SSL: error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match)", "operationName": "Default", "category": "Default"}
Looks like I need to append at least one non-TLS1.3 cipher to make the config work. I tried various such combinations and they worked. One of them is:
TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
Why is it so? I think it's happening because OpenSSL itself doesn't accept the original ciphersuite string. I am using OpenSSL-1.1.1g.
root@2ed6cae6e062:/azure/appgw# openssl ciphers -v TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256
Error in cipher list
140686067873536:error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match:ssl/ssl_lib.c:2558:
There are some useful links I came across but couldn't figure out how to achieve what I want - using only TLS1.3 ciphersuites.
https://forum.nginx.org/read.php?2,284909,284914#msg-284914
https://trac.nginx.org/nginx/ticket/1529
https://wiki.openssl.org/index.php/TLS1.3#Ciphersuites
Solution 1:
I found the answer in the provided links. All the answers by Maxim Dounin are valuable. You should provide a cipher that makes SSL_CTX_set_cipher_list
happy and then force the list of ciphers using the ssl_conf_command Ciphersuites
directive.
ssl_protocols TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
ssl_prefer_server_ciphers on;
OpenSSL version :
# openssl version
OpenSSL 1.1.1d 10 Sep 2019
Note that TLSv1.3 ciphers are enabled by default.
# openssl ciphers -v ECDHE-ECDSA-AES256-GCM-SHA384
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
Using a script proposed at https://superuser.com/a/224263 and particularly the updated version at https://gist.github.com/jahir/23c4202eee12e377ef3acf1dcdc7c776 I checked the above configuration.
$ ./test_ciphers.sh <put IP here>:443
Using OpenSSL 1.1.1k 25 Mar 2021.
Using tls1_1
Testing ECDHE-ECDSA-AES256-SHA ... NO (tlsv1 alert protocol version)
...
Using tls1_2
Testing ECDHE-ECDSA-AES256-GCM-SHA384 ... NO (tlsv1 alert protocol version)
...
Using tls1_3
Testing TLS_AES_256_GCM_SHA384 ... YES
Testing TLS_CHACHA20_POLY1305_SHA256 ... YES
Testing TLS_AES_128_GCM_SHA256 ... YES
Script included below for reference.
#!/usr/bin/env bash
CIPHERS='ALL:eNULL'
DELAY=${2:-0.1}
SERVER=${1:?usage: $0 <host:port> [delay, default is ${DELAY}s] [ciphers, default is ${CIPHERS}]}
MAXLEN=$(openssl ciphers "$CIPHERS" | sed -e 's/:/\n/g' | awk '{ if ( length > L ) { L=length} }END{ print L}')
echo Using $(openssl version).
declare -A TLSMAP=( [tls1_1]=cipher [tls1_2]=cipher [tls1_3]=ciphersuites )
for tlsver in "${!TLSMAP[@]}"
do
echo "Using $tlsver"
ciphers=$(openssl ciphers -$tlsver -s "$CIPHERS" | sed -e 's/:/ /g')
for cipher in ${ciphers[@]}
do
in=$(openssl s_client -$tlsver -${TLSMAP[$tlsver]} "$cipher" -connect $SERVER </dev/null 2>&1)
if [[ "$in" =~ ":error:" ]] ; then
result="NO ($(echo -n $in | cut -d':' -f6))"
else
if [[ "$in" =~ "Cipher is ${cipher}" || "$in" =~ "Cipher :" ]] ; then
result='YES'
else
result="UNKNOWN RESPONSE\n$in"
fi
fi
printf 'Testing %-*s ... %s\n' "$MAXLEN" "$cipher" "$result"
sleep $DELAY
done
done