SSL session caching in nginx


Sessions in SSL/TLS have been around since SSL v2. They allow multiple connections to use the same key data to calculate encryption keys for the connection instead of performing a full negotiation to determined the encryption keys. Since they are reusing data previously exchanged securely, a secure connection can be established very quickly. The alternative is to perform the full negotiation for every connection, which is a costly process.

To activate the SSL session cache in nginx, add the following to your nginx.conf:

    worker_processes  4;

    http {
        ssl_session_cache    shared:SSL:10m;
        ssl_session_timeout  10m;
        ssl_ciphers ALL:!kEDH!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ...

This creates a shared cache (shared by all the worker processes) of 10Mb. 1Mb holds approximately 4,000 sessions. The default cache timeout is five minutes, here it’s been increased to ten minutes.

Note that when you have multiple processors available you should use them by increasing the worker_processes parameter to a value not less than the available cores. The SSL handshake is a processor intensive task, so utilising the processors is beneficial.

To reduce the number of handshakes further, increase keepalive_timeout. This allows multiple requests per connection.

    server {
        listen               443;
        server_name          www.nginx.com;
        keepalive_timeout    70;
        ...

Once you have this configured, you can test that it is working by running the following command:

    $ gnutls-cli -V -r HOSTNAME |grep 'Session ID'
    - Session ID: 90:5B:99:E5:...
    - Session ID: 90:5B:99:E5:...
    - Session ID: 90:5B:99:E5:...

Providing all three Session IDs are the same, then SSL session caching is operational.

A final note about using a faster cipher

Finally, note the following line from above:

    ssl_ciphers ALL:!kEDH!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;

This is the nginx default with the addition of !kEDH. This removes the slow DHE-RSA-AES256-SHA cipher from being selected. You can see the list of supported ciphers on you server via:

    $ openssl ciphers
    DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:EDH-RSA-DES-CBC3-SHA:
    EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:
    DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:RC4-SHA:RC4-MD5:RC4-MD5:
    EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:
    EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:
    EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC4-MD5

You can check whiich cipher your site is using via:

    $ openssl s_client -host YOUR_HOSTNAME -port 443

With the nginx defaults you will see the DHE-RSA-AES256-SHA ciper being used:

    New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA

and after the faster AES256-SHA cipher:

    New, TLSv1/SSLv3, Cipher is AES256-SHA

References