面向公众的recursionDNS服务器 – iptables规则

我们在Linux机器上运行面向公众的recursionDNS服务器。 我们已经被用于DNS放大攻击。 有没有推荐的iptables规则可以帮助缓解这些攻击?

显而易见的解决scheme是将出站DNS数据包限制在一定的stream量级别。 但是我希望find一些更聪明的东西,这样攻击只是阻断了受害者IP地址的stream量。

我寻找的意见和build议,但他们都似乎是“不运行公共面向recursion名称服务器”。 不幸的是,如果我们不这样做,那么我们就会陷入一个难以改变的地步,这是十多年前在这些攻击事件之前作出的决定造成的。

整个事情的一种“不是我的问题”的情景,这不是你的错,应该/可以通过采取适当的行动100%解决,不pipe它是多么“困难”或“硬”,这就是终止你的打开recursion服务器

分阶段:告诉客户,这个服务器将在Xdate之后离开。 之后,他们需要安装一个补丁(假设你有一个补丁)来阻止它使用你的DNS服务器。 这是一直做的。 系统pipe理员,networkingpipe理员,帮助台人员,程序员? 我们得到它; 这种报废的事情总是发生,因为它的供应商/服务提供商/合作伙伴的标准操作程序告诉我们在Xdate之后停止使用某些东西。 我们并不总是喜欢它,但它是IT生活中的一个事实。

你说现在的设备没有这个问题,所以我假设你已经用固件更新或补丁解决了这个问题。 我知道你说过不能触摸设备,但是他们肯定可以? 我的意思是,如果他们让这些盒子本质上是给你打电话的,那么他们不可能真正成为谁在对他们的设备做什么的肛门。 您可以为他们所知的所有设置进行反向代理设置,为什么不让他们安装修复此问题的修补程序或告诉他们使用自己的DNS服务器 。 当然你的设备支持DHCP; 我想不出一个networking设备(不pipe多大/多/less)。

如果你不能做到这一点,接下来要做的就是控制谁可以访问你的recursion服务器 :你说“很难说”谁在使用它以及如何使用它,但是现在是时候查找一下,并开始丢弃stream量不合法。

这些是“准军事/政府”组织,对吗? 那么,他们可能是他们拥有的一个合法networking的一部分。 这些设备不是dynamicIP背后的家庭路由器。 找出。 联系他们,解释问题以及如何通过不强制固件或产品replace节省大量金钱,只要他们能够确认设备将用来访问您的DNS服务器的networking块/ IP地址即可。

这一直是这样做的:我有几个客户以这种方式限制外联网访问或HL7听众的医疗保健合作伙伴; 要让他们填写表格并提供IP和/或networking阻止我不应该期待stream量:如果他们想访问外部networking,他们必须给我一个IP或子网。 这很less是一个移动的目标,所以它不会像每天有数百个IP变更请求被淹没:大型医院networking拥有自己的networking数据块,数百个子网和数以千计的主机IP,经常给我less量的IP地址或我应该期待的子网; 再次,这些并不是笔记本电脑用户随时随地都在校园里漫游,那么为什么我会期望看到来自不断变化的IP地址的UDP源数据包呢? 很显然,我在这里做出了一个假设,但是我敢打赌,这个数字不如你想象的<100s的设备。 是的,这将是一个冗长的ACL,是的,它需要一些维护和沟通(喘气!),但它是在完全closures它之外的下一个最好的事情。

如果由于某种原因,沟通渠道不畅通(或者有人太害怕或不能联系这些传统设备所有者,并正确地做到这一点),您需要build立一个正常使用/活动的基线,以便您可以制定一些其他策略,这将有助于 (但不会阻止)您参与DNS放大攻击。

一个长时间运行的tcpdump应该能够对传入的UDP 53进行筛选,并在DNS服务器应用程序上进行详细的日志logging。 我也想开始收集源IP地址/ netblocks / geoIP信息(都是你在美国的客户吗?阻止其他一切),因为如你所说,你没有添加任何新设备,你只是提供一个遗留服务于现有的安装。

这也将帮助您了解正在请求的loggingtypes,以及对于哪些域,由谁以及多久 :要使DNS放大按预期工作,攻击者需要能够请求大型loggingtypes (1)function (2)。

  1. “大loggingtypes”:做你的设备甚至需要TXT或SOAlogging,以便能够通过您的recursionDNS服务器来解决? 您可能能够指定哪些loggingtypes在您的DNS服务器上有效; 我相信这是可能的BIND,也许Windows DNS,但你必须做一些挖掘。 如果您的DNS服务器使用SERVFAIL响应任何TXT或SOAlogging,并且响应比预期的有效负载小一个数量级(或两个)。 显然你仍然是“问题的一部分”,因为欺骗的受害者仍然会从你的服务器获得SERVFAIL响应,但至less你没有敲打它们,也许你的DNS服务器从收获列表中“摘牌” )机器人随着时间的推移不“合作”。

  2. “function域”:您可能只能将有效的域列入白名单。 我在我强化的数据中心设置上执行此操作,服务器仅需要Windows Update,Symantec等。 但是,您现在只是减轻了造成的伤害:受害者仍然会受到来自服务器的NXDOMAINSERVFAIL响应的轰炸,因为您的服务器仍然会响应伪造的源IP。 同样,Bot脚本也可能会根据结果自动更新它的开放服务器列表,所以这可能会删除您的服务器。

我也会使用某种forms的速率限制,正如其他人所build议的,无论是在应用程序级别(即消息大小,每个客户端的请求限制)还是防火墙级别(请参阅其他答案),但是,必须做一些分析,以确保你没有杀死合法的stream量。

被调整和/或训练的入侵检测系统(再次需要一个基线)应该能够通过源或者量来检测一段时间内的exceptionstream量,但是可能需要定期的保姆/调整/监视来防止误报和/或者看看它是否真的阻止了攻击。

在这一天结束的时候,你不得不怀疑这一切的努力是否值得,或者你是否应该坚持正确的做法,并且首先解决问题。

这取决于您想要做的速率限制的种类。

使用iptables速率限制实际上是为了限制传入数据包,因为限制的数据包将匹配filter,并且应用指定的目标(例如, ACCEPT )。 你大概会有一个后续的目标去DROP数据包不匹配的filter。 虽然iptables有一个QUEUE目标,但它只是将数据包传递给需要提供自己的排队应用程序的用户空间。 您也可以对传出数据包进行速率限制,但很less有人真的想要开始丢弃传出的数据包。

iptables限速下降:

 iptables -A INPUT -p udp --port 53 -m hashlimit --hashlimit 1/minute --hashlimit-burst 5 -j ACCEPT iptables -A INPUT -p udp --port 53 -j DROP 

使用hashlimit limit而不是limit会给你每个目的IP的速率限制。 也就是说,达到8.8.8.8的五个数据包达到了限制,将阻止数据包被发送到8.8.4.4,而如果使用了hashlimit如果8.8.8.8最大,你仍然可以达到8.8.4.4,这听起来更像你想要的。

如果你不希望数据包超过限制被删除,那么你真正想要的是tctc将调节stream量,以获得稳定的stream量,而不是大量的突发stream量。 在传入端数据包传送到应用程序较慢,但都将按顺序到达。 在传出数据包将尽可能快地离开你的应用程序,但放在一个连续的stream中的电线。

我没有使用过多的tc ,但是这里有一个限速ICMP的例子,你可以很容易地适应DNS。

这里有一件事你可以做,以潜在的缓解对欺骗性查询的反应,但它需要一些工作:

首先,看看安全通道的日志,find一个被欺骗的IP地址。

然后使用该源IP(10.11.12.13)运行tcpdump,如下所示:

tcpdump -n src 10.11.12.13 and udp dst port 53 -v -X -S

你会得到这样的东西:

 18:37:25.969485 IP(tos 0x0,tt152,id 46403,offset 0,flags [none],proto:UDP(17),length:45)10.11.12.13.51169> 01.02.03.04.domain:4215+ ANY ?  。  (17)
         0x0000:4500 002d b543 0000 3411 b9d9 0A0B 0C0D E ..-。C..4 .......
         0x0010:0102 0304 c7e1 0035 0019 0e89 1077 0100 ....... 5 ..... w ..
         0x0020:0001 0000 0000 0000 0000 ff00 0100 ..............

现在有趣的部分! 在http://tools.ietf.org/html/rfc1035打开rfc1035并转到4.1.1节&#x3002;

是时候翻译tcpdump的结果,找出一个我们可以用来创build一个包级别filter的模式。

标头的ID从0x1C开始,所以我们在0x1E有一些标志,0x20的QDCOUNT,0x22的ANCOUNT,0x24的NSCOUNT和0x26的ARCOUNT。

这留下了实际的问题在0x28,在这种情况下为NAME(ROOT),QTYPE = ANY 0xFF和QCLASS = IN 0x01。

为了简单起见,我发现添加以下iptables规则块超过95%的请求ANYlogging的欺骗性查询IN ROOT:

iptables -A INPUT -p udp --dport domain -m u32 --u32 "0x28=0x0000ff00" -j DROP

你的里程可能会有所不同…希望这有助于

在Linux中使用tc和排队规则出站端口53 UDP:

 IFACE=eth0 tc qdisc add dev ${IFACE} root handle 1: htb default 0 tc class add dev ${IFACE} parent 1: classid 1:1 htb rate 10mbit burst 20m tc qdisc add dev ${IFACE} parent 1:1 handle 10: sfq perturb 1 tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 handle 1 fw flowid 1:1 

将防火墙标记为“1”的数据包设置为限制为10mbit的disc 。 防火墙标记只在防火墙内部,不要修改数据包。 只是由排队规则处理数据包。 这里是你如何使用iptables来制作防火墙标记:

 iptables -A PREROUTING -o eth0 -p udp --sport 53 -t mangle -j MARK --set-mark 1 iptables -A PREROUTING -o eth0 -p udp --dport 53 -t mangle -j MARK --set-mark 1 

根据自己的喜好进行修改以排除受信任的子网和/或目的地。 -o eth0仅将整形限制为出站数据包。 希望这可以帮助。

我试图编写一个依赖于你的外部recursionparsing器的所有客户端的列表。 从DNS盒子上一天左右的数据包追踪开始。 从那里,开始创buildiptables规则,以允许您识别和授权的stream量。 默认最终将丢弃stream量到53 / tcp和53 / udp。 如果这打破了一些东西,请微调你的规则。

取决于你所在的networking'位置'(有多个bgp源或者位于互联网的“末端”),你可以尝试一些类似于uRPF的东西来防止源地址欺骗。

信息的其他来源。

这些设备是否仍然在支持合同之下? 如果是这样,请联系您的客户。 让他们知道,在过去的十年中,互联网已经发展了一些,为了继续为这些设备提供名称parsing,您需要知道SRC IP以期望查询。 将date设置为〜6个月,届时您将无法再为未知客户提供服务,并坚持下去。 这在业内是相当普遍的。 如果这些设备不再受到支持合同的约束……听起来像是一个商业决策。 贵公司打算花费不再能产生收益的古代产品多久?

这听起来像专门的设备,它们是非常专业的,你可以合理地预测哪些领域,期望合法的查询? 绑定支持视图,创build一个只对这些域进行recursion的公共视图。

如果您还没有这样做,请将其作为学习机会,停止发布您无法修复错误的产品。 这就是这个,一个错误。 一个肯定会早晚使这个装置过早的。

从某个地方的nanog,这个:

 iptables -A INPUT -p udp --dport 53 -m hashlimit \ --hashlimit-name DNS --hashlimit-above 20/second --hashlimit-mode srcip \ --hashlimit-burst 100 --hashlimit-srcmask 28 -j DROP 

这并不理想。 每秒允许更less的数据包可能会更好,并有更高的突发。

这是一个解决scheme,我用了几次DDOS攻击,这不是完美的,但帮助我。 该解决scheme包含一个脚本,每隔N分钟(如1,2,3等分钟)由cron调用,并阻止创build大于脚本中给定脚本的连接数的IP:

 #!/bin/sh PORT_TO_CHECK="53" CONNECTION_LIMIT="20" IPTABLES="/sbin/iptables" netstat -an > /tmp/netstat.tmp Buf_var1=`cat /tmp/netstat.tmp | grep -v "LISTEN"| grep ":$PORT_TO_CHECK\ " | grep -v "0.0.0.0" | awk '{print $5}' | grep -v ":$PORT_TO_CHECK$" | sed -e 's/^::ffff://g' -e 's/:.*$//g' | sort | uniq` i=0 banned_flag=0 for conn in `for i in $Buf_var1; do echo -n "$i "; cat /tmp/netstat.tmp | grep -c $i;done | grep -v "=\ 0"`;do [ $i = 0 ] && connip=$conn && i=1 [ $i = 2 ] && { connum=$conn [ $connum -ge $CONNECTION_LIMIT ] && { [ "$var_test" = "" ] && { $IPTABLES -I INPUT -s $connip -j DROP banned_flag=1 } } } [ $banned_flag = 1 ] && i=0 [ $i = 1 ] && i=2 done rm -f /tmp/netstat.tmp