Last active
August 30, 2024 20:28
-
-
Save andreif/6040183 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Original from http://code.activestate.com/recipes/491264/ (r4) | |
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding=utf-8 | |
""" | |
$ python dns.py | |
$ dig @0.0.0.0 -p 5053 -t A ietf.org | |
""" | |
import socket | |
import datetime | |
TTL = 300 | |
IP = '192.168.1.1' | |
RECORD_TYPES = { | |
'\x00\x01': 'A', | |
'\x00\x05': 'CNAME', | |
'\x00\x0f': 'MX', | |
'\x00\x02': 'NS', | |
'\x00\x10': 'TXT', | |
'\x00\x1c': 'AAAA', | |
'\x00\xff': 'ANY', | |
} | |
class Request(object): | |
def __init__(self, data): | |
self.data = data | |
def get_domain(self): | |
domain = '' | |
tipo = (ord(self.data[2]) >> 3) & 15 # Opcode bits | |
if tipo == 0: # Standard query | |
ini = 12 | |
lon = ord(self.data[ini]) | |
while lon != 0: | |
domain += self.data[ini + 1:ini + lon + 1] + '.' | |
ini += lon + 1 | |
lon = ord(self.data[ini]) | |
return domain | |
def get_raw_type(self): | |
return self.data[-4:-2] | |
def get_type(self): | |
return RECORD_TYPES.get(self.get_raw_type(), 'Unknown') | |
def response(self): | |
return Response(request=self) | |
def int_to_hex(value, zfill=None): | |
h = hex(value) # 300 -> '0x12c' | |
h = h[2:].zfill((zfill or 0) * 2) # '0x12c' -> '00012c' if zfill=3 | |
return h.decode('hex') | |
def bin_to_hex(value): | |
# http://stackoverflow.com/questions/2072351/python-conversion-from-binary-string-to-hexadecimal/2072384#2072384 | |
# '0000 0100 1000 1101' -> '\x04\x8d' | |
value = value.replace(' ', '') | |
h = '%0*X' % ((len(value) + 3) // 4, int(value, 2)) | |
return h.decode('hex') | |
class Response(object): | |
def __init__(self, request): | |
self.request = request | |
def __str__(self): | |
return self.render_packet() | |
def _get_ip_bytes(self): | |
return str.join('', map(lambda x: chr(int(x)), IP.split('.'))) | |
def _get_ttl_bytes(self): | |
return int_to_hex(TTL, zfill=4) | |
def render_packet(self): | |
packet = '' | |
if self.request.get_domain(): | |
d = self.request.data | |
packet += d[:2] # Transaction ID | |
flags = '' | |
flags += '1' # 1=response, 0=query | |
flags += '0000' # opcode, 0=standard query, 1=inverse query, 2=server status request | |
flags += '1' # Authoritative Answer | |
flags += '0' # Trancated response | |
flags += '0' # Recursion Desired | |
flags += '0' # Recursion Available | |
flags += '000' # reserved, have to be 0 | |
flags += '0000' # RCode, 0=no error | |
packet += bin_to_hex(flags) | |
packet += d[4:6] # Number of Questions | |
packet += d[4:6] # Number of Answer RRs | |
packet += '\x00\x00' # Number of Authority RRs | |
packet += '\x00\x00' # Number of Additional RRs | |
packet += d[12:] # Original Domain Name Question | |
packet += '\xc0\x0c' # NAME (domain) | |
packet += self.request.get_raw_type() # TYPE | |
packet += '\x00\x01' # CLASS (Internet) | |
packet += self._get_ttl_bytes() # TTL time to live | |
packet += int_to_hex(4, zfill=2) # RDLENGTH | |
packet += self._get_ip_bytes() # RDATA | |
return packet | |
if __name__ == '__main__': | |
print "Starting name server..." | |
udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
udps.bind(('', 5053)) | |
try: | |
while 1: | |
data, addr = udps.recvfrom(2048) | |
p = Request(data) | |
resp = str(p.response()) | |
udps.sendto(resp, addr) | |
now = datetime.datetime.utcnow() | |
cols = [now.strftime('%Y-%m-%d %H:%M:%S.%f')] + list(addr) + [p.get_type(), p.get_domain()] | |
print ' '.join((unicode(x) for x in cols)) | |
print data.encode('hex') | |
print resp.encode('hex') | |
except KeyboardInterrupt: | |
print "Done." | |
udps.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Tutorial: http://mysshlog.co.uk/tutorials/Python-Simple-Dns-Server | |
# Source: http://mysshlog.co.uk/download/Dns_Server_Python.py | |
## {{{ http://code.activestate.com/recipes/491264/ (r4) | |
#Edited By MySSHLog.co.uk | |
import socket | |
import optparse | |
import time | |
class DNSQuery: | |
def __init__(self, data): | |
self.data=data | |
self.dominio='' | |
self.DnsType='' | |
HDNS=data[-4:-2].encode("hex") | |
if HDNS == "0001": | |
self.DnsType='A' | |
elif HDNS == "000f": | |
self.DnsType='MX' | |
elif HDNS == "0002": | |
self.DnsType='NS' | |
elif HDNS == "0010": | |
self.DnsType="TXT" | |
else: | |
self.DnsType="Unknown" | |
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__': | |
parser = optparse.OptionParser() | |
parser.add_option("-f", "--filename", action="store", type="string",dest="SaveFile", help="input a filename to log output too") | |
(options, args) = parser.parse_args() | |
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 -> %s -> %s' % (addr[0], p.DnsType, p.dominio, ip) | |
if options.SaveFile: | |
MyDate=time.strftime('%Y %m %d') | |
MyTime=time.strftime('%H:%M:%S') | |
logfile = open(options.SaveFile,"a") | |
logfile.write('%s,%s,%s,%s,%s,%s\n' % (MyDate,MyTime,addr[0], p.DnsType,p.dominio,ip)) | |
logfile.close | |
except KeyboardInterrupt: | |
print 'Finalizando' | |
udps.close() | |
## end of http://code.activestate.com/recipes/491264/ }}} |
Retry with dig test.ru @127.0.0.1 +noedns
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An error in "gistfile1.py" and "Simple DNS server.py":
Server log:
Client log:
And there is no dns response