logo
podcast Podcast
get help Get Unstuck

How to rate limit by IP behind a Cloudflare proxy

If you don't do this, your app could actually start blocking Cloudflare traffic.

Joel Clermont
Joel Clermont
2023-11-27

I previously explained why Let's Encrypt works just fine behind Cloudflare, but today let's talk about something that doesn't work behind Cloudflare without extra configuration: IP-based rate limiting.

Why does Cloudflare cause a problem? It acts as a reverse proxy server. That means that all the requests from all of your different users are funneled through the Cloudflare network. So when the request reaches your server, the IP address of the connection will be one of Cloudflare's IPs, not the actual user's IP.

That means if you apply a rate limit based on IP, you're rate limiting Cloudflare, not individual users. This is definitely not what you want.

So what's the solution? We need to configure Laravel to tell it to trust the proxy server. Once we do that, Laravel will look at additional headers the trusted proxy server provides, and rewrite headers, like IP address, to match the original request, as it came into Cloudflare.

// app/Http/Middleware/TrustProxies.php

protected $proxies = [
    // list each of the Cloudflare IP ranges here
];

You can find the list of Cloudflare IP ranges here. They have not changed much historically. In fact, IPv4 ranges have only changed twice in Cloudflare's history.

Some might suggest just setting $proxies to '*', but that's a bad idea from a security perspective. It means someone else could start including proxy headers when making requests to your server, and Laravel would trust it. Even if you think this is unlikely, I say it's best to play it safe.

If you're only interested in throttling traffic from authenticated users, another approach is to throttle based on the authenticated user ID. Then you wouldn't need any special configuration around proxy servers.

Here's a bonus question to ponder: nginx is also a reverse proxy that sits in front of your PHP application. Why doesn't it cause the same problem as Cloudflare? Reply if you know the answer!

Here to help,

Joel

P.S. The best way to become a more confident developer is to understand how Laravel works under the hood. Get a deeper understanding of Laravel validation with our book.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.