Haydn Cowley

Write-ups

Testing my Cloudflare firewall rules (and finding my mistake)

Three free firewall rules stop attack traffic before it reaches my house. The rate limit didn't work at first, and testing is how I found out.

2 min readBy Haydn
Goal
Block attack traffic at Cloudflare, before it ever reaches the Pi
Result
785 of 1,000 blocked
Tools
Cloudflare WAF, curl

The rules

My site is read-only and has no WordPress or PHP, so anything asking for those is a bot looking for a way in. On Cloudflare's free plan I set up:

  • Block attack paths: /wp-, .php, /.env, /.git and phpmyadmin, which bots scan for constantly.
  • Only GET and HEAD: the site never needs POST, PUT or DELETE.
  • Rate limit: more than 100 requests in 10 seconds from one IP gets blocked.

Testing them

$ curl -s -o /dev/null -w "%{http_code}\n" https://haydnhomelab.com/wp-login.php
403
$ curl -s -o /dev/null -w "%{http_code}\n" -X POST https://haydnhomelab.com/
403

Then the rate limit: 1,000 requests, 50 at a time.

$ seq 1000 | xargs -P 50 -I{} curl -s -o /dev/null -w "%{http_code}\n" https://haydnhomelab.com/stats.json | sort | uniq -c
   1000 200  # first try: nothing blocked

Mistake I made: the first run got through completely. I'd set the rule's path to wildcard "/", which only matches the homepage exactly, and my test was hitting /stats.json. Changing it to /* fixed it.

# after the fix
    215 200
    785 429  # Too Many Requests

Cloudflare's security log showed all 785 blocked within the same second. You can see the latest blocked requests (path and country only, never IPs) in the live lab's security history.

Other settings

I turned on Always Use HTTPS and set the minimum TLS version to 1.2. I left Bot Fight Mode off on purpose, because it could block shields.io, which draws the live badges on my GitHub.

What I learned

  • A rule that looks right can still match nothing. The only way to know is to attack it yourself.
  • Blocking at Cloudflare means junk traffic never even uses my home connection.

How I used AI: Claude explained the rule options and wrote the test commands. I set the rules up in Cloudflare and ran the tests. The full, unedited notes are in my build log.