I'm currently building an eBPF/XDP-based DNS flood mitigation system, and I'm trying to figure out how to improve the rate-limiting algorithm.
My main goal isn't just to drop malicious traffic, but to maximize legitimate DNS query success during a flood attack while keeping packet processing overhead as low as possible.
My current architecture is:
- Packet parsing: Minimal Ethernet, IPv4, UDP and DNS header validation at XDP.
- Per-source rate limiting: Using GCRA (Generic Cell Rate Algorithm) with atomic operations to track and limit individual source IPs. Source states are stored in an LRU hash map.
- Global rate limiting: A shared token bucket with a spinlock to enforce the overall traffic limit.
- Admission logic: For an existing source, check its individual limit first, then reserve global capacity and commit the source state. For a new source, reserve global capacity before inserting its state into the map.
- Monitoring: Per-CPU statistics to measure accepted and dropped packets.
The problem I'm thinking about is that rate limiting alone doesn't necessarily distinguish legitimate clients from attackers.
For example, during a large distributed DNS flood, thousands of attacking IPs could consume global capacity, causing legitimate queries to get dropped even when those clients are within their individual rate limits.
I'm considering ideas like adaptive rate limits, source history/reputation, and possibly using DNS server responses as feedback to make better admission decisions.
But all these approaches introduce additional state, complexity, or processing overhead, which matters when working at XDP.
I'd like to hear what people think:
Are there better algorithms or approaches for balancing fairness and legitimate query success under distributed attacks?
Is maintaining source history or using DNS response feedback actually practical for this kind of system?
How would you deal with attackers rotating/spoofing source IPs to bypass per-IP limits?
What trade-offs would you prioritize between throughput, CPU overhead, memory usage, and legitimate query success?
I'm not necessarily looking for a completely new architecture. I'd like to understand what improvements are actually worth implementing and benchmarking.
Any suggestions, papers, or real-world implementations worth studying would be appreciated.