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?

  • 1
    Have you checked that there isn't any other ssl_protocols definitions anywhere in nginx config? – Tero Kilkanen Sep 10 '14 at 22:58
  • Yep, It's possible ro specify different protocols for each server block. I can't replicate your problem. I recently tested your scenario nginx and it's working. As other says, please checks whether there isn't any other ssl_protocols. – masegaloeh Sep 10 '14 at 23:20
  • Scott and I worked on this yesterday and I can confirm my NGINX 1.6.1 version does exactly the same. NGINX uses only the protocols from the first block, but the ciphers from the correct block. – user241923 Sep 11 '14 at 12:05
  • I've checked /etc/nginx/nginx.conf and /etc/sites-available/default.conf, these are the only 2 config files present and match the scenario above. – Scott Helme Sep 11 '14 at 12:44
  • 1
    I added an answer so that people don't have to read through all these comments. – peedee Jan 22 '17 at 4:24

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;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.