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? Sep 10, 2014 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, 2014 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, 2014 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. Sep 11, 2014 at 12:44
  • 1
    I added an answer so that people don't have to read through all these comments.
    – peedee
    Jan 22, 2017 at 4:24

3 Answers 3


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
    Still running into this in nginx 1.24.0
    – aGuegu
    Apr 27, 2023 at 5:16
  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;

IMHO, this is a bug in nginx - the Client Hello packet contains the SNI which can be extracted to find the virtual server block before responding with the server hello and the list of supported TLS protocols

I have a working patch - if someone is interested - i can publish it.

  • Have you submitted the patch to Nginx developers?
    – CDuv
    Aug 23, 2023 at 23:59
  • 1
    I haven't , until now - I will get the process started to submit the patch Aug 30, 2023 at 5:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .