我有一个可供公众访问的名称服务器,因为它是几个域的权威名称服务器。
当前,服务器充斥着ANY对isc.org,trip.net等类似的伪造类型请求(这是一种已知的分布式DoS攻击)。
该服务器运行BIND,并已allow-recursion设置为我的LAN,因此这些请求被拒绝。在这种情况下,服务器仅以authority和additional引用根服务器的部分作为响应。
是否可以配置BIND,使其完全忽略这些请求,而根本不发送响应?
我有一个可供公众访问的名称服务器,因为它是几个域的权威名称服务器。
当前,服务器充斥着ANY对isc.org,trip.net等类似的伪造类型请求(这是一种已知的分布式DoS攻击)。
该服务器运行BIND,并已allow-recursion设置为我的LAN,因此这些请求被拒绝。在这种情况下,服务器仅以authority和additional引用根服务器的部分作为响应。
是否可以配置BIND,使其完全忽略这些请求,而根本不发送响应?
Answers:
面对相同的问题,我选择忽略所有递归请求。当所有解析器都想将我的服务器用作权威服务器时,确实会发送非递归查询。就我自己而言,只有配置错误的客户端和攻击者才使用递归查询。
不幸的是,我还没有找到让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
iptables -t raw -S PREROUTING。输出:-P PREROUTING ACCEPT,然后是-A PREROUTING -i eth0 -p udp -m udp --dport 53 -m string --hex-string "|01000001000000000000|" --algo kmp --from 30 --to 65535 -j DROP。我测试了可以正常使用host -ar exampledomain.com dns-server.example.net。当然,直到我添加了-r选件,它才能正常工作。
                    -r选项与众不同。我个人不喜欢简单的host查询不再起作用,这可能会造成混乱。尽管如此,这可能是一个有效的(迄今为止最好的)答案,即使我将继续使用自己的方法来过滤输出,我也会给您赏金,因为它即将到期。
                    我会尝试:
zone "." {
  type redirect;
  allow-query "none";
}
将客户端引向根服务器的响应由“重定向”区域控制。这应该告诉它不要回复那些。
Bind9文档中暗示了这一点:http ://ftp.isc.org/isc/bind9/cur/9.9/doc/arm/Bv9ARM.ch06.html#id2592674
您可以使用替换"none"您的本地子网。
如果您已有zone "."声明,只需添加allow-query "none";即可。
zone "." { type hint; file "/etc/bind/db.root"; };db.root声明,列出了根服务器。删除该声明将停止向外国域发出请求,但是服务器仍会以“服务器故障”作为响应,因此仍然可以用于DoS。
                    allow-query "none";到zone "."配置中?
                    通常,我建议:
打开绑定日志并记录被拒绝回答的ip。安装fail2ban程序,添加黑洞操作:http : //pastebin.com/k4BxrAeG(将规则放在/etc/fail2ban/actions.d中的文件中)
使用类似这样的东西在/etc/fail2ban/filter.d中创建绑定过滤器文件(需要调试!)
[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响应分类为“拒绝”,然后使用iptables将“拒绝”转换为默默忽略。
拒绝是named.conf选项部分中的简单部分:
allow-recursion { none;};
或者当然是您最喜欢的本地异常ACL ...
下一个疯狂的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响应的标志字段上设置以下位
当规则匹配以提供一些测试反馈时,在调试中发现已运行的绑定调试日志消息“错误发送响应:主机不可达”。
必须承认这是一个毫无意义的练习。如果没有放大,攻击者就可以轻松地反映TCP SYN。最终,除了使用TCP或部署Eastlake的DNS cookie外,根本没有可行的解决方案打破DNS。
您是否尝试阻止字符串isc.org或阻止它的十六进制字符串?
这为我工作:
iptables -A INPUT -p udp -m string --hex-string“ | 03697363036f726700 |” --algo bm -j DROP
iptables -A OUTPUT -p udp -m string -hex-string "|726f6f742d73657276657273|" –algo bm –to 65535 -j DROP但是,如果可能的话,我真的更喜欢仅基于BIND配置的解决方案。
                    'bnrexex.www.sf97.net/A/IN' 'whzpkacpxpiuycm.www.tpa.net.cn/A/IN'
                    这种攻击称为放大拒绝服务。您应该正确配置绑定,但是流量一开始就不应该进入绑定。在可以在您的网络中执行此操作的第一个网络设备上将其阻止。我遇到了同样的问题,并用默认的snort规则处理了它:
警报udp $ EXTERNAL_NET任意-> $ HOME_NET 53(msg:“ PROTOCOL-DNS ANY类型的过多查询-潜在的DoS”; byte_test:1,!&,0xF8,2;内容:“ | 00 00 FF 00 01 |”; detection_filter:跟踪by_src,计数30,秒30;元数据:服务dns;参考:url,foxpa.ws / 2010/07/21 / thwarting-the-isc-org-dns-ddos /; classtype:attempted-dos; sid :21817; rev:4;)
首先,我知道这是一个老问题,但是...
我已经运行了自己的权威性,非递归型DNS服务器已有数十年了,但从未成为任何基于DNS的DDoS攻击的受害者–直到现在,我切换到新的ISP。成千上万的欺骗性DNS查询淹没了我的日志,我感到非常恼火–与其说对服务器的影响,不如说是它使我的日志混乱不堪和被滥用的感觉。攻击者似乎在“ 权威名称服务器攻击 ”中尝试使用我的DNS 。
因此,我认为,即使我将递归查询限制在我的内部网络上(拒绝所有其他请求),我宁愿将我的CPU周期花费在iptables中的字符串匹配上,而不是将否定响应发送回欺骗的IP地址(日志中的混乱程度更少,更少网络流量和更高的满意度)。
我从其他人似乎都开始做起,找出要查询的域名,并使用目标DROP在该域上创建了字符串匹配。但是我很快意识到我最终将获得大量规则,每个规则都消耗CPU周期。那么该怎么办?由于我没有运行递归名称服务器,因此我认为可以在我具有权威性的实际区域上进行匹配,然后删除其他所有内容。
我在iptables中的默认策略是ACCEPT,如果您的策略是DROP,那么如果您想使用以下解决方案,则可能需要进行一些调整。
我将区域配置保存在单独的文件(/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";
使用区域配置文件作为参数运行以上脚本。
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
将输出保存到脚本,通过管道传输到外壳,或将其复制并粘贴到终端中以创建新链并开始过滤掉所有无效的DNS查询。
运行/ sbin / iptables -L DNSvalidate -nvx 以查看新链中每个规则上的数据包(和字节)计数器(您可能希望将包含大多数数据包的区域移到列表的顶部,以使其效率更高)。
希望有人会觉得有用:)