Opened 8 months ago

Closed 8 months ago

#2541 closed defect (invalid)

TLS 1.2 connection on TLS 1.3 only site

Reported by: vp1981@… Owned by:
Priority: major Milestone:
Component: nginx-core Version: 1.25.x
Keywords: tls1.2, tls1.3 Cc: vp1981@…
uname -a: Linux node1.bkoty.ru 6.5.0-zen1-1-zen #1 ZEN SMP PREEMPT_DYNAMIC Tue, 29 Aug 2023 18:39:35 +0000 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.25.2
built with OpenSSL 3.1.2 1 Aug 2023
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --user=http --group=http --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --http-client-body-temp-path=/var/lib/nginx/client-body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-cc-opt='-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -g -ffile-prefix-map=/build/nginx-mainline/src=/usr/src/debug/nginx-mainline -flto=auto' --with-ld-opt='-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=auto' --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-pcre-jit --with-stream --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads

Description

I configured nginx to accept only TLS 1.3 connections and up to version 1.25.2 everything was fine. But since version 1.25.2, both curl and ssllabs show me that a site is accessible with TLS 1.2 as well.

To force the use of TLS 1.3, I used a trick with the OPENSSL_CONF environment variable pointing to a file with the content

openssl_conf = default_conf

[default_conf]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Ciphersuites = TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384
Options = ServerPreference,PrioritizeChaCha

and the following configuration for the site

  listen            443 ssl;
  listen       [::]:443 ssl;
  http2        on;
  server_name  isu.bkoty.ru;

  ssl_session_cache          shared:SSL:10m;
  ssl_session_timeout        10m;
  ssl_password_file          /etc/cert/hosts/isu.ppp;
  ssl_certificate            /etc/cert/hosts/isu.crt;
  ssl_certificate_key        /etc/cert/hosts/isu.key;
  ssl_protocols              TLSv1.3;
  ssl_prefer_server_ciphers  on;
  ssl_ecdh_curve             secp384r1;

To use the OPENSSL_CONF variable I added a line

Environment=OPENSSL_CONF=/etc/nginx/openssl.conf

to the nginx.service file.

Now, to test the connection to the site I ran the command

$ curl -I -v --tlsv1.2 --tls-max 1.2 https://isu.bkoty.ru

and the site responded using the TLS 1.2 protocol. I don't understand why TLS 1.2 is being used (I didn't configure it, right?). Has something changed in nginx regarding how openssl configuration is used?

P.S. Sorry, this might be my second ticket, I didn't manage to write the first one correctly.

Change History (5)

comment:1 by vp1981@…, 8 months ago

It looks like there was a problem with the nginx configuration.

Besides the mentioned configuration I have a "drop" one:

server {
  listen       443 ssl default_server;
  listen  [::]:443 ssl default_server;
  http2        on;
  # server_name  "";

  ssl_reject_handshake on;

  return 444;
}

I thought this would just drop the connection without any other consequences, but I was wrong. For some reason, this configuration somehow downgraded the TLS protocol for other site to TLS 1.2 instead of the directly configured TLS 1.3. When I changed the above configuration to

server {
  listen       443 ssl default_server;
  listen  [::]:443 ssl default_server;
  http2        on;
  # server_name  "";

  ssl_protocols             TLSv1.3;
  ssl_reject_handshake on;

  return 444;
}

the site in question started accepting only TLS 1.3 protocol connections.

I don't understand why this worked before, and why the "drop" configuration now causes the protocol downgrade for other site.

For reference, here is part of my nginx.conf

  #############################################################################
  ### Sites...
  ### For ISU project.
  include /etc/nginx/sites/isu-subdom;
  # ...
  ###
  include /etc/nginx/sites/no-name-response;

and this is isu-subdom:

server {
  listen            443 ssl;
  listen       [::]:443 ssl;
  http2        on;
  server_name  isu.bkoty.ru;

  ssl_session_cache          shared:SSL:10m;
  ssl_session_timeout        10m;
  ssl_password_file          /etc/cert/hosts/isu.ppp;
  ssl_certificate            /etc/cert/hosts/isu.crt;
  ssl_certificate_key        /etc/cert/hosts/isu.key;
  ssl_protocols              TLSv1.3;
  ssl_prefer_server_ciphers  on;
  ssl_ecdh_curve             secp384r1;

  #charset koi8-r;

  #access_log  logs/host.access.log  main;

  include headers;

  if ($badagent) {
    return 444;
  }

  location /.well-known/security.txt {
    alias /srv/http/.well-known/security.txt;
  }

  # ...
  autoindex off;

  location /favicon.ico {
    return        204;
    access_log    off;
    log_not_found off;
  }

  location / {
    index index.html;
  }

  location /styles {
    alias /srv/http/styles;
  }

  # ...

  #error_page  404              /404.html;

  # redirect server error pages to the static page /50x.html
  #
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }

Is this expected behavior?

comment:2 by Maxim Dounin, 8 months ago

See also #2538.

comment:3 by Maxim Dounin, 8 months ago

By default, nginx 1.25.2 accepts connections with TLSv1, TLSv1.1, TLSv1.2, and TLSv1.3 protocols. As such, without an explicit configuration in your default server, all these protocols will be allowed.

At the same time, it is not possible to configure SSL protocols for a name-based virtual SSL server, see here. As such, in a configuration with the default server accepting TLSv1/TLSv1.1/TLSv1.2/TLSv1.3, the virtual name-based SSL server is expected to accept both TLSv1.2 and TLSv1.3. And this is what you are seeing in your tests.

The remaining question is "how it worked before". My best guess is that either the configuration was different (for example, without the default server with ssl_reject_handshake), or nginx actually accepted TLSv1.2 in previous versions as well, but you didn't notice it. Consider reverting nginx to the version you've previously used and testing it again - do you indeed see TLSv1.2 being not available with the same configuration?

Just in case, below are some recommendations based on your configuration for you to consider:

  • Note that OPENSSL_CONF you are using is not expected to force TLSv1.3 anyhow. Rather, it configures Ciphersuites for TLSv1.3 and ServerPreference,PrioritizeChaCha options. Starting with nginx 1.19.4, you can do the same with the ssl_conf_command directive in nginx configuration.
  • Note that ssl_session_cache in a virtual name-based SSL server is useless, as SSL session resumption happens in the default server context. Similarly to ssl_protocols, it should be instead configured in the default server (or at the "http" level, so the configuration applies to all servers).

Overall, it might be a good idea to configure SSL settings at the "http" level, especially if you are using name-based virtual SSL servers. This approach will ensure that SSL settings are correctly set for all servers, and won't suddenly change if you'll change the default server.

Hope this helps.

comment:4 by vp1981@…, 8 months ago

Thanks for the explanations and suggestions!

I implemented your idea to configure SSL at the http level, now everything works fine.

comment:5 by Maxim Dounin, 8 months ago

Resolution: invalid
Status: newclosed

Thanks for the feedback, closing this.

Note: See TracTickets for help on using tickets.