Opened 5 months ago

Last modified 3 months ago

#2661 new defect

ssl_verify_client can't configured with result of map operation

Reported by: scio-nescio@… Owned by:
Priority: major Milestone:
Component: nginx-module Version: 1.22.x
Keywords: Cc:
uname -a: PREEMPT_DYNAMIC Debian 6.1.90-1
nginx -V: nginx version: nginx/1.22.1
built with OpenSSL 3.0.8 7 Feb 2023 (running with OpenSSL 3.0.13 30 Jan 2024)
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-AoTv4W/nginx-1.22.1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-mail_ssl_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-http_geoip_module=dynamic --with-http_image_filter_module=dynamic --with-http_perl_module=dynamic --with-http_xslt_module=dynamic --with-mail=dynamic --with-stream=dynamic --with-stream_geoip_module=dynamic

Description

PREEMPT_DYNAMIC Debian 6.1.90-1

Using nginx to terminate TLS connections for different domains

I have the following configuration, to server different domains with individual TLS configuration:

stream {
  map $ssl_preread_server_name $name {
    default           server_one;
    two.example.org   server_two;
    three.example.org server_three;
  }  
  
  map $ssl_preread_server_name $authen_cert {
    default           "/etc/nginx/public.cert";
    two.example.org   "None";
    three.example.org "None";
  }  
  
  map $ssl_preread_server_name $svc {
    default           "on";
    two.example.org   "off";
    three.example.org "off";
  }

  server {
    listen 127.0.0.1:3128 ssl;
    ssl_protocols TLSv1.2 TLSv1.3; 
    ssl_certificate /etc/letsencrypt/live/$name/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$name/privkey.pem;
    ssl_client_certificate $authen_cert ;
    ssl_verify_client $svc ; <==== error happens here
    proxy_pass 127.0.0.2:3128;
  }    
}

I receive the error-message: invalid value "$svc" in /etc/nginx/sites-enabled/default:27//.

So I can't use the associated configuration to ssl_client_certificate, which renders my configuration unusable for targets needing cert auth.

Unfortunately if-conditions do also not work here, even, when I can read in documentation, that if-conditions should be available in server blocks.

Change History (3)

comment:1 by Roman Arutyunyan, 5 months ago

ssl_verify_client does not support variables:

https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_verify_client

And even if it did, ssl preread happens after ssl termination anyway, so you wouldn't be able to use ssl_preread_server_name at ssl phase.

comment:2 by scio-nescio@…, 5 months ago

why is it named PREread, when it happens AFTER termination?
I thought, that it reacts on the SNI Hello, so that the right configurations for TLS Termination could be identified, based on the hostname

comment:3 by Roman Arutyunyan, 4 months ago

why is it named PREread, when it happens AFTER termination?

It can preread ssl itself if there's no ssl termination, or it can preread application protocol after ssl termination.

If you want to have more flexibility with ssl termination, ssl preread etc, try using pass directive:

https://nginx.org/en/docs/stream/ngx_stream_pass_module.html

You can preread ssl in one server and then switch to other servers depending on the result of preread.

Also, it looks like in your particular case you can just use virtual servers in stream without preread at all.

Note: See TracTickets for help on using tickets.