Can nginx use different SSL protocols in different server blocks?

I'm trying to setup a hostname to demonstrate a poor SSL config and I'm having some issues. I can specify some bad cipher suites, but nginx seems to ignore the protocol selection.

server {
    listen 443 spdy ssl;
    keepalive_timeout 70;
    server_name example.co.uk;
    client_max_body_size 10M;

    ssl_certificate /path/to/ssl.crt;
    ssl_certificate_key /path/to/ssl.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ...
}

server {
    listen 443 spdy ssl;
    keepalive_timeout 70;
    server_name weak.example.co.uk;
    client_max_body_size 10M;

    ssl_certificate /path/to/weakssl.crt;
    ssl_certificate_key /path/to/weakssl.key;
    ssl_protocols SSLv3;
    ...
}

Nginx can use the different cipher suites I have specified, but seems to use the protocols from the first server block across the board such that weak.example.co.uk has TLSv1/1.1/1.2 and no SSLv3 support.

Is it possible to specify different protocols for each server block?


This seems to be a bug in nginx. I just had this now, took me a while to figure it out.

It's always only using the ssl_protocols directive from the first server block. In my case I have many virtual servers running on the same instance, so I used the nginx -T command to display the full combined config to figure out which server block was the "first" since I have split it up into many separate config files.

At time of writing I'm trying this on Ubuntu 14.04.5 with nginx installed from the ondrej/nginx PPA. Specifically I'm running nginx 1.10.2 built with OpenSSL 1.0.2j.

Output of nginx -V

nginx version: nginx/1.10.2
built with OpenSSL 1.0.2j  26 Sep 2016
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --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-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_spdy_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-8xB1_y/nginx-1.10.2/debian/modules/nginx-auth-pam --add-dynamic-module=/build/nginx-8xB1_y/nginx-1.10.2/debian/modules/nginx-dav-ext-module --add-dynamic-module=/build/nginx-8xB1_y/nginx-1.10.2/debian/modules/nginx-echo --add-dynamic-module=/build/nginx-8xB1_y/nginx-1.10.2/debian/modules/nginx-upstream-fair --add-dynamic-module=/build/nginx-8xB1_y/nginx-1.10.2/debian/modules/ngx_http_substitutions_filter_module

  1. Check your configuration is statically validated with nginx -t
  2. Check your configuration is dynamically validated by monitoring an error log defined at main level while issuing a reload (either service nginx reload or kill -SIGHUP <nginx master PID>)
  3. Create a test location in each server (see below)
  4. Ensure your nginx is built with the SNI extension (normally yes if yo uuse a pre-built package)
  5. Ensure the right server is being used: if the domain name selection through SNI fails or if SNI is not available, nginx will fall back to the default server to serve content. Default server is, unless explicitely specified otherwise, the first found in the configuration file.
  6. Ensure browser cache is cleaned-up (and that any cache whatsoever in-between server and browser gets updated/is purged)

If a wrong certificate was to be presented (no SNI or wrong server selection), you would normally get a certificate warning since there would be a mismatch between the requested domain name and the one set for the certificate.

This will display the protocol being used by the current connection:

location /SSLProtocol {
    return 200 $ssl_protocol;
}