Nginx and Secure SSL Configuration

It turns out that it is kind of tricky to get a perfect high security SSL configuration. I will give you configuration options and I will explain the reasons for which they are chosen.

SSL Versions

SSLv2 is insecure and you also need to disable SSLv3, as TLS 1.0 suffers a downgrade attack, allowing an attacker to force a connection to use SSLv3 and therefore disable forward secrecy. SSLv3 also allows exploiting the POODLE attack which is another reason to disable it.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;


The cipher suites that provide the best Forward Secrecy are the ones that use an ephemeral form of the Diffie-Hellman key exchange. The main disadvantage is their overhead which is improved by using their elliptic curve variants.

The following options are recommended by the Mozilla Foundation. If you are not looking for backwards compatibility the following is the recommended modern configuration that is compatible with: Firefox 27, Chrome 22, IE 11, Opera 14 and Safari 7.


For services that don't need compatibility with legacy clients (WinXP), but need to support a wide range of clients, the following less recommended configuration is compatible with: Firefox 1, Chrome 1, IE 7, Opera 5 and Safari 1.


And finally if for some crazy reason you would really like to support legacy systems like Windows XP and Internet Explorer 6, this is the NOT RECOMMENDED ciphersuite which will work with all clients back to Windows XP/IE6. It should only be used as a last resort.


Forward Secrecy and DHE Parameters

Forward Secrecy is a property of a secure communication that guarantees that even if an attacker gets a hold of the server's private key he would not be able to decrypt any past recorded communications. This is done by performing a Diffie-Hellman key exchange, which guarantees that the symmetric key of a communication (session key) is never transmitted over the connection and cannot be acquired from a third party. Because this key is only used for a limited amount of time it is called Ephemeral. The server's private key is then used to sign the negotiated session key and thus protecting from a MITM attack, which a standard Diffie-Hellman key exchange is vulnerable to. Nginx relies on an input parameters from OpenSSL for the Ephemeral Diffie-Hellman (DHE), but the OpenSSL defaults only provide a 1024-bit key for the key-exchange. Since often you will be using a 2048-bit certificate (or higher), DHE clients will use a weaker key-exchange than non-ephemeral DH clients. To set a stronger DHE parameter we generate an 4096-bit key and supply it to Nginx:

cd /etc/ssl/certs
openssl dhparam -out dhparam.pem 4096

And then in your Nginx configuration:

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Additional Options

When choosing a cipher during an SSL or TLS handshake, normally the client's preference is used. If this directive is enabled, the server's preference will be used instead.

ssl_prefer_server_ciphers on;

SSL operations consume a lot of CPU resources. They can be optimised in the following way:

worker_processes auto;
http {
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    server { 
        keepalive_timeout   70;

An extra level of security can be achieved by enabling HTTP Strict Transport Security (HSTS). This is done by appending an extra header to each response signalling the browser that content from this domain should always be loaded via HTTPS.

server {
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Testing your SSL configuration

The SSL Labs have an excellent tool for testing you server configuration. I would highly recommend doing that after you've set up your server. If you get an A, then you are good to go!

Last updated
DownloadPlain text