我不知道如何阻止 BIND 上的任何 DNS 请求以降低 DNS 放大攻击的变化。我在网上看过指南,但大多数指南似乎都是通过 iptables 或 bind 执行速率限制。
有什么提示或建议吗?
答案1
这种方法效率不高,但是可以满足您的要求
我知道的唯一有效且通用的方法是启用 iptables 字符串过滤器来阻止请求。执行此操作之前,请务必备份您的 iptables 配置。
-A PREROUTING -p udp -m udp --dport 53 -m string --hex-string "|0000ff0001|" --algo bm --from 40 -j DROP
放置在你的 iptables 配置的 iptables raw table 部分中。
...或者从命令行:
iptables -t raw -I PREROUTING -p udp -m udp --dport 53 -m string --hex-string "|0000ff0001|" --algo bm --from 40 -j DROP
使用原始表的原因是为了避免在请求率较高的情况下出现状态表命中。
可能有用的可选步骤: 谨慎使用并在测试服务器上进行测试。避免在未经广泛测试的情况下在关键业务服务器上执行此操作。
这可能会停止一些DNS 枚举和放大攻击,但它破坏了几个 RFC。除了 NOERROR 之外,阻止任何其他东西离开您的服务器是微不足道的。
#
# drop anything leaving with the source port of 53 (DNS)
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -j DROP
#
# but then let through NOERROR for recursive
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -m string --hex-string "|8500|" --algo kmp --from 30 --to 31 -j ACCEPT
#
# and let through NOERROR for non-recursive
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -m string --hex-string "|8400|" --algo kmp --from 30 --to 31 -j ACCEPT
据我所知,没有一个 DNS 守护程序支持在不修改源代码的情况下选择要阻止的请求类型。例如,我修改了 rbldnsd,使其对“ANY”做出“A”的回答。这当然是不正统的,可能会让纯粹主义者感到不安。
答案2
如果您拥有 BIND 9.9 或更高版本,并且您的安装在构建期间启用了响应率限制,那么您可以设置如下所示的速率限制:
options {
...
rate-limit {
responses-per-second 10;
log-only yes;
};
};
如果您在查看 query.log 时对结果感到满意,请删除仅记录行并观察其效果。如果我没记错的话,默认值是 5,不建议低于该数字。另外,请监控您的丢弃率,因为您可能希望在托管更多区域的名称服务器上对其进行调整。
是的,你可以使用 iptables,但这是错误的建议,因为在大多数情况下,IP 过滤器会比你的名称服务器先遇到麻烦。此外,它无法根据请求进行区分,只能根据数据包数量及其源 IP 进行区分。这意味着你将丢弃大量合法流量。
答案3
没有用于删除所有类型查询的配置选项ANY
。minimal-responses
可用于删除答复的附加部分(RFC 要求的情况除外),使其成为一种安全的选择,没有真正的缺点。(除了管理员故障排除)
老实说,现在考虑这种方法已经有点晚了。当然,. ANY
可能偶尔仍会出现在你的热门查询中,但伪随机子域攻击是当今流行的趋势,强调每秒数据包数而非每秒字节数。之后还会有其他的,依此类推。
关注速率限制主要是因为它是限制基础设施整体损害的最有效策略之一。这是你应该关注的地方。如果你正在运行递归基础设施,请确保BCP-38在客户和出站路径之间实施。不要运行开放解析器。等等。只有限制了一般攻击面后,专注于特定攻击策略才有意义,因为正如您在这里发现的那样,这些策略很快就会失去价值。
答案4
我使用 Unbound DNS 或 Knot-resolver 作为 DNS 缓存来丢弃任何 PTR 请求。然后转发到您的上游解析器
policy.add(function (req, query)
if query.stype == kres.type.ANY then
return policy.DROP
elseif query.stype == kres.type.PTR then
return policy.DROP
end
end)