Skip to content

feat: rate limit user login with exponential backoff#310

Open
allamiro wants to merge 1 commit into
lixmal:masterfrom
allamiro:feat/login-rate-limit
Open

feat: rate limit user login with exponential backoff#310
allamiro wants to merge 1 commit into
lixmal:masterfrom
allamiro:feat/login-rate-limit

Conversation

@allamiro

@allamiro allamiro commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #275.

Design

In-memory RateLimiter (no new dependencies), keyed by <client ip>|<username lowercase>:

  • 5 failures are free (typos), then lockouts of 2s doubling per failure, capped at 15 minutes
  • blocked attempts return 429 Too Many Requests without hitting the auth backend
  • successful login resets the counter; stale entries are pruned opportunistically so the map stays bounded
  • client IP comes from realip_remote_addr() (honors Forwarded/X-Forwarded-For behind a reverse proxy)

Keying on ip+username means a distributed attack on one account or one IP spraying many accounts each still get throttled per pair; stronger global heuristics can build on this later.

Testing

  • 4 new unit tests: free-failure threshold, reset on success, key independence, backoff escalation/cap — cargo test 13/13
  • Live e2e against the OpenLDAP compose service: attempts 1–6 → 401, attempt 7 → 429, correct password while locked → 429, different username from same IP → unaffected

Summary by cubic

Adds in-memory login rate limiting with exponential backoff to slow brute-force attempts. Blocked attempts return 429, and a successful login resets the counter.

  • New Features
    • In-memory RateLimiter keyed by "|": 5 free failures, then 2s backoff doubling up to 15m.
    • Blocked attempts are rejected before hitting the auth backend; entries are pruned; success clears state.
    • Uses realip_remote_addr() to honor Forwarded/X-Forwarded-For behind proxies.

Written for commit bf48810. Summary will update on new commits.

Review in cubic

Updated after AI review: the client ip now defaults to the unspoofable TCP peer address; the new trust_proxy_headers option (default false) opts into forwarding headers for reverse-proxy deployments.

In-memory throttle keyed by client ip + username: 5 free failures,
then lockouts of 2s doubling up to 15 minutes. Successful login
resets the counter; stale entries are pruned opportunistically.
Blocked attempts return 429.

The client ip is the tcp peer address by default; the new
trust_proxy_headers config option (default false) opts into
Forwarded/X-Forwarded-For for reverse proxy deployments, since those
headers are spoofable when the server is directly exposed.
@allamiro allamiro force-pushed the feat/login-rate-limit branch from bf48810 to d32b52c Compare June 13, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No brute-force protection on /user_login

1 participant