Пример #1
0
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
Пример #2
0
 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)))
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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
Пример #7
0
 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
Пример #8
0
    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))
Пример #9
0
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