Nginx – Fixing TLS 1.3 Issues on Nginx 1.21 with OpenSSL 1.1.1n

nginxopensslssl

I have nginx (1.21.6) running with openssl 1.1.1n on a Debian 11 server.
Although I followed many tutorials and looked at multiple questions in this forum about this topic, I can't get TLS 1.3 working.
The output of nginx -V:

nginx version: nginx/1.21.6
built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
built with OpenSSL 1.1.1k  25 Mar 2021 (running with OpenSSL 1.1.1n  15 Mar 2022)
TLS SNI support enable

I upgraded nginx to the mainline version because I wasn't able to get TLS 1.3 working in previous versions, too. It's very strange…
Openssl definitely supports TLS 1.3. I tested it via openssl s_client -tls1_3 -connect www.cloudflare.com:443 which worked well.
Here my ssl.conf file of nginx which I included in each of my nginx servers (certificates are included separately in the server sections):

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;  # about 40000 sessions
ssl_session_tickets off;

ssl_stapling on;
#ssl_trusted_certificate /pfad/bundle.ca.pem;
ssl_stapling_verify on;

ssl_dhparam /etc/nginx/dhparams.pem;

ssl_ecdh_curve X448:secp521r1:secp384r1;


ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384: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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=31536000;preload;includeSubDomains" always;

The Qualys ssltest of my sites doesn't however show that I use TLS 1.3 on my server. Also, Chrome browser shows that it connects via TLS 1.2.
Even if I remove the TLSv1.2 directive from my ssl.conf and leaving only TLSv1.3, it connects still via TLS 1.2.

There is nowhere else a ssl_protocolsdirective in any other configuration file of nginx. I checked that via nginx -T.

I am really running out off ideas…..
Can anyone help me?

EDIT:
Somehow, nginx doesn't seem to react on the ssl_protocols and the ssl_ecdh_curve directive properly. E.g., when I delete the ssl_ciphers from my configuration (as @drookie suggested in his comment), TLS 1.0 and TLS 1.1 seem to be supported by my server although I set ssl_protocols TLSv1.3 TLSv1.2;. Similarly, according to Qualys ssltest, secp256r1 is supported, although I don't have this curve in my configuration of ssl_ecdh_curve (nor prime256v1). It seems to me as if something overwrites my settings in the ssl.conf file.
I am using acme.sh for getting my certificates.
grep -R 'ssl_protocol' /etc/* only gives the line in ssl.conf with ssl_protocols TLSv1.3 TLSv1.2;.
I have no idea what could cause the interference/overwriting…

Best Answer

After many further tests and much reading, I finally found a solution. I had to write the ssl configuration in the http block, not in the server blocks of my nginx configuration. This worked, however, only if I copy the directives from my ssl.conf file explicitly to the http block in my nginx.conf (otherwise nginx -t outputs

nginx: [emerg] invalid number of arguments in "include" directive in /etc/nginx/nginx.conf:33
nginx: configuration file /etc/nginx/nginx.conf test failed

for some reason).

Hence, my http block of nginx.conf looks now as follows:

http {

  ...
 
    ssl_dhparam /etc/nginx/dhparams.pem;
    
    ssl_ecdh_curve X448:secp521r1:secp384r1;
    
    ssl_protocols TLSv1.3 TLSv1.2;
   ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';

   ...

    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

I don't know why these ssl settings have to be included/pasted in the http block rather than in each server block..... But it works and TLS 1.3 is enabled!