防范DNS放大攻击:权威DNS服务器RRL配置教程(小白友好)

DNS放大攻击是最常见的DDoS攻击类型之一,利用少量请求即可产生洪水般响应,让权威DNS服务器成为帮凶。本文用最直白的语言解释攻击原理,并手把手教你通过RRL(响应速率限制)为BIND权威DNS服务器加装防护,从根源阻断放大。

防范DNS放大攻击:权威DNS服务器RRL配置教程(小白友好)
封面图:ZuCDN · ZuCDN 原创

一次不走心的寻路:DNS放大攻击到底在干什么?——DNS RRL

我的处理经验

折腾DNS RRL时,我发现最麻烦的往往不是安装,而是配置。想象一个场景:你在小区门口大喊一声“喂,3号楼在哪里?”保安立刻用对讲机吼出“3号楼在东边20米!”结果你这句话被隔壁一群捣蛋鬼听到,他们同时假扮你,在每栋楼门口都喊同一句话,保安则不停对讲各个方向,把整个小区吵翻天。这就是DNS放大攻击的缩影。

DNS(域名系统)本身是无辜的——它负责把“example.com”翻译成IP地址。问题出在一种特性:一个极小的查询请求(几十字节),可以触发一个巨大的响应(几百倍甚至上千倍)。攻击者通过伪造源IP地址(把源IP改成受害者的IP),向开放且未做限制的权威DNS服务器发送大量此类请求。服务器“好心”地将巨型响应一股脑发往受害者,最终耗尽受害者的带宽,使其无法正常服务。受害者甚至都不知道自己为什么被“群殴”。

这种攻击之所以“放大”,是因为响应/请求比非常高。例如,一个针对“isc.org”的ANY查询响应可以放大150倍以上。攻击者只需要很小的上游带宽,就能制造几百Gbps的洪流。长期以来,很多权威DNS服务器默认不设限制,成为DDoS的帮凶。

RRL:给DNS服务器装一个“限流阀”

先看关键判断

RRL(Response Rate Limiting,响应速率限制)就是用来解决这个问题的。它由ISC在BIND 9.9.x中引入,后来被其他实现(如Unbound、PowerDNS)采纳。核心思想很简单:当来自同一个源IP(伪造的源IP实际上就是受害者的IP)的DNS查询触发过多响应时,服务器开始选择性丢弃或延迟部分响应,从而防止放大流量产生。

注意:RRL不会限制正常查询,只会限制那些触发频繁、异常模式的流量。它通过维护一个桶(bucket)的滑动窗口机制,统计每个目标IP在单位时间内获得的响应数量,一旦超过阈值,就启动降级处理:比如丢弃、截断(TC=1强制客户端重试)、或者缓慢响应。这样,即使攻击者伪造了源IP,到达受害者IP的流量也会被服务器主动削减,放大效应被遏制。

RRL配置前必须知道的三件事——DNS RRL

故障定位思路

在动手之前,请理解以下三点,避免配置翻车:

  • RRL只工作在权威DNS服务器上:递归DNS服务器(如公共DNS)通常不直接开放给外部递归查询,RRL主要针对权威服务器暴露的递归或开放端口。
  • RRL有一定误杀风险:如果配置过于激进,可能会误伤来自共享网络(如NAT出口、CDN边缘节点)的正常用户。建议从较宽松阈值开始,观察日志再收紧。
  • RRL不能替代整体DDoS防护:它是降低放大因子的有效手段,但若攻击流量来自大量真实IP(而非伪装),仍需要上游清洗或CDN防护。

一步一步配置BIND RRL(以Debian/Ubuntu为例)

步骤1:检查BIND版本

RRL自BIND 9.9.0起正式支持。首先确认版本:

named -v | grep "BIND 9"

如果版本低于9.9,建议升级到稳定版本,如BIND 9.16 LTS。安装命令:

sudo apt update && sudo apt install bind9

步骤2:编辑named.conf配置

RRL配置只能在options块或view块中启用。在/etc/bind/named.conf.options中添加如下内容:

options {
    directory "/var/cache/bind";

    // 启用速率限制
    rate-limit {
        // 每个目标IP每秒允许的最大响应次数
        responses-per-second 50;
        // 滑动窗口大小(秒),与responses-per-second配合
        window 15;
        // 超过限制后,丢弃的请求比例(0~1)
        // 0.5表示丢弃一半超出的响应,1表示全部丢弃
        slip 0;
        // 可选:记录被限制的查询到日志
        log-only yes;
    };

    // 其他配置...
};

参数解释

  • responses-per-second:关键阈值。设为50表示每个目标IP在window时间内最多收到50个响应。一般建议从50开始,误报率低的公共权威服务器可设到100甚至更高。
  • window:统计窗口,通常设为5~15秒。如果窗口太小,容易受突发正常流量影响;太大则限制过于宽松。
  • slip:当限制生效时,是否“泄露”一部分响应。0表示直接丢弃,1表示全部丢弃;大于1则允许一定比例通过(如slip 2表示每两个限制触发一次返回NOTIMP或截断)。建议设0或者2。
  • log-only:强烈建议第一次设为yes。这样RRL只会记录日志而不会实际丢弃响应,方便你观察误报情况,确认无误后再改为no。

步骤3:验证配置并启动

sudo named-checkconf
sudo systemctl restart bind9

检查日志:

tail -f /var/log/syslog | grep "rate-limit"

如果看到类似 client 203.0.113.1#12345: rate limit drop 的日志,说明RRL正在工作。但因为你设置了log-only,它不会真的丢弃。

步骤4:观察并调整参数

建议至少观察一周。你需要关注:

  • 正常用户是否被限制:如果某个运营商的出口IP(如114.114.114.114)频繁出现在日志中,可能是正常递归查询被误伤。可以适当提高responses-per-second或window。
  • 是否有明显的攻击源IP:如果某个IP每秒请求量是正常值的几十倍,那它就是可疑攻击源。你可以通过配置ACL单独放行或封禁。
  • 日志量是否激增:当将log-only设为no后,控制台会安静很多,但也要防止日志被攻击性写入填满磁盘。

步骤5:正式启用丢弃

确认无异常后,将log-only改为no:

rate-limit {
    responses-per-second 50;
    window 15;
    slip 2;
    log-only no;
};

重载配置:

sudo rndc reload

验证RRL效果最简单的方法

配置前的检查

你可以在外部机器上模拟DNS放大请求,但注意不要攻击他人。最安全的测试是使用dnsamplifier测试工具(在自家网络内合法测试),观察响应是否被限制。更直观的方式是查看服务器的流量监控:启用RRL后,服务器出口流量应该显著下降,尤其是来自未知名查询的突发流量。

常见问题与回滚

配置前的检查

  • 配置错误导致BIND无法启动? 将rate-limit块整体注释掉,重启即可恢复。
  • 误伤正常用户后怎么回滚? 同样先注释rate-limit块,或者增大responses-per-second到200+并设slip为0.5,让限制更宽松。然后逐一排查日志中的出现频率。
  • RRL对权威服务器自身性能有影响吗? 极小。每个响应都需经过计数检查,但计算开销可忽略不计。在超大规模部署中,建议使用硬件加速或专用的DNS防火墙。

总结:让DNS服务器不再是DDoS帮凶

实际操作要点

RRL是一种轻量级、零成本的防御手段,尤其适合中小型权威DNS服务器。它不能替代专业的DDoS清洗设备,但可以从攻击源头削弱放大因子。配置起来并不复杂,只需十分钟就能让服务器从“有求必应”变成“理性限速”。开始行动前,先打开log-only观望几天,确认配置不会“伤及无辜”,再正式启用。如果你使用的是非BIND服务器(如PowerDNS、Unbound),原理一致,只需查阅对应文档调整参数即可。

DNS透明且脆弱——我们无法阻止攻击者伪造IP,但可以通过RRL让他们借力不成。保护自己,也保护他人。后续只要定期检查关键指标,DNS RRL就不会变成维护负担。

延伸阅读