As you’ll see, the situation is bad.īut this isn’t just about rate limiters. Then I moved on to worrying about how rate limiters determine what IP to rate-limit when they’re behind a load balancer (or any reverse proxy).
I wrote a post detailing how bad IPv6 rate limiting can and does lead to rate limiter escape and memory exhaustion. This leads to security vulnerabilities in a variety of projects, and will certainly lead to more in the future.Īfter thinking about rate limiters for a while, I started worrying about their IPv6 handling. It’s done incorrectly, inconsistently, and the result is used inappropriately. The state of getting the “real client IP” using X-Forwarded-For and other HTTP headers is terrible.
This is all explained in detail below, so keep reading. If you use the “real client IP” anywhere in your code or infrastructure, you need to go check right now how you’re deriving it. For example, you must not check the X-Real-IP header if you’re not behind Nginx or something else that always sets it, because you’ll be reading a spoofed value.Ī lot of rate limiter implementations are using spoofable IPs and are vulnerable to rate limiter escape and memory exhaustion attacks. Using special “true client IPs” set by reverse proxies (like X-Real-IP, True-Client-IP, etc.) can be good, but it depends on the a) how the reverse proxy actually sets it, b) whether the reverse proxy sets it if it’s already present/spoofed, and c) how you’ve configured the reverse proxy (sometimes).Īny header not specifically set by your reverse proxy cannot be trusted. When choosing the rightmost XFF IP, make sure to use the last instance of that header. Don’t use it for anything even close to security-related. The leftmost IP in the XFF header is commonly considered to be “closest to the client” and “most real”, but it’s trivially spoofable. When deriving the “real client IP address” from the X-Forwarded-For header, use the rightmost IP in the list. I’m afraid that many people won’t read enough to get everything that’s important, so here are the key points:
This post ended up being incredibly long comprehensive.