Lion Cipher Lab

Rate-limit a login endpoint with nginx limit_req, and measure what it really stops

Why it matters

Every login page on the internet gets hammered by scripts trying passwords, and the cheapest control you can add sits in front of the app: a rate limit at the reverse proxy. nginx's limit_req does it in about four lines, and it is in nearly every hardening guide. But four lines you copied are not a control you understand. This lab makes you measure it. First you send a burst of logins at an unprotected backend and count how many arrive. Then you switch the limit on and count again: how many got a 429, how many still got through, and how much waiting the burst queue added. That turns rate,…

What you'll learn

Steps in this lab

  1. What you are building, and what a rate limit is (and is not)
  2. Set up: Docker running, a lab folder, a terminal
  3. Write the login backend and the burst client
  4. Start the backend and an unprotected nginx in Docker
  5. Measure BEFORE: how fast can a script hit the backend?
  6. Turn on limit_req (nodelay) and measure AFTER
  7. nodelay vs the default delay, in numbers
  8. Honest negative 1: one address, one bucket (shared NAT) and distributed sources
  9. Honest negative 2: trusting X-Forwarded-For lets the client pick its own key -- then fix it
  10. Honest negative 3: a rate limit is not account lockout, MFA, or a ban
  11. Do it better, then clean up

Open the full interactive lab →