def get_response(data, spoofs, spoof_all): message = from_wire(data) domain = str(message.question[0].name)[:-1] rrset = None response = make_response(message) if spoofs and message.question[ 0].rdtype == dns.rdatatype.A and domain in spoofs: print('Spoofing query for %s' % domain) rrset = from_text(message.question[0].name, 300, dns.rdataclass.IN, dns.rdatatype.A, spoofs[domain]) elif spoof_all and message.question[0].rdtype == dns.rdatatype.A: print('Spoofing query for %s due to spoof all' % domain) rrset = from_text(message.question[0].name, 300, dns.rdataclass.IN, dns.rdatatype.A, spoof_all) else: print('Not spoofing %s query for %s' % (dns.rdatatype.to_text(message.question[0].rdtype), domain)) resolver = Resolver() try: rrset = resolver.query(message.question[0].name, message.question[0].rdtype, message.question[0].rdclass).rrset except dns.resolver.NXDOMAIN: response.set_rcode(dns.rcode.NXDOMAIN) except dns.resolver.NoAnswer: response.set_rcode(dns.rcode.NOERROR) if rrset: response.answer.append(rrset) return response
def handle(self, data, address): print("成功解析{}次, 共解析{}次".format(self.stats["success"], self.stats["total"])) self.stats["total"] += 1 query_msg = from_wire(data) assert len(query_msg.question) == 1 buffer = self.buffer.get(str(query_msg.question[0].name)) if buffer: response_msg = make_response(query_msg) response_msg.answer = buffer self.socket.sendto(response_msg.to_wire(), address) self.stats["success"] += 1 return client = DNSClient() for _ in range(2): server = self.get_server(query_msg.question) client.set_address(server) response_msg = client.query(query_msg) if response_msg and response_msg.answer: self.buffer[str( query_msg.question[0].name)] = response_msg.answer self.socket.sendto(response_msg.to_wire(), address) self.stats["success"] += 1 return server = self.get_server("") client.set_address(server) response_msg = client.query(query_msg) if response_msg and response_msg.answer: self.buffer[str(query_msg.question[0].name)] = response_msg.answer self.socket.sendto(response_msg.to_wire(), address) self.stats["success"] += 1 print("{}解析错误".format(str(query_msg.question[0].name)))
def create_answer(name, rrset): rdtype = rrset.rdtype rdclass = rrset.rdclass if not isinstance(name, Name): name = from_text(name) query = make_query(name, rdtype, rdclass) response = make_response(query) response.answer = [rrset] response.index = {(ANSWER, name, rdclass, rdtype, 0, None): rrset} response.find_rrset(response.answer, name, rdclass=rdclass, rdtype=rdtype) rdtype = RdataType.make(rdtype) rdclass = RdataClass.make(rdclass) answer = Answer(name, rdtype, rdclass, response) return answer
def query_uri(hosts): """ Return a list containing two answers, one for each uri type """ answers = [] if version.MAJOR < 2 or (version.MAJOR == 2 and version.MINOR == 0): m = message.Message() elif version.MAJOR == 2 and version.MINOR > 0: m = message.QueryMessage() # pylint: disable=E1101 m = message.make_response(m) # pylint: disable=E1101 rdtype = rdatatype.URI for name in ('_kerberos.', '_kpasswd.'): qname = DNSName(name + m_api.env.domain) qname = qname.make_absolute() if version.MAJOR < 2: # pylint: disable=unexpected-keyword-arg answer = Answer(qname, rdataclass.IN, rdtype, m, raise_on_no_answer=False) # pylint: enable=unexpected-keyword-arg else: if version.MAJOR == 2 and version.MINOR > 0: question = rrset.RRset(qname, rdataclass.IN, rdtype) m.question = [question] answer = Answer(qname, rdataclass.IN, rdtype, m) rl = [] for host in hosts: rlist = rrset.from_text_list( qname, 86400, rdataclass.IN, rdatatype.URI, [ '0 100 "krb5srv:m:tcp:%s."' % host, '0 100 "krb5srv:m:udp:%s."' % host, ]) rl.extend(rlist) answer.rrset = rl answers.append(answer) return answers
async def _process(sock, resolve, data, addr): try: msg = message.from_wire(data) except: print(f'[Serve53] invalid message from {addr}') return try: do = "1" if msg.flags & flags.DO else "0" rr = msg.question[0] res = await resolve(name=rr.name, type=rr.rdtype, do=do) want_nsid = edns.NSID in (o.otype for o in msg.options) msg = message.make_response(msg) msg.set_rcode(res.get('Status', rcode.NOERROR)) msg.question, msg.answer = [], [] msg.flags |= flags.from_text(" ".join(k for k, v in res.items() if len(k) == 2 and v is True)) for m, n in ((msg.question, "Question"), (msg.answer, "Answer"), (msg.authority, "Authority"), (msg.additional, "Additional")): for a in res.get(n, []): data = [a['data']] if 'data' in a else [] m.append( rrset.from_text(a['name'], a.get('TTL'), "IN", a['type'], *data)) if want_nsid: comment = res.get("Comment") nsid = f"named1/{res['NameClient']}{': ' + comment if comment else ''}" msg.options.append(edns.GenericOption(edns.NSID, nsid.encode())) except Exception as e: # Don't die on errors/timeouts but report back a failure if not isinstance(e, trio.TooSlowError): print(f"{e!r}\n{msg}") msg.flags = flags.QR msg.set_rcode(rcode.SERVFAIL) try: await sock.sendto(msg.to_wire(origin=origin), addr) except Exception as e: raise Exception( f"Malformed output with answer:\n{res}\n\nand msg:\n{msg}") from e
def collector(self, packet): packetdata = None try: eth = ImpactDecoder.EthDecoder().decode(packet) off = eth.get_header_size() if eth.get_ether_type() == ImpactPacket.IP.ethertype: ip_decoder = ImpactDecoder.IPDecoder() ip = ip_decoder.decode(packet[off:]) dst = ip.get_ip_dst() src = ip.get_ip_src() if ip.get_ip_p() == ImpactPacket.UDP.protocol: udp = ip.child() payload = udp.child().get_bytes().tostring() try: import hexdump try: msg = message.from_wire(payload) except Exception as e: # Not an acceptable DNS packet return None if len(msg.answer) > 0: # Packet should not have an answer section return None if len(msg.question) > 0: for q in msg.question: #if hasattr(q, 'name'): if q.rdtype == rdatatype.A: if self.PROPERTIES['subdomain']['Value']: prefix = '.%s.%s.' % ( self.PROPERTIES['subdomain'] ['Value'], self.PROPERTIES['domain']['Value']) else: prefix = '.%s.' % ( self.PROPERTIES['domain']['Value']) if prefix == q.name.to_text( )[-len(prefix):]: # Send a reply to the DNS packet try: r = message.make_response(msg) a = A(rdataclass.IN, rdatatype.A, '79.70.84.71' ) # OFTG in dotted-decimal rrs = rrset.from_rdata( q.name.to_text(), 30, a) r.answer.append(rrs) data = ImpactPacket.Data( r.to_wire()) rudp = ImpactPacket.UDP() rudp.set_uh_sport(53) rudp.set_uh_dport(12345) rudp.contains(data) rip = ImpactPacket.IP() rip.set_ip_dst(src) rip.set_ip_src(self.getlocaladdr()) rip.contains(rudp) s = socket.socket( socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) s.setsockopt( socket.IPPROTO_IP, socket.IP_HDRINCL, 1) s.sendto(rip.get_packet(), (src, 12345)) except Exception as e: self.logger.error( 'Failed to send reply packet with %s: %s' % (self.__class__.__name__, e)) dnsdata = q.name.to_text( )[:-len(prefix)] dnsdata = self.dnsb64unescape(dnsdata) payload = self.decoder(dnsdata) result = payload # TODO: Fix results result['Source Host'] = src result['Protocol Subtype'] = 'Port' result[ 'Subtype'] = 53 #str(ip.child().get_uh_sport()) return result except DNSException: pass except Exception as e: if e: print 'Error %s' % e.message raise elif eth.get_ether_type() == IP6.IP6.ethertype: ip6_decoder = ImpactDecoder.IP6Decoder() ip6 = ip6_decoder.decode(packet[off:]) src = ip6.get_source_address() packetdata = ip6.get_data_as_string() self.logger.debug( 'Skipping IPv6 packet (not supported for this plugin)') if not packetdata: return None return None except Exception as e: raise return None
def _make_response_for(self, request, name, address): response = message.make_response(request) respset = rrset.from_text(name + ".", 300, rdataclass.IN, rdatatype.A, address) response.answer.append(respset) return response
def run(self): flag = False data_dic = self.data_process(self.c_data) #查询数据库 # print(data_dic) db = DBFacade() _name , _type = data_dic['QUESTION'][0][0],data_dic['QUESTION'][0][2] #原始请求 answer = db.query(_name , _type) flag = (answer == []) #answer = [['www.shifen.com.','222','IN','A','39.20.1.1'],['www.shifen.com.','222','IN','A','25.69.6.3']] # print("---------------ans-----------") # print("answer: ",answer) if flag == False: #用数据库查到的数据向客户端发送 # print("---------------") # print("send case 1") # print("----------------") remark = 'Local' if answer[0][4] == '0.0.0.0' or answer[0][4] == '0:0:0:0:0:0:0:0': #拦截不良网站 print('拦截不良网站:', _name) remark = 'Rejected' elif answer[0][3] == 'MX': #answer 的处理 (MX) for i in range(len(answer)): answer[i].insert(4,'5') temp_message = message.from_wire(self.c_data) temp_message = message.make_response(temp_message).to_text() temp_list = temp_message.split("\n") index = temp_list.index(";ANSWER") for ret in answer: temp_list.insert(index+1,' '.join(ret)) index += 1 data_send = '\n'.join(temp_list) data_send = message.from_text(data_send) data_send = data_send.to_wire() self.c_socket.sendto(data_send, self.c_addr) #向客户端发回 else: #请求DNS服务器 self.s_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 与DNS服务器通信的套接字 # print("---------------") # print("send case 2") # print("----------------") self.s_socket.sendto(self.c_data, (self.send_ip, self.send_port)) #向服务器发送 self.s_socket.settimeout(self.timeout_time) #设置超时时间 try: data, addr = self.s_socket.recvfrom(1024) #读回DNS服务器的返回 remark = 'Remote' # print(data) # print(message.from_wire(data)) data_dic = self.data_process(data) # 存数据库 data_dic['ANSWER'] db = DBFacade() db.insert_records(data_dic["ANSWER"]) #发回到客户端 self.c_socket.sendto(data, self.c_addr) except socket.timeout: #DNS超时 print('请求超时:', _name) remark = 'TimeOut' self.s_socket.close() #获取DNS的返回后(或超时)关闭与服务器通信的socket #handler做完了一项工作,插入日志,退出 logger.info('%s:%s %s %s %s'%(self.c_addr[0], self.c_addr[1], _name , _type, remark))
def fake_query(qname, rdtype=rdatatype.A, rdclass=rdataclass.IN, count=1, fake_txt=False): """Fake a DNS query, returning count responses to the request Three kinds of lookups are faked: 1. A query for A/AAAA records for a service will return the count as requested in the test. This simulates lookups for the ipa-ca A/AAAA record. To force a difference in responses one can vary the count. 2. TXT queries will return the Kerberos realm fake_txt will set an invalid Kerberos realm entry to provoke a warning. """ if version.MAJOR < 2 or (version.MAJOR == 2 and version.MINOR == 0): m = message.Message() elif version.MAJOR == 2 and version.MINOR > 0: m = message.QueryMessage() m = message.make_response(m) if rdtype in (rdatatype.A, rdatatype.AAAA): fqdn = DNSName(qname) fqdn = fqdn.make_absolute() if version.MAJOR < 2: # pylint: disable=unexpected-keyword-arg answers = Answer(fqdn, rdataclass.IN, rdtype, m, raise_on_no_answer=False) # pylint: enable=unexpected-keyword-arg else: if version.MAJOR == 2 and version.MINOR > 0: question = rrset.RRset(fqdn, rdataclass.IN, rdtype) m.question = [question] answers = Answer(fqdn, rdataclass.IN, rdtype, m) rlist = rrset.from_text_list(fqdn, 86400, rdataclass.IN, rdtype, gen_addrs(rdtype, count)) answers.rrset = rlist elif rdtype == rdatatype.TXT: if fake_txt: realm = 'FAKE_REALM' else: realm = m_api.env.realm qname = DNSName('_kerberos.' + m_api.env.domain) qname = qname.make_absolute() if version.MAJOR < 2: # pylint: disable=unexpected-keyword-arg answers = Answer(qname, rdataclass.IN, rdatatype.TXT, m, raise_on_no_answer=False) # pylint: enable=unexpected-keyword-arg else: if version.MAJOR == 2 and version.MINOR > 0: question = rrset.RRset(qname, rdataclass.IN, rdtype) m.question = [question] answers = Answer(qname, rdataclass.IN, rdatatype.TXT, m) rlist = rrset.from_text_list(qname, 86400, rdataclass.IN, rdatatype.TXT, [realm]) answers.rrset = rlist return answers