Optimize SSL/TLS for Maximum Security and Speed

Optimize SSL/TLS for Maximum Security and Speed

SSL Labs score report: A+

High Goal Setting

Recently we changed our corporate website into a “HTTPS only” version. Most of the content is not secret information, still we have some sensitive areas. The ordering section and downloads, and additional our portal. While some areas were already covered with a lock, we felt it was time to make the jump to cover it all.

Additionally, we believe that we doing everything we can on our website, practicing security hardening ourselves. So that includes buying a SSL certificate, configure our web servers and finally tune it. In this article we share what we learned while doing so.

Nginx Configuration

For the purpose of demonstration, we will show some snippets in this article. While most of it is focused on nginx, the general rules can be applied to others like Apache. In any case, don’t simply copy snippets, but test them carefully and understand what they are doing.

Let’s start hardening and tuning!

Disable old protocols

SSL version 2 and 3 are insecure. Several weaknesses in the last years showed that you should no longer use these. Also for companies who need to be PCI DSS compliant, are enforced to remove support for SSLv3.

# Only allow TLS

 

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Select right ciphers

Ciphers are part of the full conversation, deciding how the connection is initiated and maintained, but also how data is encrypted and protected.

Selecting the right ciphers is not easy. All kind of vulnerabilities showed that selecting a wrong cipher can weaken your security defenses. Instead, use the great page of Mozilla, which helps you selecting the right cipher set, tuned to modern browsers.

# Use specific ciphers and let server decide which one to

use.

 

ssl_ciphers ‘long string of ciphers’;
ssl_prefer_server_ciphers on;

Exotic HTTPS features

Last years several new concepts have been introduced, to make the web a safer place.

Screenshot of HTTPS with HTST, HPKP and forward secrecy

HTTPS configured with HSTS, HPKP and forward secrecy.

Forward secrecy

The easy explanation for this feature: ensure that in the event of a private key is exposed previous recorded messages can not be decrypted. The more technical background is that no additional keys can be gathered, when another key is compromised.

 

OCSP stapling

Instead of just relying on clients checking for a revocation list, we can help saving a lot of bandwidth with OCSP stapling. The server will do the checking instead and stamp it with a recent check. This way the client knows the certificate is still valid.

HTST

HTST, or HTTP Strict Transport Security, helps the browser to save a preferred protocol (HTTPS). This means that after a redirect from HTTP to HTTPS, the browser next time remembers to go directly to HTTPS. This helps with ensuring the right protocol is used while limiting unneeded redirects at the same time.

# Redirect other domains, including www.domain.com
server {
  listen 80;
  index index.html index.htm;
  server_name *.domain.com *.other-domain.com;
  add_header "Cache-Control" "public, max-age=31536000";
  return 301 https://domain.com;
}

See also the previous article about HTST.

Public Key Pinning

HTTP Public Key Pinning, or HPKP is a way to glue a hostname and a public key (of the certificate). This is done at the level of the browser, which has static lists.

Performance

Every second counts on the web. So where possible, allow clients to cache data and do compression.

Compression

First level of performance tuning is sending less data on the line, with the help of file compression. For this the common used gzip module is used, which all modern browsers understand as well.

So we enable gzip, define what gets compressed, how much and how much buffering we use.

# Turn on gzip and disable it for MSIE6

gzip on;
gzip_disable “msie6”;

 

# Also zip proxied requests
gzip_proxied any;
# Compression level, only do zipping if minimum length is 1100 bytes
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
# Define gzip for specific types (we don’t zip fonts)
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Enabled (insert Vary: Accept-Encoding header)
gzip_vary on;

Caching

While compression is great, it is even better if we limit the amount of requests to our server. We want after all security AND performance.

While browsers are already smart in knowing which files have been changed, it still sends out requests.

Screenshot of Firefox network analyzer showing caching of objects

Firefox network analyzer showing caching of objects

The orange triangles show that requests have been done and returned with a 304 (not modified). The green circle is a successful 200 response (Ok) of the main test page.

So we want to reduce the amount of requests to a bare minimum. So we picked an expire date of 1 week. Long enough for normal users which return on a regular basis, while not caching entries too long. After all, when releasing new content, we want to push that to the client.

location ~* \.(?:css|js) {
   root /data/website/;
   expires 1w;
   add_header Cache-Control public;
   add_header Vary Accept-Encoding;
   access_log off;
 }

This configuration sets both an encoding (for compression) and sets caching to 1 week. That means that only once a week a new copy of the file is retrieved, unless the user forces a new download (CTRL+F5). Since we don’t care about logging the request of CSS and Javascript files, we don’t log it. Another slight performance win in that area as well.

HTTPS tuning

When it comes to HTTPS, a slow connection is usually caused due to the slow handshake. The main reason is network latency, in combination with the amount of packets needed to finish the handshake. The more packets, the longer it takes. The HTTP/2 protocol can help

Enable HTTP/2

Enabling HTTP/2 is easy, just add it to the listen statement. Note, you need a recent version of nginx.

listen 443 http2;
listen [::]:443 default ipv6only=on http2;

Conclusion

After all this tuning, we can learn a few things:

SSL versus TLS

SSL is old and insecure. Therefore version 2 and 3 should be disabled. TLS is fine, with TLSv1.1 and TLSv1.2 being preferred. TLSv1 might be still needed, for older browsers or some tooling (e.g. some versions of wget).

Use HTTP2

Make use of the HTTP/2 protocol to enhance the speed of HTTPS connections.

Security AND Performance

Instead of security battling against performance, the combination is possible. Test your SSL configuration with SSL Labs. Use the GZIP module for nginx for maximum compression. Finally, use website speed testing tools like Pingdom to determine any bottlenecks.

Other resources

Submit certificate key pinning: https://hstspreload.appspot.com/

Chrome

Internal link for Chrome to check HTST database: chrome://net-internals/#htst

Lynis Enterprise

Lynis Enterprise screenshot to help with system hardening

This blog post is part of our Linux security series and the mission to get Linux and Unix-based systems more secure.

Does system hardening take a lot of time, or do you have any compliance in your company? Have a look at Lynis Enterprise.

Or start today with the open source security scanner Lynis (GitHub)


Leave a Reply

Your email address will not be published. Required fields are marked *