CodePark/ questions / Rate limiting & brute force
START PRACTICINGPRACTICE
Backend question · Auth & security › Rate limiting & brute force

You rate limit login attempts by client IP, but the app runs behind a load balancer. What can go wrong, and how do you choose good rate-limit keys?

Behind a load balancer, every request seems to come from the load balancer's IP. The socket address is the load balancer's, not the user's. So every user shares one limit, and a single attacker can lock everyone out.

The naive fix is to read the X-Forwarded-For header. This header lists the client IP and each proxy the request passed through. Reading it blindly is dangerous, because clients can set this header themselves. An attacker can send a different fake IP each time and bypass the limit.

The correct fix: configure the framework to trust only your known proxies. In Express, use the trust proxy setting with the exact number of hops. Then the client IP comes from the entry that your own proxy added.

IPs alone are weak keys anyway:

  • Attackers rotate through botnets and residential proxies, so they have many IPs.
  • Many real users share one IP, through NAT (many devices behind one router) or a mobile carrier.

So combine several keys:

  • per IP
  • per account identifier, such as the username
  • per API key or user id on authenticated routes
  • a global limit per endpoint

Return status 429 (Too Many Requests) with a Retry-After header. Log what was limited.

  • Behind a proxy, all requests seem to come from the proxy's IP.
  • Clients control X-Forwarded-For, unless you trust your proxies precisely.
  • Configure the exact number of trusted proxy hops.
  • Combine IP, account, API key and global limits.
  • Return 429 with Retry-After, and log limit events.