Nikitenko Maxim (Sets88)

Personal page

Python - DNS query counter

One day I got the message, that my DNS server involved in DDOS attack, and I found out that it's true, attackers used my humanity and in case my shared DNS server, i did'nt want to close it for internet.

I had to block input requests from attackers, but to do this I had to find what domain address they are trying to resolve, I used awsome module named Scapy to solve the problem.

So, how it works? To count input DNS requests, i had to capture traffic from external interface. For example like this:

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

This command starts to capture whole traffic on interface eth0 to file 123.tmp, don't forget to stop capturing by Ctrl+C Now i ran my script, and here what we see:

#./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.

Script just counts input DNS requests by domains and sorts it ascending. Here we see a suspicious activity about "isc.org" domain, and it is capture for 10 seconds.


Source code
#! /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()
Яндекс.Метрика