绑定:黑洞无效的recursion查询?

我有一个可以公开访问的名称服务器,因为它是几个域的权威名称服务器

目前服务器充斥着伪造types的ANY请求isc.org,ripe.net和类似的(这是一个已知的分布式拒绝服务攻击 )。

服务器运行BIND,并allow-recursion设置到我的局域网,以便这些请求被拒绝。 在这种情况下,服务器仅仅通过authorityadditional部分来引用根服务器。

我可以configurationBIND,使其完全忽略这些请求,根本不发送响应?

面对同样的问题,我select忽略所有的recursion请求。 所有parsing器在他们想要将我的服务器用作权威服务器时都会发送非recursion查询。 只有错误configuration的客户端和攻击者,在我自己的情况下,使用recursion查询。

不幸的是,我还没有find一种方法让BIND做到这一点,但如果iptables对你来说足够好,我就可以使用

 iptables -t raw -I PREROUTING -i eth0 -p udp --destination-port 53 \ -m string --algo kmp --from 30 \ --hex-string "|01000001000000000000|" -j DROP 

我会尝试:

 zone "." { type redirect; allow-query "none"; } 

引用客户端到根服务器的响应由“redirect”区域控制。 这应该告诉它不要回复这些。

Bind9文档暗示了这一点: http ://ftp.isc.org/isc/bind9/cur/9.9/doc/arm/Bv9ARM.ch06.html#id2592674

你可以用你的本地子网replace"none"

如果你已经有一个zone "." 声明,只需添加allow-query "none"; 到它。

一般来说,我会build议:

打开绑定日志并logging被拒绝的ips答案。 安装fail2ban程序,添加blackhole动作: http ://pastebin.com/k4BxrAeG(将规则放在/etc/fail2ban/actions.d文件中)

用/etc/fail2ban/filter.d这样的东西创build绑定filter文件(需要debugging!)

 [Definition] failregex = ^.* security: info: client #<HOST>: query \(cache\) .* denied 

编辑fail2ban.conf,添加部分:

 [bindban] enabled = true filter = bind # "bantime" is the number of seconds that a host is banned. bantime = 6000 # A host is banned if it has generated "maxretry" during the last "findtime" # seconds. findtime = 60 # "maxretry" is the number of failures before a host get banned. maxretry = 150 action = blackhole logpath = /var/log/named.log 

希望这会有所帮助!

基本的想法让bind将DNS响应分类为Refused,然后使用iptables将Refused转换为默认忽略。

拒绝是named.conf选项部分的简单部分:

 allow-recursion { none;}; 

或者当然你最喜欢的本地exceptionACL …

下一个疯狂的iptables魔术,根据需要调整或删除“-o eth0”。 该命令假定UDP之前的标准20字节IPv4层报头。

 iptables -A OUTPUT -o eth0 -p udp --sport 53 -m string --from 30 --to 32 --hex-string "|8105|" --algo bm -j DROP 

这在DNS响应的标志字段上键入以下位设​​置

  • DNS响应
  • recursion查询
  • 回复代码被拒绝

注意到日志消息运行绑定在debugging“错误发送响应:主机不可达”当规则匹配有一些反馈testing。

必须承认这是一个毫无意义的练习。 如果没有放大,攻击者就可以轻易反映TCP SYN。 除了使用TCP或部署Eastlake的DNS cookie之外,最终DNS破坏了根本没有可行的解决scheme。

你试图阻止stringisc.org或阻止hexstring呢?

这对我工作:

iptables -A INPUT -p udp -m string –hex-string“| 03697363036f726700 |” –algo bm -j DROP

这种攻击称为“放大拒绝服务”。 您应该正确地configuration绑定,但是stream量不应该首先到达您的绑定。 在第一个能够在networking中执行此操作的networking设备上阻止它。 我有同样的问题,并用default snort规则处理:

警告udp $ EXTERNAL_NET任何 – > $ HOME_NET 53(msg:“PROTOCOL-DNS过多查询typesANY – 潜在的DoS”; byte_test:1,!&,0xF8,2;内容:“| 00 00 FF 00 01 |”; detection_filter:track by_src,count 30,seconds 30; metadata:service dns; reference:url,foxpa.ws / 2010/07/21 / thwarting-the-isc-org -dns-ddos /; classtype:attempt-dos; sid :21817; rev:4;)

首先,我知道这是一个老问题,但…

我已经运行了我自己的权威,非recursion的DNS服务器几十年,但从来没有成为任何基于DNS的DDoS攻击的受害者 – 直到现在,当我切换到一个新的ISP。 数以千计的欺骗DNS查询充斥了我的日志,我真的很恼火 – 不是太多关于我的服务器的影响,而是它混乱了我的日志和被虐待的不舒服的感觉。 似乎攻击者试图在“ 权威名称服务器攻击 ”中使用我的DNS。

所以我想,即使我限制recursion查询到我的内部networking(否认所有其他),我宁愿花在我的CPU周期在iptables的string匹配比发回负面的反应欺骗的IP地址(减less混乱在我的日志,lessnetworkingstream量和我自己的更高的满意度)。

我开始的时候和其他人似乎一样 ,找出哪些域名被查询,并在目标DROP域上创build了一个string匹配。 但是我很快就意识到,我最终会得到大量的规则,每个规则都会消耗CPU周期。 那么,该怎么办? 由于我没有运行recursion名称服务器,我想我可能会在我有权威的实际区域上进行匹配,并删除其他所有内容。

我在iptables中的默认策略是ACCEPT,如果你的策略是DROP,你可能需要做一些调整,如果你想使用下面的解决scheme。

我将我的区域configuration保存在一个单独的文件(/etc/bind/named.conf.local)中,让我们以此为例:

 zone "1.168.192.in-addr.arpa" { // Private type master; allow-query { 192.168.1.0/24; 127.0.0.1; }; allow-transfer { 127.0.0.1; }; file "/etc/bind/db.192.168.1"; }; zone "home.example.net" { // Private type master; allow-query { 192.168.1.0/24; 127.0.0.1; }; allow-transfer { 127.0.0.1; }; file "/etc/bind/pri/db.home.example.net"; }; zone "example.net" { type master; file "/etc/bind/pri/db.example.net"; allow-transfer { 127.0.0.1; 8.8.8.8; }; }; zone "example.com" { type slave; masters { 8.8.8.8; }; file "sec.example.com"; allow-transfer { 127.0.0.1; }; notify no; }; zone "subdomain.of.example.nu" { type slave; masters { 8.8.8.8; }; file "sec.subdomain.of.example.nu"; allow-transfer { 127.0.0.1; }; notify no; }; 

请注意我的前两个区域中的“// Private”注释,我在下面的脚本中使用它来将它们从有效区域列表中排除。

 #!/usr/bin/perl # zone2iptables - Richard Lithvall, april 2014 # # Since we want to match not only example.net, but also (for example) # www.example.net we need to set a reasonable maximum value for a domain # name in our zones - 100 character should be more that enough for most people # and 255 is the absolute maximum allowed in rfc1034. # Set it to 0 (zero) if you would like the script to fetch each zone (axfr) # to get the actual max value. $maxLengthOfQueryName=255; $externalInterface="eth1"; print "# first time you run this, you will get error on the 3 first commands.\n"; print "# It's here to make it safe/possible to periodically run this script.\n"; print "/sbin/iptables -D INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n"; print "/sbin/iptables -F DNSvalidate\n"; print "/sbin/iptables -X DNSvalidate\n"; print "#\n"; print "# now, create the chain (again)\n"; print "/sbin/iptables -N DNSvalidate\n"; print "# and populate it with your zones\n"; while(<>){ if(/^zone\s+"(.+)"\s+\{$/){ $zone=$1; if($maxLengthOfQueryName){ $max=$maxLengthOfQueryName; } else { open(DIG,"dig -t axfr +nocmd +nostats $zone |"); $max=0; while(<DIG>){ if(/^(.+?)\.\s/){ $max=(length($1)>$max)?length($1):$max; } } close(DIG); } printf("iptables -A DNSvalidate -m string --from 40 --to %d --hex-string \"",($max+42)); foreach $subdomain (split('\.',$zone)){ printf("|%02X|%s",length($subdomain),$subdomain); } print("|00|\" --algo bm -j RETURN -m comment --comment \"$zone\"\n"); } } print "# and end the new chain with a drop\n"; print "/sbin/iptables -A DNSvalidate -j DROP\n"; print "# And, at last, make the new chain active (on UDP/53)\n"; print "/sbin/iptables -A INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n"; 

使用区域configuration文件作为参数运行上述脚本。

 root:~/tmp/# ./zone2iptables.pl /etc/bind/named.conf.local # first time you run this, you will get error on the 3 first commands. # It's here to make it safe/possible to periodically run this script. /sbin/iptables -D INPUT -i eth1 -p udp --dport 53 -j DNSvalidate /sbin/iptables -F DNSvalidate /sbin/iptables -X DNSvalidate # # now, create the chain (again) /sbin/iptables -N DNSvalidate # and populate it with your zones iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|net|00|" --algo bm -j RETURN -m comment --comment "example.net" iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|com|00|" --algo bm -j RETURN -m comment --comment "example.com" iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|09|subdomain|02|of|07|example|02|nu|00|" --algo bm -j RETURN -m comment --comment "subdomain.of.example.nu" # and end the new chain with a drop /sbin/iptables -A DNSvalidate -j DROP # And, at last, make the new chain active (on UDP/53) /sbin/iptables -A INPUT -i eth1 -p udp --dport 53 -j DNSvalidate 

将输出保存到脚本中,将其input到shell或复制并粘贴到terminal中以创build新链并开始筛选出所有无效的DNS查询。

运行/ sbin / iptables -L DNSvalidation-nvx查看新链中每个规则上的包(和字节)计数器(您可能希望将大多数包的区域移动到列表顶部以使其更有效)。

希望有人可能会觉得这有用:)