In a post-Snowden world, it’s not unreasonable to ask that every site consider deploying “all HTTPS, all the time,” even if just to troll the guys who really want to track what videos I’m watching on Youtube. Here’s how the process breaks down, based on my research and experience. This is not a guide, but a general overview of the state of the art.
Performance was a major reservation I had going into this. So I’m happy to say: SSL/TLS is not only inexpensive, it’s ridiculously cheap. In my case, CPU load increase was on the order of 1%, which is a rounding error. Memory usage might have gone up by a couple KB per connection, and there was no noticeable increase in network overhead. In an end-to-end test, a browser with a cold cache actually loaded and rendered secure pages in (statistically speaking) the same amount of time. On the server side: visually it’s impossible to tell from perf graphs when SSL was enabled. Serving > 6 million hits a month.
There are a couple of things needed to achieve this transparent performance level while still achieving high security, and it is almost entirely configuration-dependent with very little having to do with the application itself.
SSL and TLS support an abbreviated handshake in lieu of a full one when the client has previous session information cached. The full handshake takes two roundtrips (plus one from the TCP handshake), but session resumption can save the server from doing an RSA operation for the client key exchange, as well as a roundtrip. But the big win is the reduction of a roundtrip.
Here is where things start to get weird. There’s at least two forms of session resumption. The session identifier method is baked into SSL and is therefore supported by default – enable this on the server and it should Just Work. The one issue with this is that the server must maintain a session cache. Worse, if you have multiple nodes in the backend you need to either move this session cache into a shared pool or implement some kind of session affinity (urgh). Or perhaps you could do something even stupider and have SSL terminate at your load balancer, defeating the purpose of having a loadbalancer.
Luckily, TLS has an optional extension (described in RFC 5077) that makes the client store the session resumption data, including the master secret that was negotiated and the cipher. This session ticket is further encrypted and readable only by the server to prevent tampering. In short, implementing TLS session tickets as a resumption protocol gives you the best of both worlds – a faster, abbreviated handshake without requiring the server to cache anything. Unfortunately this is an optional extension to TLS, so it is not supported by all clients and servers, and a pool of servers needs to be configured properly so they can share tickets by using a common encryption key (unless you have session affinity, in which case it doesn’t matter).
Most certificates require an intermediate certificate to be presented along with them. There could even by several intermediates. Ensure the following:
1) Send all required certificates to validate the chain. If you don’t, things will probably still work because browsers will tolerate anything short of genocide, but they’ll probably do a DNS/TCP/HTTP dance in the middle of your TLS handshake to some other server to grab the certificate, which is obviously no good.
2) Don’t send any extraneous certificates. Besides the obvious slowdown from sending unnecessary data, you *might* in some cases cause an extra roundtrip if you overflow your TCP window and end up having to wait for an ACK before sending more data. So yeah, fewer packets matter here.
OCSP is the Online Certificate Status Protocol. When a client receives the server’s certificate, it normally connects to the certificate authority to ask if the certificate has been revoked. You can save the client a roundtrip to the CA server if you enable the OCSP stapling extension, in which the server periodically connects to the CA to perform the OCSP check itself, then staples this response to the client during the handshake.
This works because the CA’s response is both time-stamped and signed. Clients can be assured that the OCSP response has therefore not been tampered with, nor can it be used in a primitive replay attack since it has an expiration tied to its validity.
There are some aggravating issues here. One is that OCSP stapling only allows one response to be stapled at a time, which is problematic for certificate chains and will probably end with the client making its own OCSP calls anyway. Another is that OCSP responses can be relatively heavy (like 1KB-ish), which combined with the certificates themselves can overflow the TCP window and cause a roundtrip for ACKs, as mentioned above.
This part can get filled with conjecture and hypotheticals pretty quickly, but basically you have two choices to make:
1) Cipher: A stream cipher like RC4 is fast and doesn’t require padding; this saves bytes on the wire. A block cipher like AES will need padding bytes, but may be more secure. AES-256 is overkill for a 1024-bit public key, but that’s not really a concern since most keys are 2048-bit now.
2) Key exchange: RSA or DHE+RSA? With ephemeral Diffie-Hellman support you can enable Perfect Forward Secrecy, which prevents recorded traffic in the past from being decrypted even if the private key is compromised. This is really powerful and really secure, but it also breaks debugging tools like Wireshark since having the private key doesn’t help you decrypt the traffic. You’ll also handshake at about half the speed of pure RSA.
The reality is that it’s more likely you’ll get pwned by some buffer overflow or Heartbleed-type bug than have someone factor your key, so keep this in mind when selecting your key exchange algorithm and cipher.
You may need HSTS (HTTP Strict Transport Security) if you have concerns about SSLStrip vulnerabilities. SSLStrip is a man-in-the-middle attack in which the MITM silently redirects requests to non-HTTP pages and then simply copies the transmitted plaintext data. You can implement “HSTS” at the application level selectively by detecting and forwarding to the HTTPS version of your page. But if you are doing this nonselectively, why write more code to do something slower higher up in the stack? A lack of protection at both the application and protocol level will result in fun things like this though: https://codebutler.com/firesheep/
Older browsers like IE 6/7/8 screw everything up and I don’t think they even support TLS; you can either support IE 6 / Windows XP or your connection can be secure.
There’s some moderate, but not insurmountable, IT overhead to enabling SSL/TLS. Apache and Nginx support SSL/TLS either out of the box or via easily enabled modules, so it isn’t hard to set them up and configure them to use OpenSSL. But configuring the options as explained above is paramount. So is keeping OpenSSL and other components up to date.
You also need to remember to renew and swap out expiring certs, as well as securely store and back up private keys, cert signing requests, passwords and certificate authority information as well. This is because in (one|three|five) years, it’ll be time to remove the expired certificate and deploy a new one, so you better A) remember where you got your certificate; B) remember how to log in and buy, request, and obtain a new one; and C) test, deploy, and restart your services using the new certificate.
You should enable SSL. It’s not that hard, performance is a non-issue, and you can buy a cert for about $15 a year. Put a date on your calendar to renew it.