使用 fail2ban 防止 Bind9 被用于 DNS 放大攻击

前言

我在阿里云搭建的自用 dnsmasq 服务器,用来做免污染的 DNS,最近由于公开了IP,果然就遭到了攻击——其实是被用于 DNS 放大攻击。

由于 dnsmasq 本身就没有设计为对外提供 DNS 服务,所以它对于安全方面的配置文件不是很多(根本没有!),但它的解析策略又很方便配置(比如中国DNS解析白名单等),所以我在原本的基础上,再加了一个 Bind9 作为前端来做安全。

那么,今天我们就一起来看看到底如何给 Bind9 做安全配置。

Bind9 自身安全配置

Bind9 本身支持很多安全策略,我们把它做好,就已经能够让 DNS 十分健壮:

编辑 /etc/bind/named.conf.options ,我们添加自定义策略:

详细解释:

隐藏掉 Bind9 的版本信息,避免黑客针对你的 Bind9 版本漏洞进行攻击。

这句是开启 Bind9 解析转发,就像 dnsmasq 一样,让 Bind9 能够向上获取解析而不是自身去从根解析,就可以避免污染了(我这里解析到了本地的 dnsmasq 上)

只允许转发,禁用根解析,同时开启外部解析和缓存。

关闭安全配置,因为我要向上转发到dnsmasq,而前者的应答是非权威应答,所以要让 Bind9 接受非权威应答,就要关闭它。你不这样用的话就不必关。

 在查询一个域名时,可能会看到有“非权威应答”的提示,该提示表示你所查询的域名不使用你当前所用的DNS查询服务器上。

为每个 IP 进行限速,如果请求超过每秒 25 个,就不再响应直接丢包。

效果

这样一来,你应该就能在  /var/log/syslog 里看到大量的超限 drop 记录了,不过,即使如此,vps的流量依旧如流水一般远去,所以,我们还需要使用第三方的工具来处理这些 IP。

记得重启服务  service bind9 restart

使用 Fail2ban 自动屏蔽黑客 IP

没错, 如果你读过我的 购买了VPS之后你应该做足的安全措施 这篇文章,那你的 vps 上应该已经安装了这个工具,它默认就已经能够很好的运行了,但要给 Bind9 使用,我们还要继续定制一番。

定制 Bind9 以兼容 Fail2ban

Bind9 默认并不会单独生成日志的,我们需要把出错的日志输出以便 Fail2ban 能够记录,所以编辑  /etc/bind/named.conf ,在文件末尾另起一行插入如下语句:

这是重定向 Bind9 的默认日志到  /var/cache/bind/security.log 大小保持30M

这时候如果你用 tail -f /var/cache/bind/security.log 来查看,就会看到一大堆类似这样的记录了:

显然,现在有人在利用我的 DNS 进行反射攻击,接下来我们配置 Fail2ban 来干掉这些 IP。

让 Fail2ban 对 Bind9 生效

其实 Fail2ban 原生支持 Bind9 的,甚至其列表里就已经内置——不过那个策略与我们的期望不甚相符,还得自己改改。

编辑过滤配置

编辑 /etc/fail2ban/jail.conf 文件,在里边找到关于 Bind9 的配置部分,默认如下:

我们给它改改,udp 和 tcp 都启用:

这里的意思是一旦在1秒内发现5次记录,就会把对应的 IP 给加入黑名单,时间则是默认的3600秒。不过不要担心,这个记录是 drop 记录,不是正常的 query 记录

修改过滤规则

接下来我们改一下默认规则,默认的规则是探测被攻击——而我们是要探测被用于攻击……编辑 /etc/fail2ban/filter.d/named-refused.conf 文件,找到如下几行:

改为:

重启服务

使用命令 service fail2ban restart 来重启服务,这时候使用命令可查看其状态:

- action
|- Currently banned: 1
| - IP list: 94.254.209.48- Total banned: 1[/crayon]
你看,已经抓到一个了。

总结

总之,一番折腾下来,我们得到了如下收获:Bind9 能够对单个 IP 的每秒请求进行限制(随后你可以根据需求进行修改),一旦某IP再一秒内对服务器请求次数超过限制,则会被记录并丢弃请求,如果超过的次数超过五次,那么就会被拉入黑名单被防火墙拒绝(对方显示目标地址不可达)。

关于UDP的一点讨论

如你所见,在 Fail2ban 配置文件当中也写明了对 UDP 的策略很有危险,因为黑客可以很容易伪造不同的地址,这样可能会被用来利用你的规则恶意屏蔽某些 IP ,如果你的服务器出现这个情况,你就需要关掉针对 UDP 的策略了。

扩展阅读

Iptables-Fail2ban处理bind 非法攻击

十分钟架设DNS转发缓存服务器

Blocking a DNS DDOS using the fail2ban package

本文由 落格博客 原创撰写:落格博客 » 使用 fail2ban 防止 Bind9 被用于 DNS 放大攻击

转载请保留出处和原文链接:https://www.logcg.com/archives/1681.html

About the Author

R0uter

如非声明,本人所著文章均为原创手打,转载请注明本页面链接和我的名字。

Comments

  1. Just to make sure other don’t make this mistake.
    Under the tcp jail:
    [named-refused-tcp]

    Change this to:
    action = iptables-multiport[name=Named, port=53, protocol=udp]

    This:
    action = iptables-multiport[name=Named, port=53, protocol=tcp] << THIS

  2. 站长好,我的dns服务器收到的攻击日志如下:
    202.9.120.7#13620 (aaa.com): view g-1: rate limit drop SERVFAIL error response to 202.9.120.7/32

    可能是由于启用了view?在使用您教程里的正则表达式failregex = #\S+( \([\S.]+\))?\: rate limit drop时无法匹配,请问我这种日志,如何修改正则表达式,使其能匹配日志?盼求回复,谢谢!

      1. 我使用您提到的两个正则式,都不行。是不是什么地方漏写了什么?
        日志中一条为
        120.9.20.2#52774 (chef.vpn.qianxin.com): view cnc-user: rate limit drop

        1. 我文中的例子是 “#80 (nhl.msk.su): rate limit drop“, 你的日志是 “#52774 (chef.vpn.qianxin.com): view cnc-user: rate limit drop“,比我的多了“ view cnc-user:“ 这么个字段,如果它是固定的,那就把正则改成“#\S+( \([\S.]+\))?\: view cnc-user\: rate limit drop“ 试试,如果是变化的,干脆变成 “#\S+( \([\S.]+\))?\:.+\: rate limit drop“ 得了。

          简单来说就是你的日志格式和我的不一致~

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注