I host my landing page (https://www.richardjameskendall.com) on AWS, but for performance and security reasons I've placed Cloudflare in front of it. I just use the free plan, but this is more than enough for my needs and it provides some great features including Cloudflare workers.
Cloudflare Workers
These are small pieces of serverless code which can run across ~190 data centres worldwide. You can have up to 30 for free + 100k free invocations per day of up to 10ms CPU time per invocation - that's a pretty chunky free allowance! You can use Javascript, Rust, C and C++.
You can attach these workers to your Cloudflare sites and modify aspects of the requests and responses very easily, for example you can add extra HTTP headers on the response.
This makes them perfect for my purpose, because I wanted to add some extra HTTP headers on my website to improve its security posture.
Checking your site
There are a couple of good services you can use to check the current status of your site and its security headers, those are
You can use these services to scan your site and report on common issues. Both guide you through various remedial actions you can take to resolve any warnings however I think Mozilla Observatory is the best for this. This service also invokes scans from other tools (like Qualsys SSL Labs) and aggregates all the results for you.
Building a Worker
Setup
Cloudflare makes a tool called Wrangler available for managing and deploying workers. You can install wrangler like this
npm install -g @cloudflare/wrangler
Note, if you have problems take a look here https://github.com/cloudflare/wrangler/issues/240.
Once installed you use wrangler config
to set up your instance with access to your Cloudflare account (using an API key). The tool provides instructions on how to do this.
Create the worker
You can use the default Javascript template for this worker, in your termninal type
wrangler generate name-of-worker
This will create the empty project in the name-of-worker
directory.
Inside the worker directory you will find a number of files, but the ones we will edit are wrangler.toml
and index.js
wrangler.toml
This file will look like this:
name = "name-of-worker"
type = "javascript"
account_id = ""
workers_dev = true
route = ""
zone_id = ""
You should make the following edits:
Property | Value |
---|---|
account_id | Set this to your Cloudflare account ID, you can find this on any Overview page in the dashboard |
zone_id | Ser this to your domain's zone ID, you can find this on the Overview page for the domain you want to use |
workers_dev | You can set this to false as we don't need to deploy this to your workers dev subdomain |
route | Change this to match your website domain e.g. www.example.com |
index.js
This is the file which contains the code which will be executed by Cloudflare for each request to your route. It gets responses from the origin and then edits the headers to add the extra headers needed to get a 'B' rating on the Obervatory service.
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
let response = await fetch(request)
response = new Response(response.body, response)
response.headers.set('Strict-Transport-Security', 'max-age=63072000')
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('X-XSS-Protection', '1; mode=block')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
return response
}
Testing
It is really easy to test a worker. From the directory which contains your worker, issue this command:
wrangler preview --watch
This will open a browser session showing you a preview deployment of your worker and allow you to test it. --watch
means that if you change your source code, wrangler will hot deploy the changes.
Clicking on the 'Testing' tab allows you to issue test requests which hit your worker, and you can inspect the output including the HTTP headers. You should be able to see new headers included in your output:
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=63072000
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
Deploying
To deploy your worker, issue the following command inside the directory which contains the worker:
wrangler publish
After this returns successfully your worker is live on your site and you'll see it in the Workers tab of the Cloudflare dashboard
The result
Now we can see a much better result!
Next steps
In subsequent articles I'll cover:
- environments and CI/CD for deploying workers automatically with GitHub actions
- improving the score even more with Content Security Policies
-- Richard, Jan 2020