Никитенко Максим (Sets88)

Личная страница

Python - подсчет DNS запросов

Как-то пришло мне письмо, о том что мой DNS сервер безжалостно DDOSит какой-то IP, причем по 53 UDP порту (DNS), оказалось действительно, злоумышленники воспользовались моей добротой и в частности моим открытым кэширующим DNS сервером, закрывать DNS сервер как-то не хотелось бы.

В общем стала задача заблокировать входящие запросы, короче говоря не буду углубляться в детали, необходимо было найти какой именно домен запрашивает злоумышленник, используя прекрасный модуль Scapy был написан данный скрипт.

Как же это работает, чтобы посчитать входящие DNS запросы, необходимо снять трафик с внешнего интерфейса. например так:

sudo tcpdump -s 1500 -n -w 123.tmp -i eth0 port 53

Эта команда начнет записывать весь трафик с интерфейса eth0 в файл 123.tmp, не забудьте остановить запись(Ctrl+C) Теперь выполняем наш скрипт:

#./count_dns_queryes.py 123.tmp
....
....
....
10 www.okcontent.video.mail.ru.
10 ns1.89.54.65.in-addr.arpa.
10 248.82.44.194.in-addr.arpa.
10 static.dl.mail.ru.
10 imgcdn.ptvcdn.net.
10 ksn-url-geo.kaspersky-labs.com.
10 ns2.89.54.65.in-addr.arpa.
10 syndication.twimg.com.
10 ns4.89.54.65.in-addr.arpa.
10 ns5.89.54.65.in-addr.arpa.
12 mb.static.socialquantum.ru.
13 www.odnoklassniki.ru.
14 vk.com.
17 a.root-servers.net.
18 swa.mail.ru.
36 dnl-01.geo.kaspersky.com.
1126 isc.org.

Скрипт просто считает о каком домене сколько раз спрашивали через DNS запрос и сортирует по возрастанию. Из вывода видно что довольно подозрительная статистика запросов, причем это за 10 секунд.


Исходный код

#! /usr/bin/python

import operator
import argparse

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *


def get_dns_queries(pcap):
	for packet in pcap:
		if packet.haslayer("DNS"):
			if packet["DNS"].ancount == 0:
				yield packet["DNS"].qd.qname


def count_dns_queries(queries):
	dnames = {}
	for name in queries:
		if name in dnames:
			dnames[name] += 1
		else:
			dnames[name] = 1
	return dnames


def print_tuple(dnames):
	for dname in dnames:
		print dname[1], dname[0]


def main():
	parser = argparse.ArgumentParser(description="Counts and sorts DNS queries from pcap file")
	parser.add_argument("filename", help="pcap file made by tcpdump or else")
	args = parser.parse_args()

	try:
		pcap = rdpcap(args.filename)
	except:
		print "Wrong file \"%s\"" % args.filename
		exit()

	dnames = count_dns_queries(get_dns_queries(pcap))
	dnames = sorted(dnames.items(), key=operator.itemgetter(1))

	print_tuple(dnames)

if __name__ == "__main__":
	main()
Яндекс.Метрика