Skip to content

Add per-IP rate limiting at the filter layer (bot / DDOS protection) #9

Description

@piush365

Background

The current RRateLimiter operates per userId. A bot that rotates user IDs can still flood the system — each new userId gets a fresh limiter. A second layer of per-IP rate limiting at the filter level catches this pattern before it even reaches the service.

Proposed Change

Add IpRateLimitFilter (ordered before CorrelationIdFilter) using Redisson RRateLimiter keyed on the client IP.

String ip = Optional.ofNullable(request.getHeader("X-Forwarded-For"))
    .map(h -> h.split(",")[0].strip())
    .orElse(request.getRemoteAddr());

RRateLimiter limiter = redissonClient.getRateLimiter("ip_rate:" + ip);
limiter.trySetRate(RateType.OVERALL, config.requestsPerMinute(), config.keyTtl());
if (!limiter.tryAcquire(1)) {
    response.setStatus(429);
    return;
}

Config

flashsale:
  ip-rate-limit:
    requests-per-minute: 60
    key-ttl: PT2M```

## Security Note

Always prefer the first token from `X-Forwarded-For` (the original client) but be aware this header can be spoofed unless set by a trusted reverse proxy. Document this in the filter's Javadoc.

## Acceptance Criteria

- [ ] `IpRateLimitFilter` implemented and registered at `@Order(0)` (before correlation ID)
- [ ] Config added to `FlashSaleProperties` and `application.yml`
- [ ] Unit test verifies 429 is returned after IP limit is reached
- [ ] Separate counter metric `flashsale.ip.rate_limited_total` incremented
- [ ] Behaviour documented in README security section

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or improvementperformanceLatency, throughput, or resource usagesecurityAuthentication, authorization, or vulnerability

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions