def _add_additional(addi_list): """ Given a domain and an additional set, this function will add the A records for the UH DNS nameservers to the set. :param addi_list: Additional set to add to. """ if addi_list == []: addi_list.append( dnslib.RR(rname="ns1.uh-dns.com.", rtype=dnslib.QTYPE.A, rdata=dnslib.A("18.130.161.247"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns1.uh-dns.com.", rtype=dnslib.QTYPE.AAAA, rdata=dnslib.AAAA("2a05:d01c:35b:7601::4"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns2.uh-dns.com.", rtype=dnslib.QTYPE.A, rdata=dnslib.A("18.130.86.161"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns2.uh-dns.com.", rtype=dnslib.QTYPE.AAAA, rdata=dnslib.AAAA("2a05:d01c:35b:7600::4"), ttl=3600))
async def _get_record(self, request, client_writer): domain = str(request.questions[0].qname)[:-1] qtype = request.questions[0].qtype logger.info('dns_request: %s, %s', domain, qtype) if not self.conf.GET_PROXY.isgfwed_resolver(domain): # try resolve with getaddrinfo first logger.debug('not gfwed.') if qtype in (dnslib.QTYPE.A, dnslib.QTYPE.AAAA, dnslib.QTYPE.ANY): result_list = await resolve(domain, 0) response = request.reply() for result in result_list: if result[0] == socket.AF_INET and qtype in ( dnslib.QTYPE.A, dnslib.QTYPE.ANY): response.add_answer( dnslib.RR(domain, dnslib.QTYPE.A, rdata=dnslib.A(result[1]))) elif result[0] == socket.AF_INET6 and qtype in ( dnslib.QTYPE.AAAA, dnslib.QTYPE.ANY): response.add_answer( dnslib.RR(domain, dnslib.QTYPE.AAAA, rdata=dnslib.AAAA(result[1]))) return response await self.tcp_dns_record(request, client_writer)
def _alias_search(q_type, record, rr_list, auth_list, addi_list): """ If no A or AAAA records exist this function will add any fixed alias records. :param q_type: Query type (A or AAAA) alias records accepted. :param record: Record from DB. :param rr_list: resource record list. :param auth_list: authority list. :param addi_list: additional list. """ try: alias_record = record["ALIAS"] ttl = int(alias_record["ttl"]) question = dnslib.DNSRecord.question(alias_record["domain"], qtype=dnslib.QTYPE[q_type]) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(1) sock.bind(("", 0)) # Bind to any available IP and port. sock.sendto(question.pack(), ("10.0.0.2", 53)) res = dnslib.DNSRecord.parse(sock.recv(4096)) sock.close() for r in res.rr: ip = str(r.rdata) if q_type == dnslib.QTYPE.A: rdata = dnslib.A(ip) elif q_type == dnslib.QTYPE.AAAA: rdata = dnslib.AAAA(ip) rr_list.append(dnslib.RR(rname=record["domain"], rtype=q_type, rdata=rdata, ttl=ttl)) _add_authority(record["domain"], auth_list) _add_additional(addi_list) except: pass
def handle(self): packet_bytes = self.request[0] packet_socket = self.request[1] parsed = False try: dnsreq = dnslib.DNSRecord.parse(packet_bytes) parsed = True except dnslib.DNSError: pass if parsed: logging.debug('IN FROM ADDRESS: %s, INTERFACE: %s, LLMNR DNS packet:\n%s' % ( self.client_address, self.server.ifindex, repr(dnsreq) )) if dnslib.OPCODE.get(dnsreq.header.opcode) != 'QUERY': return if dnsreq.header.qr: # this is response if dnsreq.header.q != 1: return else: # this is query if dnsreq.header.q != 1: return if dnsreq.header.a != 0: return if dnsreq.header.auth != 0: return if dnsreq.header.aa: # RFC 4795: flag C return hostname = str(dnsreq.q.qname) if functools.reduce( operator.or_, (hostname == _hostname for _hostname in self.server.hostname_list), False ): dnsresp = dnsreq.reply(0, 0) if dnsreq.q.qclass == dnslib.CLASS.IN: if dnsreq.q.qtype == dnslib.QTYPE.AAAA: for ipaddress in self.server.dispatcher.get_addresses_ipv6(self.server.ifindex): dnsresp.add_answer(dnslib.RR( dnsreq.q.qname.idna(), dnslib.QTYPE.AAAA, ttl=60, rdata=dnslib.AAAA(ipaddress) )) else: return else: return dnsresp.header.aa = 0 # RFC 4795: flag C packet_socket.sendto(dnsresp.pack(), self.client_address) logging.debug('OUT TO ADDRESS: %s, LLMNR DNS packet:\n%s' % ( self.client_address, repr(dnsresp) ))
def ip_encode(data, ipv6) -> list: """ Encodes data to AAAA or A rdata types. """ chunk_size = IPV6_LENGTH if ipv6 else IPV4_LENGTH data = pad_bytes(data, chunk_size) if (len(data) > chunk_size): data = chunk(data, chunk_size) else: data = [data] if (ipv6): qdata = [dns.AAAA(socket.inet_ntop(socket.AF_INET6, i)) for i in data] else: qdata = [dns.A(socket.inet_ntop(socket.AF_INET, i)) for i in data] return qdata
def _aaaa_search(record, rr_list, auth_list, addi_list): """ Searches and adds any AAAA records for the domain. :param record: Overall record for domain :param rr_list: Current record list for the domain :param auth_list: Authority list for the domain :param addi_list: Additional list for the domain """ try: _alias_search(dnslib.QTYPE.AAAA, record, rr_list, auth_list, addi_list) aaaa_record = record["AAAA"] ttl = int(aaaa_record["ttl"]) for ip in aaaa_record["value"]: rr_list.append(dnslib.RR(rname = record["domain"], rtype = dnslib.QTYPE.AAAA, rdata = dnslib.AAAA(ip), ttl = ttl)) _add_authority(record["domain"], auth_list) _add_additional(addi_list) except: pass
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() 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
def handle(self): packet_bytes = self.request[0] packet_socket = self.request[1] iface_index = self.request[2] parsed = False try: dnsreq = dnslib.DNSRecord.parse(packet_bytes) parsed = True except dnslib.DNSError: pass if parsed: logging.debug( 'IN FROM ADDRESS: %s, INTERFACE: %s, LLMNR DNS packet:\n%s' % (self.client_address, iface_index, repr(dnsreq))) if dnslib.OPCODE.get(dnsreq.header.opcode) != 'QUERY': return if dnsreq.header.qr: # this is response if dnsreq.header.q != 1: return else: # this is query if dnsreq.header.q != 1: return if dnsreq.header.a != 0: return if dnsreq.header.auth != 0: return if dnsreq.header.aa: # RFC 4795: flag C return hostname = str(dnsreq.q.qname) if functools.reduce( operator.or_, (hostname == _hostname for _hostname in self.server.hostname_list), False): dnsresp = dnsreq.reply(0, 0) if dnsreq.q.qclass == dnslib.CLASS.IN: if dnsreq.q.qtype == dnslib.QTYPE.AAAA: if iface_index is None: return ifaces = netifaces.interfaces() try: iface = ifaces[iface_index - 1] except IndexError: return try: ifaddresses = netifaces.ifaddresses(iface)[ netifaces.AF_INET6] except (KeyError, ValueError): return for ifaddress in ifaddresses: # IPv6 address may be link-local and might have interface suffix ipaddress = ifaddress['addr'].split('%', 1)[0] dnsresp.add_answer( dnslib.RR(dnsreq.q.qname.idna(), dnslib.QTYPE.AAAA, ttl=60, rdata=dnslib.AAAA(ipaddress))) else: return else: return dnsresp.header.aa = 0 # RFC 4795: flag C packet_socket.sendto(dnsresp.pack(), self.client_address) logging.debug('OUT TO ADDRESS: %s, LLMNR DNS packet:\n%s' % (self.client_address, repr(dnsresp)))
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 main(): # Creates internet UDP socket. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Binds to the specified IP and port. sock.bind((IP, PORT)) while True: try: # Receives data (DNS request) and address from a client. buffer size 512 as mentioned in DNS RFC. data, addr = sock.recvfrom(BUFFER_SIZE) except: continue # Informs in the console about a request received. print('Received request from {0} at port {1}.'.format( addr[0], addr[1])) try: # Decodes data to DNS request. dns_req = dnslib.DNSRecord.parse(data) except: # Informs in the console that the request is corrupted. print("Failed decoding the request due to corruption.") else: # For each question in the clients DNS request: for question in dns_req.questions: # Gets the name queried in the question. q_name = str(question.get_qname()).rstrip('.') # If the query type is PTR (reverse query). if dnslib.QTYPE.get(question.qtype) == 'PTR': pass # If the query type is A (IPv4). if dnslib.QTYPE.get(question.qtype) == 'A': # Generates reply. dns_rep = dnslib.DNSRecord( dnslib.DNSHeader(id=dns_req.header.id, qr=1, aa=1, ra=1), q=dnslib.DNSQuestion(q_name, dnslib.QTYPE.A)) # Looks up answers, operates on each one if there are any. for answer in lookup(q_name, 'A'): # Adds the answer to the reply. dns_rep.add_answer( dnslib.RR(q_name, dnslib.QTYPE.A, rdata=dnslib.A(answer))) # If the query type is AAAA (IPv6). if dnslib.QTYPE.get(question.qtype) == 'AAAA': # Generates reply. dns_rep = dnslib.DNSRecord( dnslib.DNSHeader(id=dns_req.header.id, qr=1, aa=1, ra=1), q=dnslib.DNSQuestion(q_name, dnslib.QTYPE.AAAA)) # Looks up answers, operates on each one if there are any. for answer in lookup(q_name, 'AAAA'): # Adds the answer to the reply. dns_rep.add_answer( dnslib.RR(q_name, dnslib.QTYPE.AAAA, rdata=dnslib.AAAA(answer))) try: # Sends the reply generated to the client. sock.sendto(bytes(dns_rep.pack()), addr) except: # Informs in the console that sending the reply failed. print("Failed sending reply.") else: # Informs in the console about a reply sent. print('Sent reply to {0} at port {1}.\n'.format( addr[0], addr[1]))
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 addr_to_qdata(addr: TAddress) -> dnslib.RD: ip = addr.compressed return dnslib.A(ip) if addr.version == 4 else dnslib.AAAA(ip)
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