Beispiel #1
0
def handle_request(data, QDCOUNT, CONFIG, id, options):
    ind = 12
    name, QTYPE, _, ind = getName(data, ind)
    answer = b''
    try:
        z = easyzone.zone_from_file(name, CONFIG + 'example.com.conf')
        l = z.root.records(types[QTYPE]).items
        answer += struct.pack('!H', id)
        answer += struct.pack('!H', 33920)
        answer += struct.pack('!H', 0)
        answer += struct.pack('!H', len(l))
        answer += struct.pack('!H', 0)
        answer += struct.pack('!H', 0)
        for elem in l:
            answer += dec(name)
            answer += struct.pack('!H', QTYPE)
            answer += struct.pack('!H', 1)
            answer += struct.pack('!I', 0)
            res = decodeData(elem, QTYPE)
            answer += struct.pack('!H', len(res))
            answer += res
    except:
        if (name, QTYPE) in cache:
            return struct.pack("!H", id) + cache[(name, QTYPE)][2:]
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        _, res = get_address(('198.41.0.4', 53), name, sock)
        cache[(name, QTYPE)] = struct.pack("!H", id) + res[2:]
        return struct.pack("!H", id) + res[2:]
    return answer
Beispiel #2
0
def run_dns_server(configpath):
    # your code here
    #print(configpath)
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((ip, port))
    print("Listening on UDP {}:{}".format(*sock.getsockname()))

    while True:
        query_original, address_original = sock.recvfrom(buffer_size)

        query_original_in_shorts = unpack("!1H2B4H", query_original[0:12])

        header_fields = parse_dns_header(query_original_in_shorts)

        fields = parse_dns_question(query_original[12:])
        name = fields["domain_name"]
        exists = os.path.isfile('./zone_files/' + name + "conf")
        if (exists):
            zone = easyzone.zone_from_file(name,
                                           './zone_files/' + name + "conf")
            ips = zone.names[name].records('A').items
            #p = zone.names["www."].items
            info = {"ttl": zone.names[name].ttl, "ip": ips[0]}

            print("file is in the zone\n")

            resp = build_responce_A(query_original, info, name)
            sock.sendto(resp, address_original)

        else:
            print("start iterative search\n")
            iterative_query(query_original, sock, address_original,
                            fields["domain_name"], header_fields["id"])
Beispiel #3
0
def read_zone_files(directory):
    zones = []
    zone_files = listdir(directory)
    for zone_filename in zone_files:
        zone = easyzone.zone_from_file(
            zone_filename.split('conf')[0], directory + zone_filename)
        zones.append(zone)
    return zones
Beispiel #4
0
def makeResponse(data, config):

    #Transaction id
    tranID = bytes(data[0:2])

    # Flags
    reqflags = data[2:4]
    responseFlags = getRespFlags(reqflags)

    # QDCOUNT
    one = 1
    qdcount = one.to_bytes(2, 'big')

    # NSCOUNT AND ARCOUNT
    zero = 0
    nscount = zero.to_bytes(2, 'big')
    arcount = zero.to_bytes(2, 'big')

    # Domain and Question type
    (domain, qtype) = getDomainAndQType(data)

    try:
        z = easyzone.zone_from_file(domain, config + 'example.com.conf')

        # finish dns header
        ancount = len(z.root.records(qtypeValue(qtype)).items).to_bytes(
            2, 'big')
        header = tranID + responseFlags + qdcount + ancount + nscount + arcount

        # build question
        question = b''
        question += getDomainbytes(domain)
        print(';; QUESTION SECTION:')
        print(domain + '         IN   ' + qtypeValue(qtype))

        #add qtype and class
        question += qtype
        question += one.to_bytes(2, 'big')

        #build body
        body = b''

        print(';; ANSWER SECTION:')
        for item in z.root.records(qtypeValue(qtype)).items:
            body += b'\xc0\x0c'
            body += qtype
            body += one.to_bytes(2, 'big')
            ttl = 1800
            body += (ttl).to_bytes(4, 'big')
            body += lengthAndData(item, qtypeValue(qtype), ttl, domain)

        return header + question + body
    except:
        pass

    return recSearchResult(data, rootDnsServers, rootDnsServers)[0]
Beispiel #5
0
def read_conf():
	if os.path.isdir(path):
		for filename in os.listdir(path):
			full_path = path + "/" + filename
			if os.path.isfile(full_path):
				domain_name = filename[:filename.rfind(".")]
				zone = easyzone.zone_from_file(domain_name, full_path)
				local_zones.append(zone)

	else:
		print("Not directory")
		exit(1)	
Beispiel #6
0
def getZoneFiles(CONFIG):
    zFiles = []
    try:
        filenames = os.listdir(CONFIG)
        for zone in filenames:
            curZone = easyzone.zone_from_file(
                zone.split('.conf')[0], os.path.join(CONFIG, zone))
            zFiles.append(curZone)
            # print(curZone.names['example.com.'].records('A').items)
    except Exception:
        print('Error reading zonefiles\n')
    return zFiles
Beispiel #7
0
def getLocalAnswers(questions, CONFIG):
    answers = []
    unansweredQuestions = []
    isAuthoritative = 0
    ttl = 0
    zoneFiles = [easyzone.zone_from_file('example.com', CONFIG + 'example.com.conf'),
                 easyzone.zone_from_file('example2.com', CONFIG + 'example2.com.conf'),
                 easyzone.zone_from_file('FreeUniCN19.com', CONFIG + 'FreeUniCN19.com.conf')]
    for question in questions:
        answerLen = len(answers)
        qName = question['domainName']
        for zoneFile in zoneFiles:
            zoneDomainNames = zoneFile.get_names()
            if qName in zoneDomainNames:
                recordType = typeConstants[question['QTYPE']]
                if zoneDomainNames[qName].soa:
                    isAuthoritative = 1
                ttl = zoneDomainNames[qName].ttl
                answer = [record for record in zoneDomainNames[qName].records(recordType)]
                answers.append(answer)
                break
        if answerLen == len(answers):
            unansweredQuestions.append(question)
    return answers, isAuthoritative, ttl, unansweredQuestions
Beispiel #8
0
    def __init__(self, path) :
        self.cache, self.zones = {}, list(map(lambda zone: easyzone.zone_from_file(zone.split('.conf')[0], path + zone), listdir(path)))

        # Iterate over every zone
        for zone in self.zones :
            
            # Extract its domains and possible values
            for domain, name_obj in zone.get_names().items() :

                # Check for every single record type
                for record_type in types.values() :

                    record = name_obj.records(record_type)

                    #If we have any record for given type, add it to the cache
                    if record is not None : Cache.checkAndAdd(self, (domain, record_type), record.get_items())
Beispiel #9
0
def generate_query(requested_domain, requested_record, question_query, message):
	path = os.sys.argv[1]
	files = list()

	for filename in os.listdir(path):
		files.append(filename)

	print("Trying to find {} record on {}".format(requested_record, requested_domain))

	try:
		zone = easyzone.zone_from_file(requested_domain, '{}/{}'.format(path, requested_domain + '.conf'))
		if requested_record == 'CNAME':
				requested_record = 'SOA'
		header = generate_header(len(zone.root.records(requested_record).items))
		body = question_query + generate_body(requested_domain, requested_record, zone)
		print("Found {} record locally".format(requested_record))
	except:
		header, body = find_recursively(requested_domain, message)

	return header, body
Beispiel #10
0
def main():
    if len(sys.argv) != 3:
        usage()

    hostname, zonename = sys.argv[1].split('.', 1)
    zonefile = '/srv/ns/zones/%s.zone' % zonename

    z = easyzone.zone_from_file(zonename, zonefile)
    r = '%s.' % sys.argv[1]

    try:
        a = z.names[r].records('A')
    except KeyError:
        print 'error: %s record not found in %s' % (hostname, zonefile)
        exit(1)

    a.delete(a.items[0])
    a.add(sys.argv[2])
    z.save(autoserial=True)

    call('sudo /etc/init.d/nsd3 rebuild', shell=True)
    call('sudo /etc/init.d/nsd3 restart', shell=True)
Beispiel #11
0
# Python 'Module' object has no Attribute Error - Imported module
from easyzone import easyzone
z = easyzone.zone_from_file('example.com', '/var/namedb/example.com')
Beispiel #12
0
 def setUp(self):
     zone_file = os.path.join(os.path.dirname(__file__), 'files', 'example.com')
     self.zone = zone_from_file('example.com', zone_file)
Beispiel #13
0
def check_domain():
    data = request.json
    try:
        message = rsa.decrypt(
            binascii.a2b_base64(data['message'].encode('utf8')), pkey)
        payload = json.loads(message.decode('utf8'))
    except rsa.pkcs1.DecryptionError as e:
        response = app.response_class(status=400)
        return response
    except binascii.Error:
        response = app.response_class(status=400)
        return response
    except TypeError:
        response = app.response_class(status=400)
        return response
    else:
        print('im in')
        domain = payload['domain']
        subdomains = payload['subdomains']
        signature = binascii.a2b_base64(data['signature'])
        pubkey = rsa.PublicKey.load_pkcs1(
            open(WORKDIR + 'rsa/' + domain, 'r').read())
        ip = request.remote_addr
        try:
            verify = rsa.verify(message, signature, pubkey)
        except rsa.pkcs1.VerificationError:
            response = app.response_class(status=400)
            return response
        else:
            if verify:
                print('in verify')
                zone = easyzone.zone_from_file(domain,
                                               ZONEDIR + domain + '.db')
                names = zone.get_names()
                zone_change = False
                for dom in subdomains:
                    print(dom + domain + '.')
                    print(names)
                    if dom == '':
                        subdom = domain + '.'
                    else:
                        subdom = dom + '.' + domain + '.'
                    try:
                        print(names[subdom])
                        this = names[subdom]
                    except KeyError:
                        pass
                    else:
                        if this.records('A').items[0] != ip:
                            this.records('A').delete(
                                this.records('A').items[0])
                            this.records('A').add(ip)
                            zone_change = True
                if zone_change is True:
                    zone.save()
                    r = ZoneReload(rndc='/usr/sbin/rndc')
                    r.reload(domain)
                    print('Reload')
                response = app.response_class(status=200)
                print('pre return')
                return response
import os
from easyzone import easyzone
from Cookie import SimpleCookie
form = cgi.FieldStorage()
#form is Dnsmanager.py
dnsname = form.getlist("dname")
dnsname = str(dnsname)
dnsname = dnsname.strip("[']")
zoneNS = [] 
C = SimpleCookie()
C["Current-domain-name"] = dnsname # Explicit variable name PLEASE!!!111oneoneone
try:
	#Standard notation of open doesn't work for easyzone.zone_from_file
	zonename = "%s" % dnsname
	filename = "/var/cache/bind/%s" % dnsname
	f = easyzone.zone_from_file(zonename, filename)
except :
	#Todo : Make a real error message and a real error handling
	print "content-type:text/html"
	print
	print '<html>'
	print '<head>'
	print '</head>'
	print '<body>'
	print "The dev was too lazy to narrow the error type so... error!"
	print "prout<br>"
	print dnsname + "test"
	print "file name is "
	print '</body>'
	print '</html>'
#f is the file opened by zone_from_file... yeah yeah i know, very explicit variable name
def updateSoa(cbot_json):
    z = easyzone.zone_from_file(myDomain(cbot_json),
                                myUnsignedRefFname(cbot_json, '.ref.soa'))
    print(z.root.soa.serial)
    z.save(autoserial=True)
Beispiel #16
0
	def handle(self, filename, zonename, keyfile, checkzone, *args, **options):
		if not filename:
			print "Must supply valid filename"
			exit(-1)
		if not zonename:
			print "Must supply valid zonename"
			exit(-1)
		if zonename[-1] != '.':
			zonename += '.'
		# Check the zone
		c = ZoneCheck(checkzone=checkzone)
		if not c.isValid(zonename, filename):
			print "Invalid zone"
			exit(-1)

		z = easyzone.zone_from_file(zonename, filename)
		
		if len(DNSZone.objects.filter(zonename=zonename)) == 0:
			dnsz = DNSZone()
			dnsz.zonename = zonename
			dnsz.ttl = z.root.soa.minttl
			dnsz.rndckey = keyfile
			#fk email to a user?
			dnsz.email = '*****@*****.**'
			dnsz.serial = z.root.soa.serial
			dnsz.refresh = z.root.soa.refresh
			dnsz.retry = z.root.soa.retry
			dnsz.expire = z.root.soa.expire
			dnsz.minimum = z.root.soa.minttl
			dnsz.save()
		else:
			dnsz = DNSZone.objects.get(zonename=zonename)
		
		#We want to populate the A and AAAA records first, else we wont have integrity for the other records.
		for rtype in ('A', 'AAAA', 'MX', 'PTR', 'TXT', 'SRV', 'CNAME', 'NS', 'HINFO'):
			for r in z.names:
				try:
					for rec in z.names[r].records(rtype).items:
						#Check if the record exists or not
						if len(DNSRecord.objects.filter(type=rtype,record=rec,fqdn=r)) == 0:
							dr = DNSRecord()
							dr.zone = dnsz
							dr.type = rtype
							if rtype == 'MX':
								rec = '%s %s' % rec
							if rtype not in ('A', 'AAAA'):
								dr.record = rec
							dr.active= True
							dr.ttl = dnsz.ttl
							dr.fqdn = r
							if rtype in ('A', 'AAAA'):
								try:
									a = Address.objects.get(address=rec)
								except Address.DoesNotExist:
									a = Address()
									a.host = None
									a.type = 6
									if rtype == 'A':
										a.type = 4
									a.vlan = 0
									a.hwid = None
									a.address = rec
									a.save()
								dr.address = a
							dr.save()
							print dr
							# TODO We should check if a DNAME to relate to a different zone .... ?
							if rtype in ('MX', 'CNAME', 'NS', 'PTR', 'TXT', 'SRV'):
								test = rec.split(' ')[-1]
								#We should also split the rec if possible - last field is our related name in SRV / MX
								related = DNSRecord.objects.filter(Q(fqdn=test) , Q(type='A') | Q(type='AAAA'))
								for x in related:
									dr.dnsrecord.add(x)
							dr.save()
							#Check if this object exists in our model (host, address and type)
							#If we find a host by this FQDN, tie the address to it. Else skip and add address / record.
				except ValueError as e:
				#	#pass
					print 'EXCEPTION ON:' + r + ':' + rtype + ' ;;ValueError; ' + e.message
				except AttributeError as e:
					pass
				except TypeError as e:
					print 'EXCEPTION ON:' + r + ':' + rtype + ' ;;TypeError; ' + e.message
					print traceback.print_tb(sys.exc_info()[2] )
Beispiel #17
0
from easyzone import easyzone
from os import listdir
from os.path import isfile, join
import time

#Run other script to append static.* zones to the end of db.* zones

mergedZonesPath = "./mergedzones/"

allZones = [
    f for f in listdir(mergedZonesPath) if isfile(join(mergedZonesPath, f))
]

#import each zone then update serial and rname
for currentZoneFile in allZones:
    ez = easyzone.zone_from_file(currentZoneFile,
                                 mergedZonesPath + currentZoneFile)
    ez.root.soa.serial = time.strftime('%Y%m%d00')
    ez.root.soa.rname = currentZoneFile
    ez.save()
Beispiel #18
0
 def parse_config_files(self, path, file_name):
     ind = file_name.find(".conf")
     domain = file_name[:ind]
     self.config_data[domain] = easyzone.zone_from_file(
         domain, path + file_name)
Beispiel #19
0
def fill_from_config_files(config_path: str, dns_retriever: DnsRetriever):
    for filename in os.listdir(config_path):
        domain_name = filename[:-4]
        dns_retriever.zone_files[domain_name] = easyzone.zone_from_file(
            domain_name, config_path + "/" + filename)
def run_dns_server(CONFIG, IP, PORT):
    sock = createSocket()
    sock.bind((IP, int(PORT)))

    idx = 0
    CACHER = dict()
    ROOT = ['198.41.0.4', '199.7.91.13']

    while True:
        data, address = sock.recvfrom(4096)
        print('starting up on {} port {}'.format(IP, PORT))

        s = struct.unpack('! H 5h', data[:12])
        ID, QR = s[0], s[1]
        QN, ANS = s[2], s[3]
        questions = data[12:]

        QName, questions, tot = readQName(data, questions)
        QType, questions = struct.unpack('!h', questions[:2])[0], questions[2:]
        QClass, questions = struct.unpack('!h',
                                          questions[:2])[0], questions[2:]
        print('QUESTION SECTION: {}   Type:{}  128   IN  {}'.format(
            QName, QType, IP))

        key = (QName, QType)
        if key in CACHER:
            RESP = data[:2] + CACHER[key]
            sock.sendto(RESP, address)
            continue

        local = True
        RESPONSE, ALL_ANSWERS = b'', b''
        try:
            ez = easyzone.zone_from_file(QName[:-1], CONFIG + QName + 'conf')
        except:
            local = False

        if QType == 1:  #A
            if local:
                for ip in ez.root.records('A').items:
                    RDATA = ipaddress.IPv4Address(ip).packed
                    ANSWER, ANS = make_answer(QName, QType, QClass, 0, RDATA,
                                              ANS)
                    ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue
        elif QType == 2:  #NS
            if local:
                for ns in ez.root.records('NS').items:
                    RDATA = make_off_sets(ns)
                    ANSWER, ANS = make_answer(QName, QType, QClass, 128, RDATA,
                                              ANS)
                    ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue
        elif QType == 5:  #CName
            if local:
                for cn in ez.root.records('CNAME').items:
                    RDATA = make_off_sets(cn)
                    ANSWER, ANS = make_answer(QName, QType, QClass, 10, RDATA,
                                              ANS)
                    ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue
        elif QType == 6:  #SOA
            if local:
                soa = ez.root.records('SOA').items[0].split(' ')
                RDATA = make_off_sets(soa[0])
                RDATA += make_off_sets(soa[1])
                RDATA += int(soa[2]).to_bytes(4, 'big')
                RDATA += int(soa[3]).to_bytes(4, 'big')
                RDATA += int(soa[4]).to_bytes(4, 'big')
                RDATA += int(soa[5]).to_bytes(4, 'big')
                RDATA += int(soa[6]).to_bytes(4, 'big')
                ANSWER, ANS = make_answer(QName, QType, QClass, 10, RDATA, ANS)
                ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue
        elif QType == 15:  #MX
            if local:
                for mx in ez.root.records('MX').items:
                    RDATA = mx[0].to_bytes(2, 'big')
                    RDATA += make_off_sets(mx[1])
                    ANSWER, ANS = make_answer(QName, QType, QClass, 10, RDATA,
                                              ANS)
                    ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue

        elif QType == 16:  #TXT
            if local:
                txt = ez.root.records('TXT').items[0].encode()
                RDATA = len(txt).to_bytes(1, 'big') + txt
                ANSWER, ANS = make_answer(QName, QType, QClass, 10, RDATA, ANS)
                ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                CACHER[key] = RESPONSE[2:]
                sock.sendto(RESPONSE, address)
                continue
        elif QType == 28:  #AAAA
            if local:
                for ip in ez.root.records('AAAA').items:
                    RDATA = ipaddress.IPv6Address(ip).packed
                    ANSWER, ANS = make_answer(QName, QType, QClass, 10, RDATA,
                                              ANS)
                    ALL_ANSWERS += ANSWER
            else:
                RESPONSE = askRoot(data, ROOT[idx], createSocket())
                sock.sendto(RESPONSE, address)
                CACHER[key] = RESPONSE
                continue
        if local: QR = 33920
        else: QR = 33792

        RESPONSE += data[:2]
        RESPONSE += struct.pack('!H', QR)
        RESPONSE += struct.pack('!h', QN)
        RESPONSE += struct.pack('!h', ANS)
        RESPONSE += data[8:]
        RESPONSE = RESPONSE[:(16 + tot)]
        RESPONSE += ALL_ANSWERS

        if data:
            CACHER[key] = RESPONSE[2:]
            sent = sock.sendto(RESPONSE, address)
            print('sent {} bytes back to {}'.format(sent, address))
    pass