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 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 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 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 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 ingest_mdns_packet(mdns_pkt): logger.debug('Packet with Dot11, UDP, and Apple mDNS') # only parse MDNS names for 802.11 layer sniffing for now, easy to see what's a request from a client for mdns_pkt in mdns_pkt: if mdns_pkt.dport == 5353: logger.debug('Packet destination port 5353') try: d = DNSRecord.parse(mdns_pkt['Raw.load']) for q in d.questions: if q.qtype == 255 and '_tcp.local' not in str(q.qname): try: src = mdns_pkt.getlayer('Dot11').addr3 name = str(q.qname).strip('.local') # An mDNS Ethernet frame is a multicast UDP packet to: # MAC address 01:00:5E:00:00:FB (for IPv4) or 33:33:00:00:00:FB (for IPv6) # IPv4 address 224.0.0.251 or IPv6 address FF02::FB # UDP port 5353 if src != '01:00:5e:00:00:fb': create_or_update_client( src, datetime.utcfromtimestamp(mdns_pkt.time), name) except AttributeError: logger.error('Error parsing MDNS packet') except IndexError: pass
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 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 _catch_dns_answer(self, dns_request_id: int, dns_socket: socket.socket): while True: raw_data, addr = dns_socket.recvfrom(4096) dns_query = DNSRecord.parse(raw_data) if dns_query.header.id == dns_request_id: return dns_query
def handle(self, data, peer): rec = DNSRecord.parse(data) addrs = None auth = False if rec.q.qtype in (QTYPE.A, QTYPE.AAAA, QTYPE.ANY): addrs = self._registry.resolve(rec.q.qname.idna()) or set() if addrs: auth = True # answer AAAA queries for existing A records # with an successful but empty result if rec.q.qtype == QTYPE.AAAA: addrs = None else: log.debug("[namesrv] resolved %s to %s", rec.q.qname.idna(), addrs) else: addr = self._resolve('.'.join(rec.q.qname.label)) if addr: addrs.add(addr) log.debug("[namesrv] externally resolved %s to %s", rec.q.qname.idna(), addrs) if addrs: addrs = list(addrs) self.socket.sendto(self._reply(rec, auth, addrs), peer)
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 parse(self, data): try: dns = DNSRecord.parse(data) except Exception as e: print e return dns
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 handle(self): request = DNSRecord.parse(self.request[0]) socket = self.request[1] reply = request.reply() answer = self.q_processors[reply.q.qtype](reply.q.qname) reply.add_answer(answer) socket.sendto(reply.pack(), self.client_address)
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 parse_udp_dns_packet(ip): """ Parses UDP DNS packet. """ d = DNSRecord.parse(ip.data.data) q = str(d.q.qname).strip(".") if QTYPE[ d.q. qtype] == 'A' and d.header.rcode == RCODE.NOERROR and d.header.a > 0: fn = q content = '' for a in d.rr: if QTYPE[a.rtype] == "CNAME": q = q + " " + str(a.rdata).strip(".") elif QTYPE[a.rtype] == 'A': content = content + str(a.rdata) + " " + q + "\n" if content != '': try: f = open("/tmp/pitm/hostsdir/" + fn, "w") f.write(content) f.close() except: pass print("%s" % (fn)) else: print("Skipped QTYPE %s q=%s RCODE %s Answer = %d" % (QTYPE[d.q.qtype], q, RCODE[d.header.rcode], d.header.a))
def show(self): print("") self.showText("Udp Datagram", 4) self.showText("source \t: (port) " + str(self.src), 5) self.showText("destination \t: (port) " + str(self.dst), 5) print() if type(self.application) != list: if self.application['description'].lower() == "domain name server": self.showText( self.application['description'] + "{}".format("REQUEST" if self.dst == self. application['port number'] else " RESPONSE"), 5) data = DNSRecord.parse(self.data) for line in str(data).split("\n"): self.showText(line, 6) elif self.application['description'].lower( ) == "bootstrap protocol server": self.bootppacket.show() elif self.application['description'].lower() == "HTTPSREQUEST": print('we are here') else: self.showText( self.application['description'] + "{}".format("REQUEST" if self.dst == self. application['port number'] else " RESPONSE")) else: self.showText(hexlify(self.data), 6) print() print()
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 resolve(self, request, handler): qname = request.q.qname qtype = QTYPE[request.q.qtype] # Custom answer only for A (ipv4) or ANY requests if fnmatch.fnmatch(str(qname), self.match) and qtype in ('A', 'ANY'): reply = request.reply() ip = self.get_ip_from_dns(str(qname)) if len(ip) == 0: reply.header.rcode = getattr(RCODE, 'NXDOMAIN') else: reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=60)) return reply 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 = request.reply() reply.header.rcode = getattr(RCODE, 'NXDOMAIN') return reply
def _resolve(self, request, handler): qname = request.q.qname reply = request.reply() # TODO: # Resolve NS?, DS, SOA somehow if not qname.matchSuffix(self.domain): if self.recursor: try: return DNSRecord.parse(request.send(self.recursor, timeout=2)) except socket.error: pass except Exception as e: logger.exception('DNS request forwarding failed ({})'.format(e)) else: logger.debug('Bad domain: {} (suffix={})'.format(qname, self.domain)) reply.header.rcode = RCODE.NXDOMAIN return reply arecords = self.process(qname.stripSuffix(self.domain).idna()[:-1]) if arecords: for address in arecords: reply.add_answer(RR(qname, QTYPE.A, rdata=A(address), ttl=600)) else: reply.header.rcode = RCODE.NXDOMAIN return reply
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 dns_handler(s, peer, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype print "------ Request (%s): %r (%s)" % (str(peer), qname.label, QTYPE[qtype]) print "\n".join([ " %s" % l for l in str(request).split("\n")]) reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) if qtype == QTYPE.A: reply.add_answer(RR(qname, qtype, rdata=A(IP))) if qtype == QTYPE.AAAA: reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6))) elif qtype == QTYPE['*']: reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP))) reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP))) reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG))) print "------ Reply" print "\n".join([ " %s" % l for l in str(reply).split("\n")]) s.sendto(reply.pack(), peer)
def encrypt(self, raw_request, port, key): """ See protocolhandler.py """ data = raw_request[0].strip() try: request = DNSRecord.parse(data) q = request.questions[0] query = str(q.get_qname()).split(".")[::-1] if query[3] == Domains.ENCRYPT.value: self._send_data(request, port, Opcodes.KEY.value, key) self.fragments.clear() return 1 elif query[3] == Domains.CONFIRM.value: if query[4] == Domains.ENCRYPT.value: self._send_data(request, port, Opcodes.ACK.value, None) self.fragments.clear() return 2 else: # Return back to SYNC state, will perform SYNC-REQUEST self.logger.debug( f"{self.ip}: Client not in ENCRYPT. Falling back to SYNC") return 0 except DNSError: self.logger.debug(f"[{self.ip}] encrypt: DNS Query Malformed") return 1
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 device_finder(device_name='appletv', service_type=['_tcp'],_socket_timeout=5): UDP_IP="0.0.0.0" UDP_PORT=5353 MCAST_GRP = '224.0.0.251' sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind( (UDP_IP,UDP_PORT) ) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) for host in service_type: name = host+'.local' # dns = dpkt.dns.DNS('\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') # print name # dns.qd[0].name=name dns_v2 = DNSRecord.parse(str('\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01').encode('utf-8')) dns_v2=dns_v2.question(qname=name) sock.sendto(dns_v2.pack(),(MCAST_GRP,UDP_PORT)) sock.settimeout(_socket_timeout) out_put_final_name=None while out_put_final_name==None: out_put_final_name=_device_loop(sock, device_name) _socket_timeout+=1 sock.settimeout(_socket_timeout) return out_put_final_name
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): 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 handle(self, data, address): # parse udp datagram as dns request record try: request = DNSRecord.parse(data) except: # no real dns request, so simple close connection self.socket.close() else: # extract domain from dns request domain = str(request.get_q().get_qname()) self.logger.debug('%s requested domain: %s' % (address, domain)) # if that is the dns server name check if domain.startswith(self.proxy_ip_reversed): self.socket.sendto(request.reply(data="deiner Mutter").pack(), address) return # decide if mapped or not if self.is_mapped(domain): response = self.handle_mapped(domain, request) else: response = self.handle_forwarded(domain, request) # answer self.socket.sendto(response.pack(), address)
def parse(self, data): """解析数据""" try: dns = DNSRecord.parse(data) except Exception as e: printRed(e) return dns
def test_udp(typ, addr, port, user=None, pwd=None, host='8.8.8.8'): s = socks.socksocket( socket.AF_INET, socket.SOCK_DGRAM) # Same API as socket.socket in the standard lib try: s.set_proxy(socks.SOCKS5, addr, port, True, user, pwd) # SOCKS4 and SOCKS5 use port 1080 by default # Can be treated identical to a regular socket object # Raw DNS request req = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x05\x62\x61\x69\x64\x75\x03\x63\x6f\x6d\x00\x00\x01\x00\x01" s.sendto(req, (host, 53)) (rsp, address) = s.recvfrom(4096) print('packet received: ') print(binascii.b2a_hex(rsp)) record = DNSRecord.parse(rsp) print('DNS response:') print(record) if rsp[0] == req[0] and rsp[1] == req[1]: print("UDP check passed") else: print("Invalid response") except socket.error as e: print('socket error') print(repr(e)) raise except socks.ProxyError as e: print('proxy error') print(e.msg) raise except DNSError as e: print('DNS record parse error') print(e) raise
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 dns_handler(s, peer, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype print "------ Request (%s): %r (%s)" % (str(peer), qname.label, QTYPE[qtype]) print request reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) if qtype == QTYPE.A: reply.add_answer(RR(qname, qtype, rdata=A(IP))) if qtype == QTYPE.AAAA: reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6))) elif qtype == QTYPE['*']: reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP))) reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP))) reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG))) print "------ Reply" print reply s.sendto(reply.pack(), peer)
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
async def __handle_response(self, response, peer): """ 本地没查到,本服务做递归DNS查询,其他服务器返回的结果 :return: """ record = DNSRecord.parse(response) id = record.header.id qname = str(record.q.qname) qtype = record.q.qtype qclass = record.q.qclass if id not in self.peers: self.logger.info( "Unknown Response ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) return addr = self.peers[id] request = self.requests[id] reply = request.reply() reply.add_answer(*record.rr) del self.peers[id] del self.requests[id] self.transport.sendto(reply.pack(), addr) self.logger.info(f"==Reply from {peer}")
def resolve(self, request, handler): qname = request.q.qname reply = request.reply() # Note responses have TTL 4, as in Amazon's Dynamo DNS print(qname) if qname == 'alternator': ip = random.choice(livenodes) reply.add_answer( *dnslib.RR.fromZone('{} 4 A {}'.format(qname, ip))) # 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 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 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 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 _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 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 receive_and_handle(self, udpSocket): rlist, wlist, xlist = select.select([udpSocket], [], [], timeout) if not rlist: return data, addr = udpSocket.recvfrom(BUFFER_SIZE) request = DNSRecord.parse(data) self.logger.debug("handling request from '{addr}'".format(addr=addr)) response = first_or_default(self.server.config.behaviors, request).handle(request) if response: udpSocket.sendto(response.pack(), addr)
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 send_req_and_print_resp(packet, port): sock = socket(AF_INET, SOCK_DGRAM) sock.sendto(packet, ("localhost", port)) resp = sock.recv(2048) print("Client got response:") try: print(DNSRecord.parse(resp)) except DNSError: print(resp) sock.close()
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 process(self): with self._lock: buf, addr = self._sock.recvfrom(512) try: query = DNSRecord.parse(buf) print("DNS Q %s FROM: %s:%d" % (query.q.qname, addr[0], addr[1])) answer = self._handler.handle(query) with self._lock: self._queue.append((addr, answer)) except Exception as e: traceback.print_exc()
def map46(self, request, server): v6enable = server[1][0].find('.') == -1 request.q.qtype = DNS_AAAA_RECORD temp_proxy_r = request.send(server[1][0], server[1][1], timeout=self.timeout, ipv6=v6enable) temp_reply = DNSRecord.parse(temp_proxy_r) iplist = map_ip(server, str(request.q.qname)[:-1], temp_reply) request.q.qtype = DNS_A_RECORD reply = request.reply() for ip in iplist: reply.add_answer(RR(rname=request.q.qname, rtype=request.q.qtype, rclass=1, ttl=TTL, rdata=A(ip))) return reply
def request_upstream_DNS(self): log.info("request the upstream DNS") sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect((self.selected_DNS, 53)) sock.send(self.packet) response_packet = sock.recv(1024) self.wfile.write(response_packet) cache_key = "cache:{}:{}".format(self.qtype, self.qname) response_parse_ret = DNSRecord.parse(response_packet) cache_db.setex( cache_key, RECORD_CACHE_TIME, dumps(response_parse_ret.rr))
def handleDatagram(udp): ((src, sport), (dst, dport)) = udp.addr if sport != 53 and dport != 53: #chop.tsprnt("STOP: %s:%s->%s:%s (%i:%i)" % (src, sport, dst, dport, len(udp.data), len(udp.ip))) udp.stop() return try: o = DNSRecord.parse(udp.data) except KeyError, e: chop.prnt("Key error: %s" % str(e)) return
def resolve(self, request, handler): global OPTIONS queue = Queue.Queue() reply = None for i in range(OPTIONS.retry): for addr in self.addresses: request2 = copy.deepcopy(request) encrypted = addr[0][:1] in ["x", "X"] if encrypted: addr = (addr[0][1:],) + addr[1:] EncryptDNSRecord(request2) def put(request, encrypted, *send_args, **send_kwargs): try: if self.request_bind_address: result = request_send(request, *send_args, \ bind_address = \ self.request_bind_address, \ **send_kwargs) else: result = request.send(*send_args, **send_kwargs) except socket.timeout: pass else: queue.put((encrypted, result)) t = Thread(target = put, \ args = (request2, encrypted,) + addr, \ kwargs = {"timeout": OPTIONS.timeout}) t.daemon = True t.start() for _ in self.addresses: try: encrypted, r = queue.get(timeout = OPTIONS.timeout) except Queue.Empty: continue reply = DNSRecord.parse(r) if encrypted: EncryptDNSRecord(reply) if IsAcceptable(reply): return reply if not reply: raise DNSError("No reply received for the request") return reply
def handle(self, data, peer): rec = DNSRecord.parse(data) addr = None if rec.q.qtype in (QTYPE.A, QTYPE.AAAA): log.debug('Quering DNS') addr = self._registry.resolve(rec.q.qname.idna()) if not addr: strArr = [] for l in rec.q.qname.label: strArr.append(str(l,'utf-8')) domainName = '.'.join(strArr) addr = self._resolve(domainName) log.debug('Sending request to %s', addr) self.socket.sendto(self._reply(rec, addr), peer)
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 resolve(self,request,handler): 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 = request.reply() reply.header.rcode = getattr(RCODE,'NXDOMAIN') return reply
def dns_response(handler, data): try: request = DNSRecord.parse(data) except Exception as err: logger.error('Parse request error: %s' % err) return qn = request.q.qname qt = QTYPE[request.q.qtype] logger.debug('\n' + str(request)) local = False if 'local' in globalvars.config['server']['search']: local = lookup_local(handler, request) if local: logger.warn('\tRequest "%s(%s)" is in "local" list.' % (qn, qt)) elif 'upstream' in globalvars.config['server']['search']: proxy = globalvars.config['smartdns']['proxy'] qn2 = str(qn).rstrip('.') for name, param in globalvars.rules.items(): if param['rule'].isBlock(qn2): logger.warn('\tRequest "%s(%s)" is in "%s" list.' % (qn, qt, name)) best_dns = None servers = [] for group in param['upstreams']: servers.extend(globalvars.upstreams[group]) for server in servers: if best_dns is None: best_dns = server elif best_dns['priority'] < server['priority']: best_dns = server reply = lookup_upstream(request, best_dns, proxy) if reply: best_dns['priority'] += (5 if best_dns['priority'] < 100 else 0) logger.debug('\n' + str(reply)) handler.send_data(reply.pack()) else: best_dns['priority'] += (-10 if best_dns['priority'] > 0 else -1) # only use first matching rule break # update for value in globalvars.rules.values(): rule = value['rule'] if rule.isNeedUpdate(value['refresh']): rule.async_update() for value in globalvars.local_domains.values(): domain = value['domain'] if domain.isNeedUpdate(value['refresh']): domain.async_update()
def resolve(self,request,handler): reply = request.reply() qname = request.q.qname qtype = QTYPE[request.q.qtype] if qname.matchGlob("api-*padsv.gungho.jp."): host = self.hostaddr reply.add_answer(RR(qname,QTYPE.A,rdata=A(host))) self.onDNSEvent(str(qname)[:-1]) time.sleep(0.5) # we need to sleep until the proxy is up, half a second should do it... # Otherwise proxy if not reply.rr: 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