DNS放大防护的核心在于对递归响应同时做速率限制和大小限制,前者拦截攻击流量突发,后者降低单包放大倍数,两者缺一不可。
DNS放大攻击之所以长期高居反射型DDoS榜首,本质是攻击者利用少量查询流量换取大体积响应流量,递归服务器作为被利用的“放大器”,其防护策略必须回归到两个最朴素的维度:单位时间内能回多少包,以及每个包最大能有多大,下面聊的,全是围绕这两个维度如何落地。
DNS放大攻击为何盯上递归响应
攻击者伪造受害者IP,向大量开放递归服务器发送小体积查询,例如ANY类型或DNSSEC记录查询,响应报文可能比查询大几十倍,业内专家指出,单个放大节点若不做任何限制,百兆带宽就能打出万兆攻击流量,递归响应是放大链路的最后一环,在这里设卡,性价比最高。
传统防火墙或上游ACL能过滤源IP,但面对伪造源地址的反射流量几乎无效,真正有效的防线必须部署在递归服务器自身,也就是对响应动作本身做约束,这决定了防护思路不是“拒绝谁”,而是“限制多少”。
速率限制:给递归响应装上流量阀门
速率限制(Response Rate Limiting,RRL)是目前公认最有效的DNS放大缓解手段,它的核心理作思想是:同一目标IP在固定时间窗口内,只响应固定数量的相同查询。
针对相同查询的令牌桶算法
递归服务器维护一张响应缓存表,记录每个目标IP的响应计数,当相同查询再次到达时,先查令牌桶:
- 桶内有令牌,正常响应。
- 桶内无令牌,直接丢弃或返回截断的TC=1响应。
- 被截断的响应会让合法客户端改用TCP重试,而伪造源IP的攻击流量则不会。
以BIND 9的RRL配置为例:
rate-limit {
responses-per-second 5;
window 5;
slip 2;
};
responses-per-second 5意味着每个目标IP每秒最多收到5条相同响应,超出部分每2条丢弃1条,其余返回截断响应,对于正常递归查询场景,这个阈值完全够用。
速率限制的粒度抉择
- 按目标IP限速:最常用,直接压制攻击目标感受到的流量。
- 按源IP限速:针对特定查询源,但递归场景下源IP是用户终端,误伤风险高。
- 按域名限速:适合针对热门域名的定向轰炸。
Unbound的配置稍有不同:
server: ratelimit: 1000 ratelimit-backoff: 100 ratelimit-size: 4m
ratelimit默认按源IP生存区(/24)维度限速,这里设置的是每秒1000次,比BIND宽松得多,需要注意的是,速率限制只对缓存命中的响应生效,因为只有重复查询才能被识别为可疑流量。
速率限制的盲区
RRL对分布式放大攻击(大量不同查询类型、不同域名)的识别能力有限,如果攻击流量中的查询各不相同,限速表无法归并同类项,限速效果大打折扣,速率限制需要配合大小限制和源端口随机化策略综合使用。
大小限制:把放大倍数关进笼子里
速率限制管的是“量”,大小限制管的是“体积”,一个100字节的ANY查询可能触发4000字节的响应,放大倍数40倍,限制了单包大小,即使速率限制被绕过,攻击带宽也会被大幅压缩。
限制EDNS0响应缓冲区
现代递归服务器默认遵循EDNS0协议,客户端会通告自己的UDP缓冲区大小,攻击者会故意通告较大的缓冲区(如4096字节),诱导服务器发送大响应。
BIND中可这样收紧:
options {
max-udp-size 1232;
max-cache-ttl 3600;
};
max-udp-size 1232是美国Verisign推荐的DNS over HTTPS/UDP传输标准值,适合绝大多数以太网环境,既能避免IP分片,又限制了单包最大体积,DNS递归服务器防护方案对比中,这个参数常被作为基线。
使用响应大小限制策略
Unbound提供更细粒度的响应大小控制:
server:
max-udp-size: 1232
answer-cookie: yes
qname-minimisation: yes
answer-cookie启用DNS Cookie机制,Unbound会对无Cookie的查询返回一个Cookie挑战,客户端需携带Cookie重试,攻击流量通常不会维护Cookie状态,这个机制能有效鉴别伪源IP流量。DNS Cookie兼容性方面,当前主流通用操作系统均支持,电信运营商网络中多数递归客户端已适配,基础场景下可安全开启。
丢弃非必要的放大记录类型
从根源上减少可用放大载体:
- 关闭ANY类型查询:BIND语法为
minimal-any yes;。 - 限制DNSSEC记录响应:仅对明确请求DNSKEY、RRSIG的查询返回相关记录。
- 过滤CHAOS TXT记录:这类记录常用于版本探测,可能被利用反射。
值得注意的是,多数企业递归服务器根本没有开启DNSSEC验证或签名,却默认响应DNSSEC相关记录,这等于主动提供了放大杠杆,DDoS防护系统中,这类“非业务必需但默认开启”的记录往往是最大风险敞口。

部署实践:从服务器到防火墙的四层防线
单靠递归软件自身的参数调整还不够,完整的DNS放大防护需要多层协同。
第一层:递归软件配置加固
修改BIND或Unbound配置后,使用named-checkconf或unbound-checkconf校验语法,再平滑重载配置,同时开启日志审计RRL丢弃行为:
logging {
channel rate_limit_log {
file "data/rate-limit.log";
severity info;
print-time yes;
};
category rate-limit { rate_limit_log; };
};
观察日志中丢弃比例,若持续高于总响应量的1%,说明业务可能受到攻击或正常流量被误伤,需要调整阈值。
第二层:内核防火墙联动
在Linux服务器上,使用iptables的hashlimit模块做UDP 53端口的总流量限速:
iptables -A INPUT -p udp --dport 53 -m hashlimit
--hashlimit-upto 1000/sec --hashlimit-burst 2000
--hashlimit-mode srcip,dstip --hashlimit-name dns_limit -j ACCEPT
这层防护胜在性能高,直接在内核态丢弃超限数据包,不会消耗递归软件进程的CPU。
第三层:网络边界过滤
在边界路由器或防火墙上,对出方向的UDP 53响应流量做带宽上限,即便攻击流量穿透了服务器,也无法占满上游链路。
第四层:响应缓存优化
提高递归缓存命中率,本质上是让服务器“少干活”,缓存未命中的查询需要向上游迭代,这一过程产生的响应时间和流量开销远大于命中响应,配置合理的max-cache-ttl和max-ncache-ttl,能显著降低递归服务器在攻击状态下的资源消耗。
效果验证与性能权衡
配置完成后,需要通过实际手段验证防护是否生效。
手工验证方法
在另一台机器上使用dig发起高频查询:
dig @202.106.0.20 example.com ANY +notcp
连续执行多次,观察响应中是否有TC标志或直接超时,合法TCP查询(加+tcp参数)应始终正常,这验证了“截断后重试”机制的可用性。
防护带来的性能代价
- 合法流量误伤率:企业内网环境下,若一台出口NAT后的所有终端共用一个公网IP,RRL可能将多用户的正常查询误判为攻击,此时应适当调高
responses-per-second,或改用值更小的策略。
slip
- 延迟增加:DNS Cookie机制引入的额外RTT(往返时延)会让首次查询变慢约一倍,对延迟敏感的业务,应优先使用响应大小限制替代Cookie机制。
- CPU开销:启用RRL后,BIND的查询处理性能平均下降5%-10%,在高端多核服务器上这个损耗可忽略不计。
企业DNS安全防护怎么做这个问题,核心答案就是先做递归响应治理,再谈链路扩容和流量清洗。
常见配置错误排查
- 修改配置后未重启服务,RRL未生效。
max-udp-size设置过大(如4096),导致分片概率上升。- 防火墙规则只限速了入方向SYN包,忽略了UDP攻击流量。
- 预留了过多的
allow-query网段,扩大了攻击面。
问答精选
DNS放大攻击防护方案中,速率限制和大小限制哪个优先级更高?
建议先启用大小限制,将max-udp-size收紧到1232字节,再配置速率限制,因为大小限制直接降低单包放大倍数,即使限速被绕过,攻击效果也有限,速率限制需要收集足够多的重复查询才能生效,且存在误伤风险,优先级后置。
DNS递归服务器限速配置中,BIND和Unbound的参数有何区别?
BIND依靠rate-limit字句中的responses-per-second和slip参数,粒度较粗但稳定性好,Unbound通过顶层ratelimit指令配置,支持按源IP网段和域名维度细化,且提供自动退避机制(ratelimit-backoff),在遭遇突发流量时能动态降低响应频率,恢复后自动回归正常状态。
限制DNS响应包大小后,DNSSEC验证会不会受影响?
受影响程度取决于验证方式,若递归服务器仅做DNSKEY缓存,不返回DNSSEC相关记录,1232字节足以承载绝大多数DNSSEC响应,若客户端主动请求DNSSEC记录且需要完整RRset,大响应不得不被截断,此时客户端需通过TCP重试,目前主流DNS解析库已支持TCP回退,基本感受不到差异。
DNS放大防护没有一劳永逸的方案,但抓住“速率”和“大小”两个阀门口径,配合合理的响应策略配置,能解决多数场景下的反射放大问题,先收紧响应体积,再限制响应频率,最后用防火墙兜底,这是一套在企业网络中经受过实战考验的顺序,最终目标不是让递归服务器完全不响应,而是让它只响应“值得响应”的查询。
