SSL Handshake negotiation on Nginx terribly slow

I am using Nginx as a proxy to 4 apache instances. My problem is that SSL negotiation takes a lot of time (600 ms). See this as an example: http://www.webpagetest.org/result/101020_8JXS/1/details/

Here is my Nginx Conf:

user www-data;
worker_processes  4;


events {
    worker_connections 2048;
    use epoll;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    access_log  /var/log/nginx/access.log;
    sendfile        on;
    keepalive_timeout  0;
    tcp_nodelay        on;
    gzip  on;
    gzip_proxied any;
    server_names_hash_bucket_size 128;


}

upstream abc {
     server 1.1.1.1 weight=1;
     server 1.1.1.2 weight=1;
     server 1.1.1.3 weight=1;


 }


server {
    listen   443;
    server_name  blah;

    keepalive_timeout 5;

    ssl  on;
    ssl_certificate  /blah.crt;
    ssl_certificate_key  /blah.key;
    ssl_session_cache  shared:SSL:10m;
    ssl_session_timeout  5m;
    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;

    location / { proxy_pass http://abc;

                 proxy_set_header X-Real-IP  $remote_addr;
                 proxy_set_header Host $host;
                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    }

}

The machine is a VPS on Linode with 1 G of RAM. Can anyone please tell why SSL Hand shake is taking ages?


Solution 1:

You need to disable "ephemeral diffie-hellman" ciphers. Browsers don't use them anyway, but openSSL will when used with tools like cURL or apachebench. So I am betting that webpagetest.org is using them.

See this thread for more details.

I personally use these settings in nginx to force the fastest-but-still-secure SSL ciphers based on the server's preferences, and not the browsers:

Update 2014-01-13: This advice has changed given recent attacks on RC4, browser updates which protect against BEAST, and the more widespread availability of TLS v1.2 in clients and servers.

Updated 2015-10-16: current nginx TLS settings 2015-10-16 as recommended by CloudFlare. Please check the preceeding link for updates, as TLSv1 will likely be removed from the recommended configuration at some point. The current settings disable SSLv3 and RC4 in accordance with current best practice and the latest PCI-DSS as of this date.

ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers                 EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers   on;

This supersedes the earlier advice in this answer, which has been removed to avoid confustion.

Solution 2:

You may not have a good entropy source. Does /dev/urandom exist? If not Nginx will block on reading /dev/random.

What is the size of your key? Longer is slower.

Try straceing the processes to see what they are doing.