Cloudflare Security

Securing a Site With a Cloudflare Client Certificate and mTLS

When a website required limited access, I needed a way to lock it down to specific physical devices. I couldn't rely on IP addresses which might change regularly, and while a strong password requirement might be sufficient I wanted something a little more secure. Not to mention that it shouldn't be crawled by any search engines either. The solution was a Cloudflare client certificate and mTLS firewall rule.

After some extensive searching and having some trouble installing the certificate on two Windows PCs, I came across this Cloudflare blog post about using your devices as the key to your apps. It lead me down the right track, but I wanted to outline my process here to document it for the future.

I started by heading to the domain in my Cloudflare account, then heading to the SSL/TLS section under Client Certificates and clicking the 'Create Certificate' button. For my purposes, I opted to let Cloudflare generate the private key and CSR and increased the validity period to 15 years. Once the certificate was created, I saved the key file and certificate with .pem extensions to my local computer (which happens to be macOS).

Referencing the Cloudflare blog post, I then ran the following command to convert the certificate and key to PKCS #12 format:

openssl pkcs12 -export -out outfile.p12 -inkey keyfile.pem -in certfile.pem

During this process, I opted to press Enter twice to choose an empty export password. Once this file was generated, I could then install it on any physical devices, with a mix of both Windows and Mac devices.

For Windows, in each user's browser of choice, I navigated to the browser settings to the Manage Certificates section. Choose Import, select the exported .p12 file from above leaving the password field blank and all other options as their defaults. Once imported, each PC needed to be fully restarted in order for the certificate to be recognized and used.

For Mac, I opened Keychain Access, selected the System keychain, then clicked the Add button and selected the .p12 file. After entering the user's password, the certificate password was "entered" which was actually blank. Mac devices did not require a restart.

Now to actually restrict access to devices with this certificate installed, in Cloudflare I navigated to the Security section under WAF and clicked the 'Create mTLS rule' button. Using the 'Use firewall rule builder' link, I added the proper hostname and selected the 'Client Certificate Verified' rule leaving the toggle off, which generates the following expression:

(http.host in {"hostname.tld"} and not cf.tls_client_auth.cert_verified)

Set the action to "Block" and click 'Deploy firewall rule', and you're all set! On both Windows and Mac devices, when accessing the domain the browser will prompt to select the appropriate certificate in the response.

This selection appears to be saved for all future requests until the browser is restarted. All other devices without a certificate installed will forego the certificate selection prompt and immediately receive an Access Denied error page from Cloudflare.

You May Also Like

Configuring a Cloudflare R2 Bucket and Worker For Public Access
Cloudflare R2 Workers

Configuring a Cloudflare R2 Bucket and Worker for Public Access

I recently published a plugin to integrate Cloudflare R2 with Craft CMS. After having a chance to utilize this on a few more projects after its release, I wanted to put together a guide to streamline this process for future use cases. Hopefully this will help out any others out there looking to setup R2 on their Cloudflare accounts, as most of this won't be specific to Craft CMS.

Learn More