Blog

Securing a Site With a Cloudflare Client Certificate and mTLS

Categories: Cloudflare | Security

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 the Windows devices, when accessing the domain it did prompt to select the appropriate certificate in the response. I'm not completely certain if this selection is saved for future requests, or if it needs to be selected again each time the browser or computer is restarted. If I find out I'll update this post, but for now all is working as expected with all other devices immediately getting an Access Denied error page from Cloudflare.

Access denied message from Cloudflare
comments powered by Disqus