13

I recently changed my nginx config to redirect all http traffic to https (and all www traffic to no-www).

Would it make sense to also add add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; to my server blocks as well? Or that's unneeded since I'm already redirecting all traffic? Would be great to know the pros (and cons, if any).


In case relevant, my current virtual host configuration is:

server {
    server_name example.com www.example.com;

    listen 80;

    return 301 https://example.com$request_uri;
}

server {
    server_name www.example.com;

    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/cert_chain.crt;
    ... other SSL related config ...

    return 301 https://example.com$request_uri;
}

server {
    server_name example.com;

    listen 443 ssl;
    ... other SSL related config ...

    ... remaining server configuration ...
}
Hassan Baig
  • 2,033
  • 11
  • 27
  • 47

3 Answers3

23

HSTS tells the browser to always use https, rather than http. Adding that configuration may reduce the need for forwarding from http to https, so it may very slightly increase website performance and very slightly decrease server load.

For reference, here's the security headers I use on my Nginx based websites. I save this to a single file and include it from all servers that need it, including http and https servers. It allows some common resources like Google and Facebook to load.

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self' www.google-analytics.com ajax.googleapis.com www.google.com google.com gstatic.com www.gstatic.com connect.facebook.net facebook.com;";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "origin";

Clarification

You still need the http to https redirection in place.

Tim
  • 30,383
  • 6
  • 47
  • 77
  • 1
    Okay, good answer but it creates one confusion for me. I.e., would I need to do away with the redirection going on in my nginx config? I'm now confused as to what the final config would look like. Would be great if you could add a bit more illustration to your answer. – Hassan Baig Sep 21 '17 at 22:32
  • 2
    The best practice is to use both redirect and HSTS. Redirect makes sure that first-time visitors to your site get forwarded to a TLS connection. HSTS makes sure that browsers won't even try to connect via HTTP, which makes things more secure. You should add Tim's directives to your `server` block for the TLS connections (port 443). – Tero Kilkanen Sep 21 '17 at 22:35
  • I never said to remove redirection. You want both. – Tim Sep 21 '17 at 22:40
  • @TeroKilkanen: and like you advised previously, I should add these headers under all blocks using listen `443 ssl;`, or just the one containing the main configuration? – Hassan Baig Sep 21 '17 at 22:47
  • 1
    Put the directives into a single file, include them from every server block - not just the https servers, include the http servers. – Tim Sep 21 '17 at 23:28
  • Since http is being redirected to https in its entirety, wouldn't just having it in https-related server block(s) suffice? – Hassan Baig Sep 21 '17 at 23:46
  • It's not really important either way. Even if it's just in your main server block that's fine. – Tim Sep 22 '17 at 00:50
  • 1
    Your `max-age` of 30 days (2592000) makes it so that your `preload` directive doesn't do anything. [`preload` requires a `max-age` of at least 1 year (31536000).](https://hstspreload.org/) – Maximillian Laumeister Sep 20 '20 at 02:35
  • Thanks @MaximillianLaumeister, fixed. – Tim Sep 20 '20 at 08:04
8

The accepted answer is great but has become outdated and has a flaw that I have found while researching it line-by-line.

The duration of the HSTS header must be at least three months to satisfy security requirements. I used the following in my security headers snippet to get an A+ on the SSL test:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

Secondly, use of X-Frame-Options is deprecated (and was never supported by many/most major browsers). The current standard (ie implemented in all major modern browsers) is is Content-Security-Policy (CSP).

add_header Content-Security-Policy 'frame-ancestors https://mywebapp.mywebsite.example';

As is evident from the example CSP headers will have to be set on a per-site basis (barring clever regex/etc that I haven't seen yet).

Patrick Mevzek
  • 9,273
  • 7
  • 29
  • 42
2

I would suggest specifying the always parameter in add_header to include this header for the internally generated error pages as well.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

As well, add the preload directive to the response header so you can later add your website to the preload list

druss
  • 141
  • 2