DNS rate limiting is a critical defense layer for any self-hosted DNS infrastructure. Without it, your recursive or authoritative servers become amplification targets in distributed denial-of-service (DDoS) attacks. This guide compares three leading approaches to DNS rate limiting: dnsdist from PowerDNS, BIND Response Rate Limiting (RRL), and Unbound’s built-in rate-limit feature.
Why DNS Rate Limiting Matters
DNS is inherently stateless — a small query can trigger a large response, making it one of the most effective amplification vectors for DDoS attacks. In 2023 and 2024, DNS amplification attacks consistently ranked among the top five attack vectors, with peak traffic exceeding 3 Tbps. A self-hosted DNS server without rate limiting is both a victim and an unwitting accomplice in these attacks.
Rate limiting works by tracking query patterns per source IP and dropping or truncating responses that exceed configured thresholds. This protects your server’s resources and prevents it from being used as an amplification reflector. For organizations running their own authoritative or recursive DNS, implementing rate limiting is not optional — it’s a fundamental security requirement.
For broader DNS infrastructure planning, see our comprehensive DNS server comparison and DNS firewall with RPZ guide.
Comparison Overview
| Feature | dnsdist | BIND RRL | Unbound rate-limit |
|---|---|---|---|
| Developer | PowerDNS | ISC | NLnet Labs |
| License | GPL-2.0 | MPL-2.0 | BSD-3-Clause |
| GitHub Stars | Part of PowerDNS (4,361+) | Part of BIND (ISC) | Part of Unbound (NLnetLabs) |
| Rate Limit Type | Global + per-client rules | Per-zone, per-source IP | Per-source IP |
| QPS Threshold | Configurable per rule | qps-limit, slip | default 50 qps |
| Slip Response | Yes (TC=1) | Yes (slip parameter) | Yes (TC=1) |
| IPv6 Support | Yes | Yes | Yes |
| Dynamic Rules | Yes (Lua, API) | No (static config) | No (static config) |
| Logging | Extensible (Lua, stats) | Query log | Verbosity levels |
| Docker Image | Official (powerdns/dnsdist) | Official (isc/bind) | Official (nlnetlabs/unbound) |
| Best For | Advanced traffic shaping | BIND deployments | Recursive resolver protection |
dnsdist (PowerDNS)
dnsdist is a highly configurable DNS load balancer and rate limiter. Unlike the other two options, it operates as a front-end proxy, sitting in front of your backend DNS servers and applying rate limiting rules before queries reach them.
Key Features
- Rule-based rate limiting: Define granular rules based on source IP, query type, domain name, or any combination
- Lua scripting: Dynamic rule creation and real-time adjustments via embedded Lua
- Multiple backends: Distribute traffic across multiple DNS servers with health checking
- DoH/DoT termination: Handle encrypted DNS traffic and apply rate limits per-client
- Real-time statistics: Web-based dashboard and console for monitoring
Docker Compose Configuration
| |
Rate Limiting Configuration
| |
Advanced: Per-Domain Rate Limiting
| |
BIND Response Rate Limiting (RRL)
BIND’s Response Rate Limiting is a built-in feature that limits the rate at which the server sends responses to the same client for the same type of question. It has been part of BIND since version 9.9 and is considered the gold standard for authoritative server protection.
Key Features
- Slip mechanism: Sends truncated responses (TC=1) at a configurable rate, allowing legitimate clients to retry over TCP
- Per-source, per-zone tracking: Tracks query rates independently for each source IP and zone combination
- IPv6 prefix aggregation: Uses /56 prefixes for IPv6 to prevent per-address evasion
- Exempt lists: Whitelist trusted resolvers that should not be rate-limited
- Automatic tuning: Adjusts behavior based on server load
BIND Configuration
| |
Docker Compose for BIND with RRL
| |
Unbound Rate Limiting
Unbound is a recursive DNS resolver with a built-in rate-limit feature designed to protect against cache poisoning and query floods. It operates at the recursive resolver level, limiting how many queries a single source can make.
Key Features
- Recursive-specific protection: Designed for resolver protection, not authoritative
- Simple configuration: Single parameter controls the rate limit
- IPv6 support: Full IPv6 rate limiting with prefix aggregation
- Low memory overhead: Efficient tracking with minimal resource impact
- TC=1 slip: Sends truncated responses for legitimate clients to retry over TCP
Unbound Configuration
| |
Docker Compose for Unbound
| |
Choosing the Right DNS Rate Limiting Solution
The choice depends on your architecture:
- Use dnsdist when you need advanced traffic shaping, DoH/DoT termination, or want to rate-limit across multiple backend servers. Its Lua-based rules and API make it the most flexible option.
- Use BIND RRL when running BIND as an authoritative server. It’s the most battle-tested rate limiting for authoritative DNS, with decades of production use.
- Use Unbound rate-limit when protecting a recursive resolver. It’s simple, effective, and requires minimal configuration.
For comprehensive DNS management, check our DNS management web UI guide and DNS-over-QUIC setup guide.
FAQ
What is DNS rate limiting and why is it necessary?
DNS rate limiting controls how many queries a DNS server will respond to from a single source IP within a time window. It prevents DNS amplification attacks, where attackers send small spoofed queries that generate large responses directed at a victim. Without rate limiting, any open DNS resolver can be weaponized as a DDoS amplifier.
What is the “slip” mechanism in DNS rate limiting?
The slip mechanism sends truncated responses (TC=1 flag) to rate-limited clients instead of dropping queries entirely. This tells legitimate clients to retry their query over TCP, which is harder to spoof. The slip ratio controls how often TC=1 responses are sent — a slip of 2 means every second limited query gets a truncated response instead of a refusal.
Should I use rate limiting on both authoritative and recursive DNS servers?
Yes, but with different configurations. Authoritative servers should use response rate limiting (like BIND RRL) to prevent amplification. Recursive resolvers should use query rate limiting (like Unbound’s ratelimit) to prevent cache flooding and query storms. dnsdist can protect both by sitting in front as a proxy.
How do I whitelist trusted resolvers from rate limiting?
All three solutions support whitelisting. In dnsdist, use NetGroup() with an allowlist file. In BIND, define an ACL and set responses-per-second 0 for that ACL. In Unbound, use access-control entries with allow_snoop or exempt specific subnets. Always whitelist your internal resolvers, monitoring systems, and any legitimate high-volume clients.
What rate limit values should I start with?
For authoritative servers (BIND RRL): start with responses-per-second 50 and slip 2. For recursive resolvers (Unbound): start with ratelimit: 50. For dnsdist: start with QPSAction(100) per source IP and adjust based on your traffic patterns. Monitor your logs and adjust thresholds — legitimate recursive resolvers may send hundreds of queries per second.
Can rate limiting cause false positives for legitimate users?
Yes, if configured too aggressively. Large organizations with NAT may have many users sharing a single public IP. The slip mechanism mitigates this by allowing TCP retries. For dnsdist, you can use Lua scripting to implement adaptive rate limiting based on historical patterns. Always monitor dropped queries and adjust thresholds accordingly.