使用 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
来重启服务,这时候使用命令可查看其状态:

你看,已经抓到一个了。

总结

总之,一番折腾下来,我们得到了如下收获: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. Thank you for writing a helpful blog. I followed your configuration and configured my server.
    But failregex = #\S+( \([\S.]+\))?\: rate limit drop does not matches for me. My log file generates logs. Does The # after commenting the line “^\s*\S+\s+named(?:\[\d+\])?: [^:]+: rate limit drop” ? Color also change after #.

    My Fail2ban version is 1.0.2.

    Output of

    fail2ban-regex /var/cache/bind/security.log /etc/fail2ban/filter.d/named-refused.conf

    Running tests
    =============

    Use failregex filter file : named-refused, basedir: /etc/fail2ban
    Use log file : /var/cache/bind/security.log
    Use encoding : UTF-8

    Results
    =======

    Prefregex: 1 total
    | ^\s*(?:\S+ (?:(?:\[\d+\])?:\s+\(?named(?:-\w+)?(?:\(\S+\))?\)?:?|\(?named(?:-\w+)?(?:\(\S+\))?\)?:?(?:\[\d+\])?:)\s+)?(?:(?!error|info)[\w-]+: )?(?:(?:error|info):\s*)?client(?: @\S*)? (?:\[?(?:(?:::f{4,6}:)?(?P(?:\d{1,3}\.){3}\d{1,3})|(?P(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}|(?<=:):)))\]?|(?P[\w\-.^_]*\w))#\S+(?: \([\S.]+\))?: (?P.+)\s(?:denied|\(NOTAUTH\))\s*$
    -

    Failregex: 0 total

    Ignoreregex: 0 total

    Date template hits:
    |- [# of hits] date format
    | [253912] {^LN-BEG}Day(?P[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)?

    Lines: 253912 lines, 0 ignored, 0 matched, 253912 missed
    [processed in 9.25 sec]

    Missed line(s): too many to print. Use –print-all-missed to print all 253912 lines

    What I am missing ?

    1. I would say… try restart the fail2ban first. It seems like ur changes not take effect, Failregex: 0 total, it should be 1, otherwise the regex was not loaded.
      If a service restart not work, then I d suggest go over the path/filenames see if there any typo or something, or even poking around the prefregex to blah then see if the change take effect.

  2. 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

  3. 站长好,我的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“ 得了。

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

发表回复

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