I've been playing Legend of Zelda (a lot) lately on the Nintendo Switch. (So fun!) One of the things I am great at in that game (dare I say it) is avoiding the bad guys. Fighting them gives me a crazy amount of anxiety. As I was playing, I couldn't help but think about how I have a tendency to do this in my development also. Meet today's bad guy: HTTP Headers.
While the anxiety might not be present, often my strategy of 'avoid getting into the weeds' for dealing with things I don't fully understand is the same. But over the past few weeks I've been traveling down a few web security and/or performance paths that have been dumping me at HTTP Headers. Figured it was time to roll up the sleeves and start to put this in my brain.
In the case at hand, I was trying to not fail on Mozilla's Observatory. The next step for the site I was working on was to set up 'HTTP Strict Transport Security' which involved setting a HTTP Header called 'Strict-Transport-Security'.
What exactly are HTTP Headers?
When you boil it down, here's what happens:
- Joe types in http://mattjenkinscomic.com in a browser.
- His computer says, OK, you want this information below. Let me go get it. (This is called the 'Request')
GET / HTTP/1.1 Host: mattjenkinscomic.com Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 .... Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, sdch, br Accept-Language: en-US,en;q=0.8 Cookie: PHPSESSID=9cs10mhllkroajsiatbigkg0b6; DNT: 1
- The computer that that website lives on (a server, if you will) takes in that information, and processes it. When it sends the information back to Joe's computer, it also sends along some info. (This is called the 'Response')
HTTP/1.1 200 OK Date: Fri, 31 Mar 2017 02:33:47 GMT Server: Apache/2.4.7 (Ubuntu) Strict-Transport-Security: max-age=63072000; includeSubdomains; X-Powered-By: PHP/5.5.9-1ubuntu4.21 Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 5643 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
What are HTTP Headers good for?
So many things! Dealing with cache management is one thing, that's probably going to be my next tackle. Then next, if I'm feeling feisty and have sharpened my blade enough I might take a stab at setting up a Content Security Policy. Turns out I was having Apache set some headers for authentication. And cookie information is passed along in headers as well.
On a side tangent I went down related to security, I learned there's a header called Do Not Track that a user can set if they would prefer to not be tracked. Sites are supposed to honor this setting when they do things like tracking you with cookies. There's a plugin called Privacy Badger that actually sets this header for users. I use privacy badger, so you can actually see the
DNT header in the above request.
How do you set HTTP Headers?
If it's just one file that needs some special instruction you can set HTTP headers with PHP individually per file.
header('Strict-Transport-Security: max-age=63072000; includeSubdomains;');
In my case, this wasn't really a option for this because ALL THE THINGS need that header.
I ended up setting my headers on my web server, which is Apache. First I had to enable mod_headers, by (
Then in my .conf file (
/etc/apache2/sites-available/mattjenksincomic.conf) I set the php header like so:
<VirtualHost *:443> ... ... Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;" </VirtualHost>
How can I make sure HTTP Headers are set correctly?
You can see the requests that your page is making across the network in a browsers developer tools, usually in a 'Network' tab. More than likely you will see a mess of requests when you look at these files. It makes my brain hurt less if I filter them by type. Then you click on the name of the resource you want to look at and voila! Headers.
So, one bad guy slain. Maybe I'll attempt one in Zelda... mayyybe.