Welcome, guest | Sign In | My Account | Store | Cart

Minimal python dns server, it only replies with a selected ip in an A record

Python, 43 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import socket

class DNSQuery:
  def __init__(self, data):
    self.data=data
    self.dominio=''

    tipo = (ord(data[2]) >> 3) & 15   # Opcode bits
    if tipo == 0:                     # Standard query
      ini=12
      lon=ord(data[ini])
      while lon != 0:
        self.dominio+=data[ini+1:ini+lon+1]+'.'
        ini+=lon+1
        lon=ord(data[ini])

  def respuesta(self, ip):
    packet=''
    if self.dominio:
      packet+=self.data[:2] + "\x81\x80"
      packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00'   # Questions and Answers Counts
      packet+=self.data[12:]                                         # Original Domain Name Question
      packet+='\xc0\x0c'                                             # Pointer to domain name
      packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04'             # Response type, ttl and resource data length -> 4 bytes
      packet+=str.join('',map(lambda x: chr(int(x)), ip.split('.'))) # 4bytes of IP
    return packet

if __name__ == '__main__':
  ip='192.168.1.1'
  print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip
  
  udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  udps.bind(('',53))
  
  try:
    while 1:
      data, addr = udps.recvfrom(1024)
      p=DNSQuery(data)
      udps.sendto(p.respuesta(ip), addr)
      print 'Respuesta: %s -> %s' % (p.dominio, ip)
  except KeyboardInterrupt:
    print 'Finalizando'
    udps.close()

Its general purpose is to anwser to ALL domain names queries with a know ip. Useful for malware analysis on virtual machines. You need administrative privileges to run it.

DNSQuery class reads a binary packet, received in port 53 (where dns server listen), this packet must be an "standard query" with one or more queries, we just reply to the first one (I have tested it in win and linux and it works well). We extract domain name just for informational purposes, we can do the reply blindly. DNSQuery.respuesta build the packet we will send to our client, hexadecimal values are based on dns rfc ( http://www.ietf.org/rfc/rfc1035.txt ) for an standard query.

Explanation in Spanish in: http://preachermm.blogspot.com/2006/04/servidor-fake-dns-en-python.html

3 comments

PerseoIIN x 15 years, 11 months ago  # | flag

There is anoter good fakeDNS sever written in java. At http://dnspentest.sourceforge.net there is a good fakeDNS server written in java. I have tested it and i can say that it is very stable. Probably, as the project says, it will be a part of DNS pentest suite. Bye

Justin Force 12 years, 7 months ago  # | flag

Thank you for this! You just saved me A LOT of trouble. I need to run a DNS server that responds with anything at all on an iMac on a private LAN. This is exactly what I was looking for.

Alex Sandro 8 years, 4 months ago  # | flag

I made my own dns server cache and everything using the code above. I'm even using it right now!

Thanks to the author of the code for showing me the way:

https://github.com/alexsilva/MINI-DNS-Server

Created by Francisco Santos on Sat, 15 Apr 2006 (PSF)
Python recipes (4591)
Francisco Santos's recipes (1)

Required Modules

Other Information and Tasks