def _add_authority(domain, auth_list): """ Given a domain and an authority set, this function will add the UH DNS nameservers to the set if they don't already exist. :param domain: Domain to be authoritative over. :param auth_list: Auth set to add to. """ record1 = dnslib.RR(rname=domain, rtype=dnslib.QTYPE.NS, rdata=dnslib.NS("ns1.uh-dns.com"), ttl=3600) record2 = dnslib.RR(rname=domain, rtype=dnslib.QTYPE.NS, rdata=dnslib.NS("ns2.uh-dns.com"), ttl=3600) if record1 not in auth_list: auth_list.append(record1) if record2 not in auth_list: auth_list.append(record2)
def gen_response(qt, qn): global serving_domains prefix_ = list( filter(lambda d: qn == d or qn.endswith('.' + d), serving_domains)) if len(prefix_) != 1: # print("Error: invalid request domain {} in {}".format(qn, serving_domains)) return None prefix = prefix_[0] print('REQ: ', qt, qn) if qt == 'SOA': generated_soa = dnslib.SOA( mname="todo." + domain_text, rname="*****@*****.**", times=( 201307231, # serial number 10000, # refresh 2400, # retry 604800, # expire 3600, # minimum )) return RR(rname=prefix, rtype=QTYPE.SOA, rclass=1, ttl=86400, rdata=generated_soa) # return {"mname": "todo."+domain_text, "rname": "*****@*****.**", "serial": "10", "refresh": 3600, "retry": 600, "expire": 604800, "minimum": 86400} elif qt == 'A': requested_ip = qn[:len(qn) - len(prefix)].strip('.') if not re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', requested_ip): print("Invalid requested_ip: " + requested_ip) return None generated_a = dnslib.A(requested_ip) return RR(rname=qn, rtype=QTYPE.A, rclass=1, ttl=86400, rdata=generated_a) elif qt == 'NS': generated_ns = dnslib.NS(ns_ipaddr) return RR(rname=prefix, rtype=QTYPE.NS, rclass=1, ttl=86400, rdata=generated_ns) else: print("Invalid qt=" + qt) return None
def _ns_search(record, rr_list, addi_list): """ Searches and adds any NS records for the domain. :param record: Overall record for domain :param rr_list: Current record list for the domain :param addi_list: Additional list for the domain """ try: ns_record = record["NS"] ttl = int(ns_record["ttl"]) for ns in ns_record["value"]: rr_list.append(dnslib.RR(rname = record["domain"], rtype = dnslib.QTYPE.NS, rdata = dnslib.NS(label = ns), ttl = ttl)) _add_additional(addi_list) except: pass
def __init__(self, upstream): super().__init__(upstream, 53, 5) if confs.SOA_MNAME and confs.SOA_RNAME: self.SOA = dnslib.SOA( mname=DNSLabel(confs.SOA_MNAME), rname=DNSLabel(confs.SOA_RNAME.replace( '@', '.')), # TODO: . before @ should be escaped times=( confs.SOA_SERIAL, # serial number 60 * 60 * 1, # refresh 60 * 60 * 2, # retry 60 * 60 * 24, # expire 60 * 60 * 1, # minimum )) else: self.SOA = None if confs.NS_SERVERS: self.NS = [dnslib.NS(i) for i in confs.NS_SERVERS] else: self.NS = []
def add_answer_to_query(required_data, query): qtype = query.q.qtype q = query.q # Для каждого типа запроса добавляем интересующий ответ if qtype == dnslib.QTYPE.A: # Добавляем все A адреса for addr in required_data.addresses: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.A(addr))) if qtype == dnslib.QTYPE.AAAA: # Добавляем все AAAA адреса for addr in required_data.addresses: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.AAAA(addr))) if qtype == dnslib.QTYPE.NS: # Добавляем все NS серверы for addr in required_data.servers: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.NS(addr))) if qtype == dnslib.QTYPE.PTR: # Добавляем PTR query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.PTR(required_data.name)))
def resolve(self, request, handler): question = request.get_q() req_name = str(question.get_qname()) # TXT = 16 reply = request.reply() pivot = req_name.rfind("_tox.") if pivot == -1: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply name = req_name[:pivot].rstrip(".") suffix = req_name[pivot:] domain = suffix[5:].rstrip(".") if question.qtype == 16: if not name and domain in self.workable_domains: data = self.cryptocore.public_key.encode("ascii") reply.add_answer( dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(data))) return reply first_try = self.try_tox3_resolve(reply, name, domain, req_name) if not first_try: return self.try_tox1_resolve(reply, name, domain, req_name) else: return first_try elif question.qtype == 2: reply.add_answer( dnslib.RR(req_name, 2, ttl=86400, rdata=dnslib.NS(self.home))) return reply else: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply return reply
def resolve(self, request, handler): question = request.get_q() req_name = str(question.get_qname()) # TXT = 16 reply = request.reply() suffix = "._tox.{0}".format(self.ireg) if question.qtype != 16 and not req_name.endswith(self.ireg): reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply if question.qtype == 16: if req_name == suffix[1:]: reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(self.cryptocore.public_key.encode("ascii")))) return reply if not req_name.endswith(suffix): reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply user_name = req_name[:req_name.rfind(suffix)] if len(user_name) > NAME_LIMIT_HARD and user_name[0] == "_": encrypted = user_name.replace(".", "")[1:] try: b = notsecure32_decode(encrypted) nonce = b[:4] + (b"\0" * 20) ck = b[4:36] payload = b[36:] name = self.cryptocore.dsrep_decode_name(ck, nonce, payload) except Exception: print("error >_<") reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply rec = self.store.get(name.decode("utf8")) if not rec: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply base = b"v=tox3;id=" if rec.pin: r_payload = "{0}{1}{2}".format(rec.public_key, rec.pin, rec.checksum) else: r_payload = "{0}00000000{1}".format(rec.public_key, rec.checksum) msg = binascii.unhexlify(r_payload) nonce_reply = b[:4] + b"\x01" + (b"\0" * 19) ct = self.cryptocore.dsrec_encrypt_key(ck, nonce_reply, msg) key_part = notsecure32_encode(ct) reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(b"".join((base, key_part))))) return reply else: rec = self.store.get(user_name) if not rec: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply else: reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(rec.record(0) .encode("utf8")))) return reply elif question.qtype == 6: self.update_soa() reply.add_answer(self.soa) return reply elif question.qtype == 2: for name in self.authority_list: reply.add_answer(dnslib.RR(req_name, 2, ttl=86400, rdata=dnslib.NS(name.encode("utf8")) )) return reply elif question.qtype == 1 and self.home_addresses: for ip in self.home_addresses: reply.add_answer(dnslib.RR(req_name, 1, ttl=3600, rdata=dnslib.A(ip))) elif question.qtype == 28 and self.home_addresses_6: for ip in self.home_addresses_6: reply.add_answer(dnslib.RR(req_name, 28, ttl=3600, rdata=dnslib.AAAA(ip))) else: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply return reply
class BaseRequestHandler(socketserver.BaseRequestHandler): fIP = {} D = DomainName('0h0.us.') IP = '18.219.234.8' TTL = 60 * 1 soa_record = dnslib.SOA( mname=D.ns1, # primary name server times=( 22118400, # serial number 60 * 60 * 1, # refresh 60 * 60 * 3, # retry 1 * 1 * 1, # expire 1 * 1 * 1, # minimum )) ns_records = [dnslib.NS(D.ns1), dnslib.NS(D.ns2)] records = { D: [dnslib.A(IP), dnslib.AAAA((0, ) * 16), soa_record] + ns_records, D.ns1: [ dnslib.A(IP) ], # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3) D.ns2: [dnslib.A(IP)] } def progressBar(self, c, tot, status): bar = 40 filled = int(round(bar * (tot - c) / float(tot))) pct = round(100.0 * (tot - c) / float(tot), 1) barstr = '=' * filled + '-' * (bar - filled) sys.stdout.write('[%s] %s%s ...%s\r' % (barstr, pct, '%', status)) sys.stdout.flush() def processRequest(self, request): reply = dnslib.DNSRecord(dnslib.DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) qname = request.q.qname qn = str(qname) qtype = request.q.qtype qt = dnslib.QTYPE[qtype] if qn == self.D or qn.endswith('.' + self.D): for name, rrs in self.records.items(): if name == qn: for rdata in rrs: rqt = rdata.__class__.__name__ if qt in ['*', rqt]: reply.add_answer( dnslib.RR(rname=qname, rtype=getattr(dnslib.QTYPE, rqt), rclass=1, ttl=self.TTL, rdata=rdata)) for rdata in self.ns_records: reply.add_ar( dnslib.RR(rname=self.D, rtype=dnslib.QTYPE.NS, rclass=1, ttl=self.TTL, rdata=rdata)) reply.add_auth( dnslib.RR(rname=self.D, rtype=dnslib.QTYPE.SOA, rclass=1, ttl=self.TTL, rdata=self.soa_record)) for question in request.questions: if (question.qtype == dnslib.QTYPE.TXT): #only process TXT record requests content = str(question.qname)[:-1] if content.endswith(self.D[:-1]): content = content[:-len(self.D[:-1]) - 1] key = content[:4] if key in self.fIP: content = str(content[4:]) self.fIP[key][3] += content self.fIP[key][1] -= len(content) #print(key, content,len(content),self.fIP[key][1] ) #print("Left: "+str(self.fIP[sIP][1])) self.progressBar( self.fIP[key][1], self.fIP[key][4], "Receiving '" + self.fIP[key][0] + "' with index " + key) reply.add_answer( dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT(content))) #reply.add_answer(dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT("OK"))) if (self.fIP[key][1] == 0): #we have received the entire file. Time to write it. content_decoded = base64.standard_b64decode( self.fIP[key][3]) with open(self.fIP[key][0], 'wb') as newfile: newfile.write(content_decoded) hashedWord = md5(content_decoded).hexdigest() if (self.fIP[key][2] == hashedWord): print("\nFile successfully received") reply.add_answer( dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT("OK"))) else: print("\nFile received but failed hash:") reply.add_answer( dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT("FAIL HASH"))) del self.fIP[key] else: # new connection. we expect a file name print("New file:", content) parts = content.split("|") if (len(parts) == 3): #we have valid request print("new file upload: ", content) self.fIP[parts[2][:4]] = [ os.path.basename(parts[0]), int(parts[1]), parts[2], "", int(parts[1]) ] reply.add_answer( dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT("OK"))) else: reply.add_answer( dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.A(self.IP))) #print("responding:",reply) return reply.pack()
def py3dns(serverip='', serverport=0): class DNSify(str): def __getattr__(self, item): return DNSify(item + '.' + self) def get_lan_ip4(forcelocalhost=False): if forcelocalhost: return '127.0.0.1' s = dnslib.socket.socket(dnslib.socket.AF_INET, dnslib.socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 0)) IP = s.getsockname()[0] except: IP = '127.0.0.1' finally: s.close() return IP def is_domain_blacklisted(sqname, domain_blacklist): for test_domain in domain_blacklist: if test_domain in sqname: return True return False # Init server settings killcommand = 'stop.py3dns.now' serve_forever = True udp_buffer_size = 1024 server_name = dnslib.socket.getfqdn() server_ip = get_lan_ip4() if serverip: server_ip = serverip reverse_server_ip = '.'.join(reversed( server_ip.split('.'))) + '.in-addr.arpa' server_port = 53 if serverport: server_port = int(serverport) server_protocol = 'UDP' public_dns_resolvers = [ '91.239.100.100', '89.233.43.71', '8.8.8.8', '8.8.4.4' ] # Init simple host cache host_cache = {} host_cache[server_ip] = server_name # Init blacklists use_blacklists = True domain_blacklist = make_domain_blacklist() ipaddr_blacklist = make_ipaddr_blacklist() rpz_domain = DNSify('getthefuckaway.net') rpz_ip4 = '10.20.30.40' rpz_ip6 = '10:20:30:40:50:60:70:80' # Init UDP socket server udpsrv = dnslib.socket.socket(dnslib.socket.AF_INET, dnslib.socket.SOCK_DGRAM) udpsrv.bind((server_ip, server_port)) udpsrv.setblocking(False) # Init external resolvers external_resolver = dns.resolver.Resolver() external_resolver_cache = dns.resolver.Cache(cleaning_interval=600.0) external_resolver.cache = external_resolver_cache external_resolver.nameservers = public_dns_resolvers external_resolver.retry_servfail = False external_resolver.port = 53 ##external_resolver.timeout = 1.0 ##external_resolver.lifetime = 2.0 # Timestamp UTC now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') # App Header print('+' + ('-' * 71)) print('| PY3DNS v/1.0 by BikerDroid') print('+' + ('-' * 71)) print('| Server :', server_name) print('| Address :', server_ip) print('| Port Used :', server_port) print('| Protocol :', server_protocol) print('| Recv Size :', udp_buffer_size, 'bytes') print('| Solvers :', str(public_dns_resolvers).strip("[]").replace("'", "")) print('+' + ('-' * 71)) print('| Stop PY3DNS by sending "nslookup ' + killcommand + ' ' + server_ip + '"') print('+' + ('-' * 71)) print(now, ': Ready to serve...') # Main Loop while serve_forever: # Clear vars sres = sip4 = sip6 = smx = scname = sns = stxt = sptr = ssoa = sany = hostip = '' # Main: Get client request, add hostip and host name to host_cache try: data, addr = udpsrv.recvfrom(udp_buffer_size) hostip = str(addr[0]) if not hostip in host_cache: host_cache[hostip] = dnslib.socket.getfqdn( str(dnslib.socket.gethostbyaddr(hostip)[0])) now = datetime.datetime.utcnow().strftime( '%Y-%m-%d %H:%M:%S.%f') # UTC except: continue # Client request -> id, qname (domain), qtype (A,AAAA,MX etc) request = dnslib.DNSRecord.parse(data) qid = request.header.id qname = request.q.qname qtype = request.q.qtype slabel = str(qname.label) sqname = str(qname) sqtype = str(dnslib.QTYPE[qtype]) # Rem this line if rpz_domain is to overwrite # blacklisted domains with their real names. sdomain = sqname # Dirty trick to shut down server from commandline: # Syntax : nslookup stop.dns.srv <server_ip> # Example: nslookup stop.dns.srv 127.0.0.1 # Must be before external_resolver.query() if sqname.rstrip('.') == killcommand: serve_forever = False continue # Dirty Reverse Lookup of local server # Allows requesting client to get server_name if qtype == dnslib.QTYPE.PTR: if sqname.rstrip('.') == reverse_server_ip: reply = dnslib.DNSRecord(header=dnslib.DNSHeader(id=qid, qr=1, aa=1, ra=1, rcode=0), q=dnslib.DNSQuestion(sqname, qtype)).reply() reply.add_answer( dnslib.RR(sqname, dnslib.QTYPE.PTR, rdata=dnslib.PTR(server_name), ttl=3600)) udpsrv.sendto(reply.pack(), addr) print(now, ':', sqname, '|', sqtype, '=', qtype, '|', server_name, '|', hostip, '=', host_cache[hostip]) continue # Get DNS record from public_dns_resolvers. # This section can be changed to serve from # own database, stationary files or similar. try: if not sqname.rstrip('.') in domain_blacklist: external_resolver_result = external_resolver.query( sqname.rstrip('.'), sqtype) found = True except: print(now, '> qtype', sqtype, '(' + str(qtype) + ') was not found for', sqname) external_resolver_result = [] sres = sip4 = sip6 = '' found = False if not found: # Create DNSRecord Header reply: rcode = 5 (Query Refused). See RFC2136 for rcode's. reply = dnslib.DNSRecord(header=dnslib.DNSHeader(id=qid, qr=1, aa=1, ra=1, rcode=5), q=dnslib.DNSQuestion(sdomain, qtype)).reply() else: # Create DNSRecord Header reply: rcode = 0 (No Error) reply = dnslib.DNSRecord(header=dnslib.DNSHeader(id=qid, qr=1, aa=1, ra=1, rcode=0), q=dnslib.DNSQuestion(sdomain, qtype)).reply() # Add A record answer for domain and IP # Filter blacklisted IP4/6 addresses. if qtype == dnslib.QTYPE.A: if is_domain_blacklisted( sqname.rstrip('.'), domain_blacklist): # Simple domain blacklist check sres = sip4 = rpz_ip4 reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.A, rdata=dnslib.A(sip4), ttl=60)) else: for data in external_resolver_result: sres = sip4 = str(data).strip() if sip4: if sip4 in ipaddr_blacklist: # Simple IP (4+6) blacklist check sres = sip4 = rpz_ip4 reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.A, rdata=dnslib.A(sip4), ttl=60)) # Add AAAA record answer for domain and IP # Filter blacklisted IP4/6 addresses. elif qtype == dnslib.QTYPE.AAAA: if is_domain_blacklisted( sqname.rstrip('.'), domain_blacklist): # Simple domain blacklist check sres = sip6 = rpz_ip6 reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.AAAA, rdata=dnslib.AAAA(sip6), ttl=60)) else: for data in external_resolver_result: sres = sip6 = str(data).strip() if sip6: if sip6 in ipaddr_blacklist: # Simple IP (4+6) blacklist check sres = sip6 = rpz_ip6 reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.AAAA, rdata=dnslib.AAAA(sip6), ttl=60)) # Add NS record answer for domain elif qtype == dnslib.QTYPE.NS: for data in external_resolver_result: sres = sns = str(data).strip() if sns: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.NS, rdata=dnslib.NS(sns), ttl=60)) # Add MX record answer for domain and IP elif qtype == dnslib.QTYPE.MX: for data in external_resolver_result: sres = smx = str(data).strip() if smx: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.MX, rdata=dnslib.MX(smx), ttl=60)) # Add CNAME record answer for domain elif qtype == dnslib.QTYPE.CNAME: for data in external_resolver_result: sres = scname = str(data).strip() if scname: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.CNAME, rdata=dnslib.CNAME(scname), ttl=60)) # Add TXT record answer for domain elif qtype == dnslib.QTYPE.TXT: for data in external_resolver_result: sres = stxt = str(data).strip() if stxt: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.TXT, rdata=dnslib.TXT(stxt), ttl=60)) # Add PTR record answer for domain elif qtype == dnslib.QTYPE.PTR: for data in external_resolver_result: sres = sptr = str(data).strip() if sptr: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.PTR, rdata=dnslib.PTR(sptr), ttl=60)) # Add ANY record answer for domain elif qtype == dnslib.QTYPE.ANY: for data in external_resolver_result: sres = sany = str(data).strip() if sany: reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.ANY, rdata=dnslib.ANY(sany), ttl=60)) # Add SOA record answer for domain elif qtype == dnslib.QTYPE.SOA: for data in external_resolver_result: if str(data).strip(): soa_data = str(data).strip().split(' ') soa_mname = soa_data[0] soa_rname = soa_data[1] soa_serial = soa_data[2] soa_refresh = soa_data[3] soa_retry = soa_data[4] soa_expire = soa_data[5] soa_minimum = soa_data[6] soa_time = (int(soa_serial), int(soa_refresh), int(soa_retry), int(soa_expire), int(soa_minimum)) sres = soa_mname + ',' + soa_rname + ',' + soa_serial + ',' + soa_refresh + ',' + soa_retry + ',' + soa_expire + ',' + soa_minimum reply.add_answer( dnslib.RR(sdomain, dnslib.QTYPE.SOA, rdata=dnslib.SOA(soa_mname, soa_rname, soa_time), ttl=60)) else: # Unknown qtype - add CNAME as answer :) reply.add_answer( dnslib.RR(qname, dnslib.QTYPE.CNAME, rdata=dnslib.CNAME(server_name), ttl=60)) # Send DNS reply to client address using UDP udpsrv.sendto(reply.pack(), addr) # Show status in console print(now, ':', sqname, '|', sqtype, '=', qtype, '|', sres, '|', hostip, '=', host_cache[hostip]) #,reply.pack() # Shutting down print(now, ': Shutting down...') udpsrv.shutdown(0) print(now, ': Done.')
def parse_server_config(server_config): import copy _server_config = copy.deepcopy(server_config) dns_servers = _server_config.get('dns_servers', []) for server in dns_servers: # parse url scheme, hostname, port = DNSServerLoader.parse_url(server['url']) server['scheme'] = scheme server['hostname'] = hostname server['port'] = port # parse rules for rule in server['rules']: rtype = rule['type'] if rule['domain-type'] in ('FQDN', 'PREFIX', 'SUFFIX'): rule['domain'] = DNSLabel(rule['domain']) if rtype == 'FORWARD': _scheme, _hostname, _port = DNSServerLoader.parse_url(rule['value']) rule['pvalue'] = { 'scheme': _scheme, 'hostname': _hostname, 'port': _port, 'url': _scheme + '://' + _hostname + ':' + str(_port) } elif rtype in ('A', 'CNAME', 'MX', 'NS', 'PTR', 'AAAA', 'SRV', 'SOA'): if isinstance(rule['value'], six.string_types): rule['value'] = [rule['value']] if rtype == 'A': rule['pvalue'] = [dnslib.A(item) for item in rule['value']] elif rtype == 'CNAME': rule['pvalue'] = [dnslib.CNAME(DNSLabel(item)) for item in rule['value']] elif rtype == 'MX': rule['pvalue'] = [dnslib.MX(DNSLabel(item)) for item in rule['value']] elif rtype == 'NS': rule['pvalue'] = [dnslib.NS(DNSLabel(item)) for item in rule['value']] elif rtype == 'PTR': rule['pvalue'] = [dnslib.PTR(DNSLabel(item)) for item in rule['value']] elif rtype == 'AAAA': rule['pvalue'] = [dnslib.AAAA(item) for item in rule['value']] elif rtype == 'SRV': srv_arr = [] for item in rule['value']: item_arr = item.split(' ') srv_arr.append(dnslib.SRV( priority=num.safe_int(item_arr[0]), weight=num.safe_int(item_arr[1]), port=num.safe_int(item_arr[2]), target=item_arr[3])) rule['pvalue'] = srv_arr elif rtype == 'SOA': soa_arr = [] for item in rule['value']: item_arr = item.split(' ') soa_arr.append(dnslib.SOA( mname=DNSLabel(item_arr[0]), rname=DNSLabel(item_arr[1]), times=(num.safe_int(t) for t in item_arr[2:]) # serial, refresh, retry, expire, minimun )) rule['pvalue'] = soa_arr return dns_servers
def dns_resolve(self, query, tcp): """ Resolves DNS request from one client at the time. Encodes its actual data and forms DNS response from it. """ request = dns.DNSRecord.parse(query) reply = request.reply() domain = request.q.get_qname() qtype = request.q.qtype data = exf.domain_decode(str(domain), base64.urlsafe_b64decode) # If encryption key is present - decode it for futher data decryption if (len(request.questions) > 1): enc_domain = str(request.questions[1].get_qname()) enc_key = exf.domain_decode(enc_domain, base64.urlsafe_b64decode) # Descramble key enc_key = exf.scramble(enc_key, (4, 12), True) # Check if the key is scramble offset if len(enc_key) < 3: enc_key = tuple(enc_key) data = exf.scramble(data, enc_key, True) # Or AES decryption key else: enc_key = enc_key.decode() data = exf.aes_decrypt(data, enc_key) # reply.add_question(request.questions[1]) if DEBUG: print_with_time("***", f"DNS QTYPE is {qtype}") print_with_time("***", f"Original data length {len(data)} bytes") print_with_time("***", f"{data[:24]}...") data = base64.b64encode(data) core_domain = deepcopy(domain) # Get TLD domain from original object core_domain.label = domain.label[-2:] if (qtype == dns.QTYPE.A): data = exf.ip_encode(data, False) elif (qtype == dns.QTYPE.AAAA): data = exf.ip_encode(data, True) elif (qtype == dns.QTYPE.TXT): data = [dns.TXT(data)] elif (qtype == 10): # NULL type data = [dns.RD(data)] else: data = exf.domain_encode(data, str(core_domain), base64.urlsafe_b64encode) if (qtype == dns.QTYPE.CNAME): data = [dns.CNAME(data)] elif (qtype == dns.QTYPE.MX): data = [dns.MX(data)] elif (qtype == dns.QTYPE.NS): data = [dns.NS(data)] for rd in data: reply.add_answer(dns.RR(str(domain), rtype=qtype, rdata=rd)) raw_reply = reply.pack() # Truncate large (> 512 bytes) data for UDP payload if (len(raw_reply) > exf.MAX_DNS_LEN and not tcp): print_with_time("DNS", f"Response message is big! Truncate it...") reply.header.set_tc(1) raw_reply = reply.pack()[:exf.MAX_DNS_LEN] print_with_time("DNS", f"Sending back the request in size {len(raw_reply)} bytes\n") return raw_reply