There has been a lot of discussion recently about Perfect Forward Secrecy (PFS) and the benefits it can bring you, especially in terms of any kind of traffic sniffing attack. Unfortunately setting this up I found very few guides telling you exactly what you need to do.
The downside to PFS is that it uses more CPU power than other ciphers. This is a trade-off between security and cost.
Importantly, this guide is for sites that already have SSL setup with a valid certificate.
The key to PFS is the cipher: ECDHE – Elliptic Curve Diffie Hellman Encryption.
But before we configure the cipher we need to add some “randomness” to our Key. I will assume your key is in the mywebsite.com.pem file, as is compatible with both stud and nginx:
$ openssl dhparam -rand - 1024 >> mywebsite.com.pem
Note that this pem file must already exist, and is the file you concatenated together with your certificates and private key from whoever signed your SSL certificate request. Afterwards it will have a section at the end labelled -----BEGIN DH PARAMETERS-----.
Now it’s a simple matter of enabling the right ciphers in nginx or stud. One problem I had doing this is the version of stud shipped with Ubuntu 12.04 doesn’t support ECDHE, despite the version of openssl supporting it. So I had to download and install a new version of stud. I’m not sure about nginx, but you may need to do the same there.
First though let’s test if we can get everything working just using openssl. You’ll want two windows open for this. In one window create a server:
$ openssl s_server -accept 8888 -cert mywebsite.com.pem -pass stdin -cipher ECDHE-RSA-RC4-SHA (you may need to press enter to get it to say "ACCEPT")
And in another window connect to it with a client:
$ openssl s_client -connect 127.0.0.1:8888 -cipher ECDHE-RSA-RC4-SHA
If it works fine, you will get lots of output about the certificate and the current connection, and anything you type in the client will appear in the server.
If it has not worked it will exit after showing something like:
CONNECTED(00000003) 139923546220192:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:724: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 90 bytes --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE ---
Now we know our .pem file works, let’s try again with stud. In our “server” window run:
$ stud --prefer-server-ciphers --ciphers='ECDHE-RSA-RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH' -f 127.0.0.1,8888 -b 127.0.0.1,8081 mywebsite.com.pem
This time we have added more ciphers so that clients that don’t support ECDHE can still connect. Now in our “client” window use the same openssl s_client command and ensure you can connect. Try a second time with the flag -cipher RSA to ensure that lesser clients can still connect.
Now you have all the pieces working. Just modify your start script for stud (we use runit for this, but there are plenty of other ways). Note we use a slightly longer cipher suite as recommended by SSLLabs and Qualys:
For Nginx all you need to do is add the following line to your configuration for your server:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+RC4:EDH+aRSA:EECDH:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
Remember to test nginx/stud with openssl s_client once you have restarted it!