def send_request(self, ip, name):

        #create socket and request
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(self.timeout)

        question = Question(name, Type.A, Class.IN)
        header = Header(9001, 0, 1, 0, 0, 0)
        header.qr = 0
        header.opcode = 0
        header.rd = self.rd
        query = Message(header, [question])

        sock.sendto(query.to_bytes(), (ip, 53))

        # Receive response
        data = sock.recv(512)
        sock.close()
        response = Message.from_bytes(data)
        self.logHeader(response.header)
        if self.caching:
            for r in response.resources:
                if r.type_ == Type.A or r.type_ == Type.CNAME or r.type_ == Type.NS:
                    self.cache.add_record(r)

        return response.answers, response.authorities, response.additionals
 def test_authority_domain(self):
     question = Question(Name("server1.gumpe"), Type.A, Class.IN)
     header = Header(1337, 0, 1, 0, 0, 0)
     query = Message(header, questions=[question])
     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     s.sendto(query.to_bytes(), (SERVER, PORT))
     data = s.recv(512)
     s.close()
     message = Message.from_bytes(data)
     self.assertCountEqual(message.answers, [
         ResourceRecord(
             name=Name("server1.gumpe."),
             type_=Type.A,
             class_=Class.IN,
             ttl=0,
             rdata=ARecordData("10.0.1.5"),
         ),
         ResourceRecord(
             name=Name("server1.gumpe."),
             type_=Type.A,
             class_=Class.IN,
             ttl=0,
             rdata=ARecordData("10.0.1.4"),
         ),
     ])
Example #3
0
def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    question = Question(Name("google.com."), Type.A, Class.IN)
    header = Header(9001, 0, 1, 0, 0, 0)
    header.qr = 0  # 0 for query
    header.opcode = 0  # standad query
    header.rd = 1  #  recursive
    query = Message(header, [question])
    ip = (([
        ip for ip in socket.gethostbyname_ex(socket.gethostname())[2]
        if not ip.startswith("127.")
    ] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close())
           for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]])
          + ["no IP found"])[0]

    sock.sendto(query.to_bytes(), (ip, 53))
    data = sock.recv(1024)
    mess = Message.from_bytes(data)
    """
  answer =  ResourceRecord.to_dict(mess.answers[0])
  auth = ResourceRecord.to_dict(mess.authorities[0])
  addi = ResourceRecord.to_dict(mess.additionals[0])
"""
    rrs = []
    rrs += mess.answers + mess.authorities + mess.additionals
    for r in rrs:
        print("R", r.to_dict())
Example #4
0
    def test_server_no_caching(self):
        data = self.send_query("nickstracke.xyz", PORT + 5)

        mess = Message.from_bytes(data)
        ip1 = mess.answers[0].rdata.address
        ip2 = socket.gethostbyname("nickstracke.xyz")
        self.assertEqual(ip1, ip2)
Example #5
0
    def test_concurrency(self):
        s2 = threading.Thread(target=self.send_query,
                              args=("nickstracke.xyz", PORT + 2))
        s2.daemon = True
        s2.start()
        data = self.send_query("nickstracke.xyz", PORT + 3)

        mess = Message.from_bytes(data)
        ip1 = mess.answers[0].rdata.address
        ip2 = socket.gethostbyname("nickstracke.xyz")
        self.assertEqual(ip1, ip2)
 def test_concurrent_requests(self):
     queries = []
     answers = []
     question = Question(Name("gaia.cs.umass.edu"), Type.A, Class.IN)
     header = Header(1337, 0, 1, 0, 0, 0)
     header.rd = 1
     queries.append(Message(header, questions=[question]))
     answers.append([
         ResourceRecord(name=Name("gaia.cs.umass.edu"),
                        type_=Type.A,
                        class_=Class.IN,
                        ttl=0,
                        rdata=ARecordData("128.119.245.12")),
     ])
     question = Question(Name("server2.gumpe"), Type.A, Class.IN)
     header = Header(420, 0, 1, 0, 0, 0)
     queries.append(Message(header, questions=[question]))
     answers.append([
         ResourceRecord(name=Name("server2.gumpe"),
                        type_=Type.A,
                        class_=Class.IN,
                        ttl=0,
                        rdata=ARecordData("10.0.1.7")),
     ])
     header = Header(69, 0, 1, 0, 0, 0)
     question = Question(Name("www.gumpe"), Type.A, Class.IN)
     queries.append(Message(header, questions=[question]))
     answers.append([
         ResourceRecord(name=Name("www.gumpe"),
                        type_=Type.A,
                        class_=Class.IN,
                        ttl=0,
                        rdata=ARecordData("10.0.1.7")),
         ResourceRecord(name=Name("www.gumpe"),
                        type_=Type.CNAME,
                        class_=Class.IN,
                        ttl=0,
                        rdata=CNAMERecordData(Name("server2.gumpe"))),
     ])
     sockets = [
         socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
         for _ in range(len(queries))
     ]
     for i in range(len(sockets)):
         sockets[i].sendto(queries[i].to_bytes(), (SERVER, PORT))
     responses = []
     for i in range(len(sockets)):
         responses.append(Message.from_bytes(sockets[i].recv(1024)))
     for i in range(len(sockets)):
         sockets[i].close()
     for i in range(len(queries)):
         self.assertCountEqual(responses[i].answers, answers[i])
Example #7
0
    def send_query(sock, hostname, ip):
        # Create and send query
        question = Question(Name(hostname), Type.A, Class.IN)
        header = Header(randint(0, 2**16), 0, 1, 0, 0, 0)
        header.qr = 0
        header.opcode = 0
        header.rd = 0  # no recursion desired
        query = Message(header, [question])
        sock.sendto(query.to_bytes(), (ip, 53))

        # Receive response
        data = sock.recv(512)
        return Message.from_bytes(data)
 def test_message_from_bytes(self, HeaderMock, QuestionMock, ResourceMock):
     packet = b"\x01\x02\x03\x04\x05"
     header = Header(9001, 0, 1, 1, 1, 1)
     HeaderMock.from_bytes.return_value = header
     QuestionMock.from_bytes.return_value = (1, 13)
     ResourceMock.from_bytes.side_effect = [(2, 14), (3, 15), (4, 16)]
     message1 = Message.from_bytes(packet)
     message2 = Message(header, [1], [2], [3], [4])
     self.assertEqual(message1, message2)
     HeaderMock.from_bytes.assert_called_with(packet)
     QuestionMock.from_bytes.assert_called_with(packet, 12)
     calls = [call(packet, 13), call(packet, 14), call(packet, 15)]
     ResourceMock.from_bytes.assert_has_calls(calls)
 def test_outside_zone(self):
     question = Question(Name("gaia.cs.umass.edu"), Type.A, Class.IN)
     header = Header(1337, 0, 1, 0, 0, 0)
     header.rd = 1
     query = Message(header, questions=[question])
     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     s.sendto(query.to_bytes(), (SERVER, PORT))
     data = s.recv(512)
     s.close()
     message = Message.from_bytes(data)
     self.assertEqual(message.answers, [
         ResourceRecord(name=Name("gaia.cs.umass.edu"),
                        type_=Type.A,
                        class_=Class.IN,
                        ttl=0,
                        rdata=ARecordData("128.119.245.12")),
     ])
Example #10
0
    def serve(self):
        """Start serving requests"""
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(("", self.port))

        while not self.done:
            data, address = sock.recvfrom(65565)
            message = Message.from_bytes(data)

            rd = message.header.rd
            rcode = 0
            aa = 1

            self.log("REQUEST RECIEVED:", address)
            answers, authorities, additionals = self.zone_resolution(message.questions)

            if answers == []:
                if authorities == [] and additionals == []:
                    self.log("\tZONE RESOLUTION FAILED")
                    answers = self.consult_cache(message.questions)

                    if answers == []:
                        self.log("\tCACHE LOOKUP FAILED")
                        rcode = 3
                    else:
                        aa = 0

                if rcode == 3 and rd == 1:
                    rcode = 0
                    self.log("\tCALLING RESOLVER")
                    resolver = Resolver(5, True, 0)
                    resolver.rd = 0
                    resolver.rootip = "198.41.0.4"
                    for q in message.questions:
                        self.log("\t\tRESOLVING:", q.qname)

                        hostname, namelist, iplist = resolver.gethostbyname(str(q.qname))
                        if hostname == str(q.qname):
                            for ip in iplist:
                                answers.append(ResourceRecord(q.qname, Type.A, Class.IN, self.ttl, ARecordData(ip)))
                            for n in namelist:
                                answers.append(ResourceRecord(q.qname, Type.CNAME, Class.IN, self.ttl, CNAMERecordData(n)))

            self.log("SENDING RESPONSE:", rcode, "\n")
            mess = self.build_message(message.header.ident, rd, aa, rcode, message.questions, answers, authorities, additionals)
            sock.sendto(mess.to_bytes(), address)
Example #11
0
    def serve(self):
        """ Start serving request """

        print("[+] - DNS Server up and running.")

        while not self.done:
            data, addr = self.socket.recvfrom(1024)

            try:
                message = Message.from_bytes(data)
            except:
                print("[-] - Received invalid data.")
                continue

            rh = RequestHandler(self.socket, addr, self.ttl, message,
                                self.resolver, self.catalog)
            rh.start()
Example #12
0
    def sendQuestion(self, hostname, server):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(self.timeout)

        # Create and send query
        identifier = 9001  # placeholder
        question = Question(Name(hostname), Type.A, Class.IN)
        header = Header(identifier, 0, 1, 0, 0, 0)
        header.qr = 0
        header.opcode = 0
        header.rd = 1
        query = Message(header, [question])
        sock.sendto(query.to_bytes(), (server, 53))

        # Receive response
        data = sock.recv(512)
        response = Message.from_bytes(data)
        sock.close()
        return response
Example #13
0
    def serve(self):
        """Start serving requests"""
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('localhost', self.port))
        zone = Zone().read_master_file("roothints.md")
        #load zone file into memory
        while not self.done:
            print("Waiting...")
            data, address = sock.recvfrom(512)
            #Following piece of code results in a weird error message which I do not understand. I do quite literally the same thing some other students do but it results in an error message.
            req = Message.from_bytes(data)
            questions = req.questions
            for question in questions:
                hostname = question.qname

                #consult zone and try to answer and cache
                #if recursion is enabled, and zone does not help: use resolver
            #send back reply.
            pass
 def run(self):
     """ Run the handler thread"""
     try:
         self.message = Message.from_bytes(self.data)
     except:
         self.message = Message(Header(0, 0, 0, 0, 0, 0))
         self.send_response([], False, 1)
         return
     self.domain = self.message.questions[0].qname
     print(threading.current_thread())
     print("\tDomain:", self.domain)
     print("\tAddress:", self.address)
     authoritative, records = self.lookup_zone(self.domain)
     if records is None:
         if self.message.header.rd:
             sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
             resolver = Resolver(5, Server.cache)
             records = resolver.query_recursive(sock, self.domain,
                                                Resolver.root_server)
             sock.close()
         else:
             records = []
     self.send_response(records, authoritative)
Example #15
0
    def run(self):
        """ Run the handler thread"""
        msg = Message.from_bytes(self.data)
        header = msg.header
        recursion = header.rd != 0
        questions = msg.questions

        answers = []
        authorative = []
        additional = []
        for question in questions:
            qname = question.qname
            qtype = question.qtype
            if question.qclass != Class.IN:
                pass
            domains = self.getdomains(str(qname))
            for domain in domains:
                if not self.zone.records.get(domain, False):
                    continue
                for rr in self.zone.records[domain]:
                    if (rr.type_ == Type.A or rr.type_
                            == Type.CNAME) and domain == str(qname):
                        answers.append(rr)
                    if rr.type_ == Type.NS:
                        authorative.append(rr)
                        for rec in self.zone.records[str(rr.rdata.nsdname)]:
                            if rec not in additional:
                                if rec.qtype == Type.A:
                                    additional.append(rec)
            if authorative or answers:
                header_response = Header(9001, 0, 1, len(answers),
                                         len(authorative), len(additionals))
                header_response.qr = True
                header_response.opcode(1)
                header_response.aa(False)
                header_respones.tc(False)
                header_response.rd(False)
                header_response.ra(True)
                header_response.z(False)
                header_respones.rcode(False)

                respons = Message(header_response, [question], answers,
                                  authorities, additionals)

                self.sock.sendto(respons.to_bytes(), self.addr)
                break

            if recursion and (qtype == Type.A or qtype == Type.CNAME):
                answers = []
                resolver = Resolver(100, False, 0, True)
                (hostname, aliaslist,
                 ipaddrlist) = resolver.gethostbyname(question.qname)
                header_response = Header(9001, 0, 1,
                                         len(aliaslist) + len(ipaddrlist), 0,
                                         0)
                header_response.qr = 1
                header_response.opcode = 1
                header_response.aa = 0
                header_response.tc = 0
                header_response.rd = 0
                header_response.ra = 1
                header_response.rcode = 0

                for addr in ipaddrlist:
                    answers.append(
                        ResourceRecord.from_dict({
                            "name": str(hostname),
                            "type": str(Type.A),
                            "class": str(Class.IN),
                            "ttl": 0,
                            "rdata": {
                                "address": str(addr)
                            }
                        }))
                for alias in aliaslist:
                    answers.append(
                        ResourceRecord.from_dict({
                            "name": str(hostname),
                            "type": str(Type.CNAME),
                            "class": str(Class.IN),
                            "ttl": 0,
                            "rdata": {
                                "cname": str(alias)
                            }
                        }))
                response = Message(header_response, questions, answers)
                self.sock.sendto(response.to_bytes(), self.addr)
                break
Example #16
0
 def test_authority(self):
     data = self.send_query("ns1.ourdomain.com", PORT + 4)
     mess = Message.from_bytes(data)
     ip1 = mess.answers[0].rdata.address
     print(ip1)
     self.assertEqual(ip1, "255.255.255.255")
Example #17
0
    def gethostbyname(self, hostname, dnsserv='192.112.36.4'):
        """Translate a host name to IPv4 address.

        Currently this method contains an example. You will have to replace
        this example with the algorithm described in section 5.3.3 in RFC 1034.

        Args:
            hostname (str): the hostname to resolve

        Returns:
            (str, [str], [str]): (hostname, aliaslist, ipaddrlist)
        """
        ipaddrlist = []
        cnames = []
        temp = []
        if (self.caching):
            rcache = RecordCache(self.ttl)
            rcord = rcache.lookup(hostname, Type.ANY, Class.IN)
            if (rcord):
                for rec in rcord:
                    if rec.type_ == Type.A:
                        arec = rec.rdata
                        ipaddrlist.append(arec.address)
                    elif rec.type_ == Type.CNAME:
                        crec = rec.rdata
                        cnames.append(crec.cname)
            if ipaddrlist:
                return hostname, cnames, ipaddrlist
            elif cnames:
                return self.gethostbyname(cnames[0], dnsserv)

        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(self.timeout)

        # Create and send query
        question = Question(Name(str(hostname)), Type.A, Class.IN)
        header = Header(9001, 0, 1, 0, 0, 0)
        header.qr = 0
        header.opcode = 0
        header.rd = 1
        query = Message(header, [question])
        sock.sendto(query.to_bytes(), (str(dnsserv), 53))

        # Receive response
        data = sock.recv(2048)
        response = Message.from_bytes(data)
        print("Number of answers: " + str(len(response.answers)))
        print("Number of authorities: " + str(len(response.authorities)))
        print("Number of additionals: " + str(len(response.additionals)))

        # Get data
        aliaslist = cnames
        ipaddrlist = []
        dnslist = []

        while response.answers:
            for answer in response.answers:
                if answer.type_ == Type.A:
                    print("found A RR")
                    if (self.caching):
                        rcache.add_record(answer)
                    ipaddrlist.append(answer.rdata.address)
                if answer.type_ == Type.CNAME:
                    aliaslist.append(answer.rdata.cname)
                if answer.type_ == Type.NS:
                    dnslist.append(answer.rdata.nsdname)
            if ipaddrlist:
                return hostname, aliaslist, ipaddrlist
            elif aliaslist:
                question = Question(Name(aliaslist[0]), Type.A, Class.IN)
                query = Message(header, [question])
                sock.sendto(query.to_bytes(), (dnsserv, 53))
                data = sock.recv(2048)
                response = Message.from_bytes(data)
            elif dnslist:
                nsname = dnslist.pop()
                maybe_dnsserv = self.getnsaddr(nsname, response.additionals)
                if maybe_dnsserv:
                    dnsserv = maybe_dnsserv
                else:
                    pass
                sock.sendto(query.to_bytes(), (dnsserv, 53))
                data = sock.recv(2048)
                response = Message.from_bytes(data)
            else:
                break

        if response.authorities:
            for authority in response.authorities:
                if authority.type_ != Type.NS:
                    pass
                dnslist.append(authority.rdata.nsdname)
            while dnslist:
                nsname = dnslist.pop()
                maybe_next_dnsserv = self.getnsaddr(nsname,
                                                    response.additionals)
                if maybe_next_dnsserv:
                    next_dns_serv = maybe_next_dnsserv
                else:
                    pass
                (hname, aliasl, ipaddrl) = self.gethostbyname(hostname, nsname)
                if ipaddrl:
                    return hname, aliasl, ipaddrl