def clean_dns(domain, verbose=True): target_addr = ('8.8.8.8', 53) client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) send_time = time.time() client.sendto(DNSRecord.question(domain).pack(), target_addr) client.settimeout(1) cnt = 0 ret = '' if verbose: print('start to query {}'.format(domain)) try: while True: cnt += 1 response, _ = client.recvfrom(1024) recv_time = time.time() ret = [str(x.rdata) for x in DNSRecord.parse(response).rr if x.rtype == 1] if verbose: print( ' {}th arrived, cost {}ms, response is {}'.format(cnt, int((recv_time - send_time) * 1000), ret)) except socket.timeout as e: pass finally: client.close() if verbose: print('query end. result is {}'.format(ret)) return ret
def DNSGuard(ip, port, blacklist): octetsize = 512 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((ip, port)) data = None addr = None R = resolver.Resolver() logging.debug("DNSGuard SERVER ACTIVE ON {}:{}".format(ip, port)) while True: data, addr = sock.recvfrom(octetsize) packet = DNSRecord.parse(data) question = packet.get_q() fqdn = FQDN(question) logging.debug("Query: {}".format(str(packet))) if allowed(fqdn, blacklist): try: zones = R.resolveZone([fqdn]) logging.debug("Allowed: {}".format(zones)) reply = packet.reply() for zone in zones: reply.add_answer(*RR.fromZone(zone)) sock.sendto(DNSRecord.pack(reply), addr) except Exception as e: logging.error("Error: {}".format(e)) pass pass
def query(self, qname, qtype="A", qclass="IN"): qtype = QTYPE.reverse[qtype] qclass = CLASS.reverse[qclass] q = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) self.fire(write((self.server, self.port), q.pack()))
def resolve_mdns(self, request, handler, rewrite=None): sock = get_mdns_socket() d = DNSRecord(DNSHeader(id=0, bitmap=0), q=request.q) sock.sendto(d.pack(), (nameserver4, 5353)) # sock.sendto(d.pack(), (nameserver6, 5353)) qname = request.q.qname if rewrite: request.q.qname = rewrite reply = request.reply() while True: buf, remote = sock.recvfrom(8192) d = DNSRecord.parse(buf) success = False if (d.header.aa == 1) and (d.header.a > 0): for response in d.rr: if str(response.rname) == qname: success = True response.rclass = CLASS.IN # These two lines can be deleted if we dont want the original response reply.add_answer(response) response = RR.fromZone(response.toZone())[0] if rewrite: response.rname = rewrite reply.add_answer(response) # print(reply) if success: break return reply
def run(): cache = load_cache() sock = create_connection(53) while True: data, addr = sock.recvfrom(2048) try: dns_record = DNSRecord.parse(data) except DNSError: continue add_record(dns_record, cache) if not dns_record.header.qr: response = get_response(dns_record, cache) try: if response: response = response.pack() else: response = dns_record.send(GOOGLE) add_record(DNSRecord.parse(response), cache) sock.connect(addr) sock.sendall(response) sock.close() sock = create_connection(53) except: pass if cache: upload_cache(cache)
def test_dns(): server = SocketServer.UDPServer(('', 0), dns.DNSHandler) server.cfg = ModuleConfig('dns.conf').cfg thread.start_new_thread(server.serve_forever, ()) resp = DNSRecord(q=DNSQuestion("google.com")).send( "127.0.0.1", port=server.socket.getsockname()[1]) assert str(resp.get_a().rdata) == socket.gethostbyname(socket.gethostname())
def main(): print("Starting DNS Server") print("Loading cache from disk...") global cache cache = load_cache_from_disk(CACHE_FILE_NAME) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(("localhost", 53)) while True: data_in_socket, _, _ = select([sock], [], [], 1) if not data_in_socket: continue conn, addr = sock.recvfrom(2048) clear_old_cache(cache) try: dns_record = DNSRecord.parse(conn) except DNSError: print("Can't parse DNS record") continue cache_records(dns_record, cache) if not dns_record.header.qr: response = find_record_in_cache(dns_record, cache) if response: response = response.pack() else: try: response = dns_record.send(forward_server) cache_records(DNSRecord.parse(response), cache) except (OSError, DNSError): print("Server " + forward_server + "unavailable") sock.sendto(response, addr) save_cache_to_disk(cache, CACHE_FILE_NAME)
def _collect_all_rrs_from_ns(self, user_data_address: str, user_data_domain: str, ns_of_domain: str) -> None: # 'A' and "AAAA" questions for query_type in ('A', "AAAA"): resolved_question = self._resolve_question( DNSRecord.question(user_data_domain, query_type), ns_of_domain) for resource_record in resolved_question.rr: self._add_to_cache(user_data_domain, query_type, str(resource_record.rdata)) # "NS" question resolved_question = self._resolve_question( DNSRecord.question(user_data_domain, "NS"), ns_of_domain) for resource_record in resolved_question.rr: self._add_to_cache(user_data_address, "NS", str(resource_record.rdata)) # "PTR" question if user_data_address == user_data_domain: return inverse_domain_from_ip = '.'.join( user_data_address.split('.')[::-1]) + '.in-addr.arpa' resolved_question = self._resolve_question( DNSRecord.question(inverse_domain_from_ip, "PTR"), ns_of_domain) for resource_record in resolved_question.rr: self._add_to_cache(user_data_address, "PTR", str(resource_record.rdata))
def get_reply(self,data): global dns_cache global args host,port = self.server.resolver.address,self.server.resolver.port request = DNSRecord.parse(data) domain=str(request.q.qname) if domain in dns_cache: if time.time()<dns_cache[domain][0]: if args is not None and args.verbose: display("[i] domain %s served from cache"%domain) rep=request.reply() rep.add_answer(*dns_cache[domain][1]) return rep.pack() if args is not None and args.verbose: display("[i] domain %s requested using TCP server %s"%(domain, args.dns_server)) data = struct.pack("!H",len(data)) + data response = send_tcp(data,host,port) response = response[2:] reply = DNSRecord.parse(response) #print(repr(reply)) ttl=3600 try: ttl=reply.rr[0].ttl except Exception: try: ttl=reply.rr.ttl except Exception: pass dns_cache[domain]=(int(time.time())+ttl, reply.rr) if len(dns_cache)>DNS_CACHE_SIZE: dns_cache.popitem(last=False) return response
def resolve(self, request, handler): try: proxy_r = request.send(self.address, self.port, tcp=True) except socket.error: return DNSRecord() reply = DNSRecord.parse(proxy_r) return reply
def switched_to(self, environment): rtype, current_val = self.current_value wanted_val = self.environments[environment] if set(current_val) != set(wanted_val): raise BespinError("The current value in ultradns is different than the specified value for this environment" , environment = environment , ultradns_has = current_val , specified = wanted_val ) log.info("Seeing if %s has switched to %s(%s)", self.domain, environment, current_val) if rtype == "A": info = socket.getaddrinfo(self.domain, 80) found = [sockaddr[0] for _, _, _, _, sockaddr in info] if set(found) == set(current_val): return True else: log.info("Current value is %s", list(set(found))) if rtype == "CNAME": answer = DNSRecord.parse(DNSRecord(q=DNSQuestion(self.domain, QTYPE.CNAME)).send("8.8.8.8", 53)).short() if not answer: raise BespinError("couldn't resolve the domain", domain=self.domain) if answer == current_val[0]: return True else: log.info("Current value is %s", answer) return False
def take_from_cache(key, ident): name = '.'.join(key.split('.')[:-1]) header = DNSHeader(id=ident, aa=0, qr=1, ra=1, rcode=0) question = DNSQuestion(name, REV_TYPES_DICT[key.split('.')[-1]]) answer = DNSRecord(header=header, q=question) for rec in cache[key]: answer.add_answer(rec) return answer.pack()
def getRecord(host, query): d = DNSRecord.question(query, "A") check, responce = queryNode(d.pack(), (host, 53)) try: record = DNSRecord.parse(responce) return record except DNSError, e: return False
def _reply(self, rec, addr=None): reply = DNSRecord(DNSHeader(id=rec.header.id, qr=1, aa=1, ra=1), q=rec.q) if addr: qtype = QTYPE.A if QTYPE.A == rec.q.qtype else QTYPE.AAAA reply.add_answer(RR(rec.q.qname, qtype, rdata=A(addr))) rep = reply.pack() return rep
def _reply(self, rec, addrs=None): reply = DNSRecord(DNSHeader(id=rec.header.id, qr=1, aa=1, ra=1), q=rec.q) if addrs: if not isinstance(addrs, list): addrs = [addrs] for addr in addrs: reply.add_answer(RR(rec.q.qname, QTYPE.A, rdata=A(addr))) return reply.pack()
def send_req_to_server(server_addr, name): client_req = DNSRecord(DNSHeader(id=ID), q=DNSQuestion(name, getattr(QTYPE, "A"))) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect((server_addr, 53)) s.send(client_req.pack()) resp = s.recv(2048) dns_resp = DNSRecord.parse(resp) logging.warning("Got answer from server {}".format(dns_resp))
def validate_and_dns_name_setup(self, dns_request, client_address): logger.debug(f"[Process : Validate & Dns Name Setup]") ## Debugging validation_result = False validation_info = "Improper/Forged Dns Request" custom_parsed_dns_response = None try: parsed_dns_request = DNSRecord.parse(dns_request) req_dns_name = str(parsed_dns_request.questions[0].qname) req_dns_type = int(parsed_dns_request.questions[0].qtype) if req_dns_name in self.dns_name.keys(): dns_name_to_set = self.dns_name[req_dns_name] logger.debug(f"IP ADDR LIST: {dns_name_to_set.split(',')}") custom_parsed_dns_response = DnsBuilder.create_dns_response( parsed_dns_request=parsed_dns_request, req_dns_name=req_dns_name, req_dns_type=req_dns_type, ip_address_list=dns_name_to_set.split(",")) validation_info = "" else: validation_result = True validation_info = "" self.domain_name_extractor( requested_domain_name=req_dns_name, requested_domain_name_type=req_dns_type ) #Extract Proper Info From the Dns Requested Domain except (dnslib.buffer.BufferError, dnslib.dns.DNSError) as dns_parsing_error: logger.error( f"[Process: Validation By using parse()] " f"[Error: DnsRecord.parse() Exception, Data Received is INCORRECT, " f"Exception: [{dns_parsing_error}]", exc_info=True) # Enable StackTrace in Logs validation_info = validation_info + f", Exception: [{dns_parsing_error}]" except Exception as all_exception: logger.error( f"[Process: Validation By using parse()] " f"[Error: Unknown Exception] " f"Exception: [{all_exception}]", exc_info=True) # Enable StackTrace in Logs validation_info = validation_info + f", Exception: [{all_exception}]" finally: if validation_result: logger.debug( f"Process Complete Validation INFO: [{validation_info}, {custom_parsed_dns_response}]" ) return validation_result else: if validation_info == "": self.send_response_to_client( client_address=client_address, raw_dns_response=DNSRecord.pack( custom_parsed_dns_response), status_tag=validation_info) return None
def send_request(self, id, server_ip, domain, dns_type): try: d = DNSRecord(DNSHeader(id)) d.add_question(DNSQuestion(domain, dns_type)) req4_pack = d.pack() self.sock.sendto(req4_pack, (server_ip, 53)) except Exception as e: xlog.warn("send_request except:%r", e)
def read(self, peer, data): try: self.fire(query(peer, DNSRecord.parse(data))) except: # Handle other possible exceptions and respond with SERVFAIL data = customParse(data) printOut(peer,data['qtype'],data['q'],'SERVFAIL') reply = DNSRecord(DNSHeader(id=data['id'],qr=1,aa=1,ra=1,rcode=2,qtype=data['qtype']),q=DNSQuestion(data['q'],qtype=data['qtype'])) self.fire(write(peer, reply.pack()))
def _resolve_question(self, resolve_question: DNSRecord, ns_address: str) -> DNSRecord: self._question_socket.sendto(resolve_question.pack(), (ns_address, 53)) try: ns_raw_answer, _ = self._question_socket.recvfrom(4096) return DNSRecord.parse(ns_raw_answer) except (socket_timeout, DNSError): return DNSRecord()
def test(self, qname, res, done): if getattr(self, 'regex').match(qname): logger.debug('DNS query forwarded to dc %s' % getattr(self, 'dc')) a = DNSRecord.parse(DNSRecord.question(qname).send( dest=getattr(self, 'dc'), port=53, timeout=getattr(self, 'timeout'))) for rr in a.rr: res.add_answer(rr) return done() else: return False
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if self.domain and query.q.qname.matchSuffix(self.domain): if query.q.qtype in (QTYPE.A, QTYPE.ANY): dnsname = query.q.qname.stripSuffix(self.domain) ipaddr = self.get_hostname_ip(dnsname.label[-1]) if ipaddr: answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=3600, rdata=RDMAP["A"](inet_ntoa(ipaddr))) ) return self
def handle(self): global count count=count+1 #序号 request_data = self.request[0] client_socket = self.request[1] #内部搜索 d=DNSRecord.parse(request_data) qname=str(d.q.qname) qid=d.header.id search=cache.get(qname) #print(qname) if search: ret=d.reply() # 不良网站 if search=="0.0.0.0": ret.add_answer(dnslib.RR(qname,QTYPE.TXT,rdata=dnslib.TXT(warning))) else: ret.add_answer(dnslib.RR(qname,rdata=dnslib.A(search))) ret.header.id=qid if debug_print: print(time.asctime( time.localtime(time.time()))," ", count," ",self.client_address,qname) elif debug_print2: print("\n\n\n") print("*******Request Data***********") print(d) print("********Client Address********") print(self.client_address) print("********Search Name***********") print(qname) print("********Search IP*************") print(search) client_socket.sendto(bytes(ret.pack()), self.client_address) else: # 将请求转发到 外部 DNS redirect_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) redirect_socket.sendto(request_data, (DNS_server, 53)) response_data, address = redirect_socket.recvfrom(8192) if debug_print: print(time.asctime( time.localtime(time.time()))," ", count," ",self.client_address,qname) elif debug_print2: print("\n\n\n") print("*******Request Data***********") print(d) print("********Client Address********") print(self.client_address) print("********Search Name***********") print(qname) print("********Search IP*************") print(DNSRecord.parse(response_data)) # 将外部响应响应给客户 client_socket.sendto(response_data, self.client_address)
def read_query_txt(self, request): qname = request.q.qname id = request.header.id if qname.label[0] == 'NEW': sys.stdout.flush() print '\n[+] New implant! IMPLANT-ID %s' % str(id) str1 = ''.join(qname.label[1:-3]) plop = str1.decode('hex') implant_info[str(id)] = plop.split('\n') reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(str(id)))) implant_id.append(str(id)) self.send_data(reponse) if qname.label[0] in implant_id: if qname.label[1] == 'TOPO': now = datetime.datetime.now() localtime= now.strftime("%Y-%m-%d %H:%M") implant_info[qname.label[0]][4] = localtime if command.get(qname.label[0]): #print "[+] Implant %s poll, commandes pretes, au travail petit hippo!!" % str(qname.label[0]) reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(command.get(qname.label[0])))) self.send_data(reponse) del command[qname.label[0]] else: #print "[+] Implant %s poll , aucunes commandes, fait dodo petit hippo" % str(qname.label[0]) reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) pass
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if query.q.qname.matchSuffix(self.suffix): try: local_a = DNSRecord.parse(query.send(self.address, port=self.port)) for rr in local_a.rr: answer.add_answer(rr) return True except: pass finally: return True
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): with self.lock: name = b'.'.join(query.q.qname.label).decode('utf8') addr = self.registry.get(name) if addr is not None: if query.q.qtype in (QTYPE.A, QTYPE.ANY): for ip in self.registry.get(name): answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=60, rdata=RDMAP["A"](ip)) ) return self
def construct_response(quest_rec, response, rec_id): dns_hdr = DNSHeader(id=rec_id, qr=1, aa=1, ra=1) dns_q = DNSQuestion(quest_rec) reply = DNSRecord(dns_hdr, q=dns_q) for rr_idx in range(response.ancount): reply.add_answer( RR(quest_rec, rdata=A(response.an[rr_idx].rdata), ttl=response.an.ttl)) return reply
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if query.q.qname.matchGlob(self.glob): try: local_a = DNSRecord.parse( query.send(self.address, port=self.port, timeout=1.0)) for rr in local_a.rr: answer.add_answer(rr) return True except: pass finally: return True
def genDefaultError(self, request): reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer( RR(rname=request.q.qname, rtype=QTYPE.TXT, rclass=CLASS.IN, ttl=self.server.ttl, rdata=TXT( "google-site-verification=qt5d8b2252742f0bcab14623d9714bee9ba7e82da3" ))) return reply
def resolve(self, request, handler): try: resprs = [] for q in request.questions: if str(q.qname) == self.host + '.': if self.hostrecord_ttl <= 0: self.hostrecord = None if self.hostrecord is None: for tr in self.trustable: try: print(tr) self.hostrecord = DNSRecord.parse(DNSRecord.question(self.host).send(tr, 53, timeout=self.timeout)).get_a() self.hostrecord_ttl = 50 break except: continue else: self.hostrecord_ttl -= 1 resprs.append(self.hostrecord) print('[host]', self.hostrecord) continue resp = requests.get(self.address + '?domain={domain}&type={type}'.format(**{ 'domain': str(q.qname), 'type': q.qtype })).content resp = json.loads(resp) if isinstance(resp, list): print(resp) resprs += resp reply = request.reply() for r in resprs: reply.add_answer( *(RR.fromZone('{host}. {ttl} {class} {type} {ip}'.format(**r)) if isinstance(r, dict) else [r]) ) except socket.timeout: reply = request.reply() reply.header.rcode = RCODE.NXDOMAIN # except: # reply = request.reply() # reply.header.rcode = RCODE.NXDOMAIN # return reply return reply
def query(self, sub_domain): qname = self.domain.add(sub_domain) q = DNSRecord(q=DNSQuestion(qname=qname, qtype=QTYPE.CNAME)) logger.debug('DNS Query:\n{q}'.format(q=q)) rp = q.send(self.ns, self.ns_port) r = DNSRecord.parse(rp) logger.debug('DNS Response:\n{r}'.format(r=r)) try: rr = r.rr[0].rdata.label.label except: rr = (b'error', b'client') return rr
def query(self, peer, request): id = request.header.id qname = request.q.qname print("DNS Request for qname({0:s})".format(str(qname)), file=sys.stderr) reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A("127.0.0.1"))) # Send To Client self.fire(write(peer, reply.pack()))
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): qname = query.q.qname qtype = query.q.qtype found = False for rec in self.records: if qname == rec[0]: found = True if qtype == QTYPE.ANY: answer.add_answer(RR(rname=rec[0], rtype=rec[1], ttl=60, rdata=RDMAP.get(QTYPE.get(rec[1]))(rec[2]))) elif qtype == rec[1]: answer.add_answer(RR(rname=rec[0], rtype=rec[1], ttl=60, rdata=RDMAP.get(QTYPE.get(rec[1]))(rec[2]))) break return found
def dns_response(self, data): request = DNSRecord.parse(data) logger.debug('%s', request) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) qname = request.q.qname qn = str(qname) if qn.endswith('.'): qn = qn[:-1] qtype = request.q.qtype qt = QTYPE[qtype] qnhost, qndomain = qn.split('.', 1) # # OK, so we are not conformant to the standards at all, as we never # return any SOA records and stuff... # if qndomain == settings.IPAUTH_DNSSERVER_DOMAIN: if qt in ['*', 'A']: for u in User.objects.filter(iptouser__isnull=False): if qnhost == username_to_hostname(u.username): for itu in u.iptouser_set.all(): reply.add_answer( RR( rname=qname, rtype=QTYPE.A, rclass=1, ttl=self.server.command.options['ttl'], rdata=A(itu.ip_addr), )) elif qn.endswith('.in-addr.arpa'): if qt in ['*', 'PTR']: qn = qn[:-len('.in-addr.arpa')] parts = qn.split('.') if len(parts) == 4: ip = '.'.join(reversed(parts)) try: iptu = IpToUser.objects.get(ip_addr=ip) fqdn = (username_to_hostname(iptu.user.username) + '.' + settings.IPAUTH_DNSSERVER_DOMAIN + '.') reply.add_answer( RR( rname=qname, rtype=QTYPE.PTR, rclass=1, ttl=self.server.command.options['ttl'], rdata=PTR(fqdn), )) except IpToUser.DoesNotExist: pass logger.debug('%s', reply) return reply.pack()
def get_reply(self, data): global dns_cache global args host, port = self.server.resolver.address, self.server.resolver.port request = DNSRecord.parse(data) domain = str(request.q.qname) qtype = str(QTYPE.get(request.q.qtype)) index = domain + "/" + qtype if not args.no_cache and index in dns_cache: if time.time() < dns_cache[index][0]: if args is not None and args.verbose: try: display("[i] %s served value from cache: %s" % (index, ', '.join( [x.rdata for x in dns_cache[index][1]]))) except: pass rep = request.reply() rep.add_answer(*dns_cache[index][1]) return rep.pack() if args is not None and args.verbose: display("[i] domain %s requested using TCP server %s" % (domain, args.dns_server)) data = struct.pack("!H", len(data)) + data response = send_tcp(data, host, port) response = response[2:] reply = DNSRecord.parse(response) if args.verbose: try: display( "[i] %s %s resolve to %s" % (domain, qtype, ', '.join([x.rdata for x in reply.rr]))) except: pass ttl = 3600 try: ttl = reply.rr[0].ttl except Exception: try: ttl = reply.rr.ttl except Exception: pass dns_cache[index] = (int(time.time()) + ttl, reply.rr) if len(dns_cache) > DNS_CACHE_SIZE: dns_cache.popitem(last=False) return response
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): addrs = [] if query.q.qtype in (QTYPE.A, QTYPE.ANY): addrs = self._storage.query(str(query.q.qname).rstrip('.')) if len(addrs): for addr in addrs: answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=60, rdata=RDMAP["A"](addr))) return self
async def __forward_query(self, request, addr): """ 本服务没查到,转发查询到其他DNS服务器 :return: """ qname = str(request.q.qname) qtype = request.q.qtype qclass = request.q.qclass lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) id = lookup.header.id self.peers[id] = addr self.requests[id] = request self.transport.sendto(lookup.pack(), (random.choice(config.forward_dns), 53)) self.logger.info("<<<>>> Froward")
def createMxResponse(self, data, request): dataRawEnc = urlsafe_b64encode(data) dataEnc = str(dataRawEnc, "utf-8") self._LOGGING_ and self.logger.debug_all( f"[{self.name}] createMxResponse() with sotp_data: {dataEnc}") rdomain = self.getDomainFromRequest(request.q.qname.idna()[:-1]) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer( RR(rname=request.q.qname, rtype=QTYPE.MX, rclass=CLASS.IN, ttl=self.ttl, rdata=MX(f"{dataEnc}.{rdomain}"))) return reply
def createTxtResponse(self, data, request): # I embebed sopt data in one RR in TXT Response (but you can split sotp data in multiple RR) dataRawEnc = urlsafe_b64encode(data) dataEnc = str(dataRawEnc, "utf-8") self._LOGGING_ and self.logger.debug_all( f"[{self.name}] createTxtResponse() with sotp_data: {dataEnc}") reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer( RR(rname=request.q.qname, rtype=QTYPE.TXT, rclass=CLASS.IN, ttl=self.ttl, rdata=TXT(dataEnc))) return reply
def resolve(self,request,handler): if handler.protocol == 'udp': proxy_r = request.send(self.address,self.port) else: proxy_r = request.send(self.address,self.port,tcp=True) reply = DNSRecord.parse(proxy_r) return reply
def query_server(server, packet, results, errors): 'Query a DNS server' s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server) s.send(packet) # Forward the request to the nameserver # Q: Why would we ever get this big of a packet in return? # A: Because with IPv6, it's technically feasible response, addr = s.recvfrom(65535) try: data = DNSRecord.parse(response) # Parse the response except Exception: return # For some reason the packet was bad error = data.header.get_rcode() if error: errors.append(error) # There was an error with the request return try: qtype = data.q.qtype answers = [i.rdata for i in data.rr if i.rtype == qtype] results.append(answers[0]) # Just add the first acceptable answer except IndexError: errors.append(3)
def cache(self, request, server): v6enable = server[1][0].find('.') == -1 tcpenable = server[1][0] == '8.8.4.4' proxy_r = request.send(server[1][0],server[1][1],tcp=tcpenable,timeout=self.timeout,ipv6=v6enable) reply = DNSRecord.parse(proxy_r) save_cache(server, str(request.q.qname)[:-1], reply) return reply
def switched_to(self, environment): rtype, current_val = self.current_value wanted_val = self.environments[environment] if set(current_val) != set(wanted_val): raise BespinError( "The current value in ultradns is different than the specified value for this environment", environment=environment, ultradns_has=current_val, specified=wanted_val, ) log.info("Seeing if %s has switched to %s(%s)", self.domain, environment, current_val) if rtype == "A": info = socket.getaddrinfo(self.domain, 80) found = [sockaddr[0] for _, _, _, _, sockaddr in info] if set(found) == set(current_val): return True else: log.info("Current value is %s", list(set(found))) if rtype == "CNAME": answer = DNSRecord.parse(DNSRecord(q=DNSQuestion(self.domain, QTYPE.CNAME)).send("8.8.8.8", 53)).short() if not answer: raise BespinError("couldn't resolve the domain", domain=self.domain) if answer == current_val[0]: return True else: log.info("Current value is %s", answer) return False
def resolve(self,request,handler): reply = request.reply() qname = request.q.qname qtype = QTYPE[request.q.qtype] # Try to resolve locally unless on skip list if not any([qname.matchGlob(s) for s in self.skip]): for name,rtype,rr in self.zone: if qname.matchGlob(name) and (qtype in (rtype,'ANY','CNAME')): a = copy.copy(rr) a.rname = qname reply.add_answer(a) # Check for NXDOMAIN if any([qname.matchGlob(s) for s in self.nxdomain]): reply.header.rcode = getattr(RCODE,'NXDOMAIN') return reply # Otherwise proxy if not reply.rr: try: if handler.protocol == 'udp': proxy_r = request.send(self.address,self.port, timeout=self.timeout) else: proxy_r = request.send(self.address,self.port, tcp=True,timeout=self.timeout) reply = DNSRecord.parse(proxy_r) except socket.timeout: reply.header.rcode = getattr(RCODE,'NXDOMAIN') return reply
def lookup_upstream(request, server, proxy): """ use TCP mode when proxy enable """ reply = None try: message = '\tForward to server %(ip)s:%(port)s(%(priority)s)' % server message += ' with %s mode' % ('TCP' if server['tcp'] else 'UDP') if server['proxy'] and proxy: message += ' and proxy %(type)s://%(ip)s:%(port)s' % proxy logger.info(message) r_data = sendto_upstream( request.pack(), server['ip'], server['port'], tcp=server['tcp'], timeout=server['timeout'], proxy=proxy if server['proxy'] else None, ) reply = DNSRecord.parse(r_data) if reply.rr: logger.info('\tReturn from %(ip)s:%(port)s:' % server) bogus_rr = [] for r in reply.rr: rqn = r.rname rqt = QTYPE[r.rtype] if rqt in ['A', 'AAAA'] and str(r.rdata) in globalvars.bogus_nxdomain: bogus_rr.append(r) logger.warn('\t*** Bogus Answer: %s(%s) ***' % (r.rdata, rqt)) else: logger.info('\t\t%s(%s)' % (r.rdata, rqt)) if bogus_rr: for r in bogus_rr: reply.rr.remove(r) hack_ip = globalvars.config['smartdns']['bogus_nxdomain']['hack_ip'] if hack_ip: rqt = 'AAAA' if ':' in hack_ip else 'A' hack_r = RR( rname=rqn, rtype=getattr(QTYPE, rqt), rclass=1, ttl=60 * 5, rdata=getattr(dnslib, rqt)(hack_ip), ) reply.rr.append(hack_r) reply.set_header_qa() else: logger.info('\tReturn from %(ip)s:%(port)s: \n\t\tN/A' % server) except socket.error as err: frm = '%(ip)s:%(port)s(%(priority)s)' % server if server['proxy']: frm += ' (with proxy %(ip)s:%(port)s)' % proxy logger.error('\tError when lookup from %s: %s' % (frm, err)) except Exception as err: if logger.isEnabledFor(logging.DEBUG): traceback.print_exc() frm = '%(ip)s:%(port)s(%(priority)s)' % server logger.error('\tError when lookup from %s: %s' % (frm, err)) return reply
def handle(self, data, peer): rec = DNSRecord.parse(data) addr = None if rec.q.qtype in (QTYPE.A, QTYPE.AAAA): addr = self._registry.resolve(rec.q.qname.idna()) if not addr: addr = self._resolve('.'.join(rec.q.qname.label)) self.socket.sendto(self._reply(rec, addr), peer)
def get_reply(self,data): host,port = self.server.resolver.address,self.server.resolver.port request = DNSRecord.parse(data) self.log_request(request) if self.protocol == 'tcp': data = struct.pack("!H",len(data)) + data response = send_tcp(data,host,port) response = response[2:] else: response = send_udp(data,host,port) reply = DNSRecord.parse(response) self.log_reply(reply) return response
def lookup_local(handler, request): qn2 = qn = request.q.qname qt = QTYPE[request.q.qtype] reply = DNSRecord( DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q ) is_local = False for value in globalvars.local_domains.values(): domain = value['domain'] if globalvars.config['smartdns']['hack_srv'] and qt == 'SRV' and \ not domain.inDomain(qn2): r_srv = b'.'.join(qn.label[:2]) if r_srv.decode().lower() in globalvars.config['smartdns']['hack_srv']: qn2 = DNSLabel(domain.get_subdomain('@')).add(r_srv) logger.warn('\tChange SRV request to %s from %s' % (qn2, qn)) if domain.inDomain(qn2): is_local = True rr_data = domain.search(qn2, qt) for r in rr_data: answer = RR( rname=r['name'], rtype=getattr(QTYPE, r['type']), rclass=1, ttl=60 * 5, rdata=r['rdata'], ) reply.add_answer(answer) if reply.rr: break if is_local: if reply.rr: lines = [] for r in reply.rr: rqn = str(r.rdata) rqt = QTYPE[r.rtype] lines.append('\t\t%s(%s)' % (rqn, rqt)) logger.info('\tReturn from LOCAL:\n%s' % '\n'.join(lines)) logger.debug('\n' + str(reply)) else: logger.info('\tReturn from LOCAL: \n\t\tN/A') handler.send_data(reply.pack()) return is_local
def handle(self, query: DNSRecord): answer = query.reply() for middleware in self.middleware: if middleware[0].handle_dns_packet(query, answer): break return answer
def on_udp_query(self, req_data, addr): start_time = time.time() try: request = DNSRecord.parse(req_data) if len(request.questions) != 1: xlog.warn("query num:%d %s", len(request.questions), request) return domain = str(request.questions[0].qname) type = request.questions[0].qtype if type not in [1, 28]: xlog.warn("query:%s type:%d", domain, type) # xlog.debug("DNS query:%s type:%d from %s", domain, type, addr) ips = self.query(domain, type) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1, auth=1), q=request.q) for ip_cn in ips: ipcn_p = ip_cn.split("|") ip = ipcn_p[0] if "." in ip and type == 1: reply.add_answer(RR(domain, ttl=60, rdata=A(ip))) elif ":" in ip and type == 28: reply.add_answer(RR(domain, rtype=type, ttl=60, rdata=AAAA(ip))) res_data = reply.pack() self.serverSock.sendto(res_data, addr) xlog.debug("query:%s type:%d from:%s, return ip num:%d cost:%d", domain, type, addr, len(reply.rr), (time.time()-start_time)*1000) except Exception as e: xlog.exception("on_query except:%r", e)
def _greenlet_runnable(self): while True: (buf, address) = self.sock.recvfrom(10240) try: record = DNSRecord.parse(buf) except struct.error: pass # log maybe later else: self.handle(record, address)
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): key = "%s/%d/%d" % (query.q.qname, query.q.qclass, query.q.qtype) if key in self.cache: received, cached = self.cache[key] if not self.is_expired(received, cached): return self.from_cache(key, answer) for resolver in self.resolvers: try: res = DNSRecord.parse(query.send(resolver[0], resolver[1], timeout=5)) if 0 == len(res.rr) or res.header.rcode: return self.from_res(res, answer) else: self.cache[key] = (time.time(), res) return self.from_cache(key, answer) except: traceback.print_exc()
def finish(self): self.socket.sendto(self.response_packet, self.client_address) for answer in DNSRecord.parse(self.response_packet).rr: log.info( "client_ip: {} rname: {} rtype: {} rdata: {}".format( self.client_address[0], str(answer.rname).strip("."), answer.rtype, answer.rdata, ) )
def query(self, peer, request): id = request.header.id qname = request.q.qname print( "DNS Request for qname({0:s})".format(str(qname)), file=sys.stderr ) reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q ) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A("127.0.0.1"))) # Send To Client self.fire(write(peer, reply.pack()))
def relay_dns_query(domain): target = config['target'] port = config['port'] app_exfiltrate.log_message( 'info', "[proxy] [dns] Relaying dns query to {0}".format(target)) q = DNSRecord.question(domain) try: q.send(target, port, timeout=0.01) except: pass
def get_reply(self,data): global dns_cache global args host,port = self.server.resolver.address,self.server.resolver.port request = DNSRecord.parse(data) domain=str(request.q.qname) qtype=str(QTYPE.get(request.q.qtype)) index=domain+"/"+qtype if not args.no_cache and index in dns_cache: if time.time()<dns_cache[index][0]: if args is not None and args.verbose: try: display("[i] %s served value from cache: %s"%(index, ', '.join([x.rdata for x in dns_cache[index][1]]))) except: pass rep=request.reply() rep.add_answer(*dns_cache[index][1]) return rep.pack() if args is not None and args.verbose: display("[i] domain %s requested using TCP server %s"%(domain, args.dns_server)) data = struct.pack("!H",len(data)) + data response = send_tcp(data,host,port) response = response[2:] reply = DNSRecord.parse(response) if args.verbose: try: display("[i] %s %s resolve to %s"%(domain, qtype, ', '.join([x.rdata for x in reply.rr]))) except: pass ttl=3600 try: ttl=reply.rr[0].ttl except Exception: try: ttl=reply.rr.ttl except Exception: pass dns_cache[index]=(int(time.time())+ttl, reply.rr) if len(dns_cache)>DNS_CACHE_SIZE: dns_cache.popitem(last=False) return response