コード例 #1
0
    def testSendECS(self):
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', '127.0.0.1/32')
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected)

        # check that a query in a different range is a miss
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.2', 32)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected)
コード例 #2
0
    def testRequireNoECS(self):
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', '192.168.0.1/32')

        ecso = clientsubnetoption.ClientSubnetOption('0.0.0.0', 0)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected, ttlECS)
コード例 #3
0
    def testSendECS(self):
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', emptyECSText)

        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected)
コード例 #4
0
    def testSendECS(self):
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', '127.0.0.0/24')
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected)

        # check that a query in a different ECS range is a hit, because we don't use the incoming ECS
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.2', 32)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.checkECSQueryHit(query, expected)
コード例 #5
0
ファイル: test_EdnsClientSubnet.py プロジェクト: swinsey/pdns
    def testWithEDNSNoECSResponseWithECS(self):
        """
        ECS: Existing EDNS without ECS (BE returning only the ECS option)

        Send a query with EDNS but no ECS value.
        Check that the query received by the responder
        has a valid ECS value and that the response
        received from dnsdist contains an EDNS pseudo-RR.
        This time the response returned by the backend contains
        an ECS option with scope set.
        """
        name = 'withednsnoecs.bereturnsecs.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096)
        expectedQuery = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
        response = dns.message.make_response(expectedQuery)
        ecsoResponse = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24, scope=24)
        response.use_edns(edns=True, payload=4096, options=[ecsoResponse])
        expectedResponse = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name,
                                    3600,
                                    dns.rdataclass.IN,
                                    dns.rdatatype.A,
                                    '127.0.0.1')
        response.answer.append(rrset)
        expectedResponse.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithoutECS(expectedResponse, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithoutECS(expectedResponse, receivedResponse)
コード例 #6
0
    def testRequireNoECS(self):
        # we will get ::1 because ecs-scope-zero-addr is set to ::1
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', '::1/128')

        ecso = clientsubnetoption.ClientSubnetOption('0.0.0.0', 0)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected, ttlECS)
コード例 #7
0
    def testWithoutEDNSResponseWithECS(self):
        """
        ECS: No existing EDNS (BE returning ECS)

        Send a query without EDNS, check that the query
        received by the responder has the correct ECS value
        and that the response received from dnsdist does not
        have an EDNS pseudo-RR.
        This time the response returned by the backend contains
        an ECS option with scope set.
        """
        name = 'withoutedns.bereturnsecs.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name, 'A', 'IN')
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               options=[ecso],
                                               payload=512)
        response = dns.message.make_response(expectedQuery)
        ecsoResponse = clientsubnetoption.ClientSubnetOption('127.0.0.1',
                                                             24,
                                                             scope=24)
        response.use_edns(edns=True, payload=4096, options=[ecsoResponse])
        expectedResponse = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)
        expectedResponse.answer.append(rrset)

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            (receivedQuery, receivedResponse) = sender(query, response)
            self.assertTrue(receivedQuery)
            self.assertTrue(receivedResponse)
            receivedQuery.id = expectedQuery.id
            self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
            self.checkResponseNoEDNS(expectedResponse, receivedResponse)
コード例 #8
0
    def testRequireNoECS(self):
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', '127.0.0.0/24')

        # the request for no ECS is ignored because use-incoming-edns-subnet is not set
        ecso = clientsubnetoption.ClientSubnetOption('0.0.0.0', 0)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected)
コード例 #9
0
    def testLatlonloc(self):
        """
        Basic latlonloc() test
        """
        name = 'latlonloc.geo.example.org.'
        expected = dns.rrset.from_text(name, 0,dns.rdataclass.IN, 'TXT',
                                       '"47 54 46.8 N 122 18 15.12 W 0.00m 1.00m 10000.00m 10.00m"')
        ecso = clientsubnetoption.ClientSubnetOption('1.2.3.0', 24)
        query = dns.message.make_query(name, 'TXT', 'IN', use_edns=True, payload=4096, options=[ecso])

        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
コード例 #10
0
ファイル: test_EdnsClientSubnet.py プロジェクト: swinsey/pdns
    def testWithEDNSSameSizeInitialECS(self):
        """
        ECS Override: Existing EDNS with ECS (same)

        Send a query with EDNS and a crafted ECS value.
        Check that the query received by the responder
        has an overwritten ECS value (not the initial one)
        and that the response received from dnsdist contains
        an EDNS pseudo-RR.
        The initial ECS value is exactly the same size as
        the one it will replaced with.
        """
        name = 'withednsecs.overridden.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 24)
        rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
        expectedQuery = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[rewrittenEcso])
        response = dns.message.make_response(query)
        response.use_edns(edns=True, payload=4096, options=[rewrittenEcso])
        rrset = dns.rrset.from_text(name,
                                    3600,
                                    dns.rdataclass.IN,
                                    dns.rdatatype.A,
                                    '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithECS(response, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithECS(response, receivedResponse)
コード例 #11
0
    def testTeeWithECS(self):
        """
        TeeAction: ECS
        """
        name = 'ecs.tee.tests.powerdns.com.'
        query = dns.message.make_query(name, 'A', 'IN')
        response = dns.message.make_response(query)

        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '192.0.2.1')
        response.answer.append(rrset)

        numberOfQueries = 10
        for _ in range(numberOfQueries):
            # push the response to the Tee server
            self._toTeeQueue.put(response, True, 2.0)

            (receivedQuery,
             receivedResponse) = self.sendUDPQuery(query, response)
            self.assertTrue(receivedQuery)
            self.assertTrue(receivedResponse)
            receivedQuery.id = query.id
            self.assertEquals(query, receivedQuery)
            self.assertEquals(response, receivedResponse)

            # retrieve the query from the Tee server
            teedQuery = self._fromTeeQueue.get(True, 2.0)
            ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
            expectedQuery = dns.message.make_query(name,
                                                   'A',
                                                   'IN',
                                                   use_edns=True,
                                                   options=[ecso],
                                                   payload=512)
            expectedQuery.id = query.id
            self.checkQueryEDNSWithECS(expectedQuery, teedQuery)

        # check the TeeAction stats
        stats = self.sendConsoleCommand("getAction(0):printStats()")
        self.assertEquals(
            stats, """noerrors\t%d
nxdomains\t0
other-rcode\t0
queries\t%d
recv-errors\t0
refuseds\t0
responses\t%d
send-errors\t0
servfails\t0
tcp-drops\t0
""" % (numberOfQueries, numberOfQueries, numberOfQueries))
コード例 #12
0
    def testWithECSOverrideSetViaLua(self):
        """
        ECS Override: set via Lua
        """
        name = 'overriddenvialua.ecsrules.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 24)
        rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[ecso])
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               payload=4096,
                                               options=[rewrittenEcso])
        response = dns.message.make_response(query)
        response.use_edns(edns=True, payload=4096, options=[rewrittenEcso])
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithECS(response, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithECS(response, receivedResponse)
コード例 #13
0
    def testRequireNoECS(self):
        # we should get ::1/128 because neither ecs-scope-zero-addr nor query-local-address are set,
        # but query-local-address6 is set to ::1
        expected = dns.rrset.from_text(nameECS, ttlECS, dns.rdataclass.IN,
                                       'TXT', "::1/128")

        ecso = clientsubnetoption.ClientSubnetOption('0.0.0.0', 0)
        query = dns.message.make_query(nameECS,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)
        self.sendECSQuery(query, expected, ttlECS)
コード例 #14
0
 def testSubnet(self):
     name = 'gettag-subnet.lua.'
     subnet = '192.0.2.255'
     subnetMask = 32
     ecso = clientsubnetoption.ClientSubnetOption(subnet, subnetMask)
     expected = [
         dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.1'),
         dns.rrset.from_text_list(name, 0, dns.rdataclass.IN, 'TXT', [name, 'gettag-qtype-1', 'edns-subnet-' + subnet + '/' + str(subnetMask),
                                                                      'ednsoption-8-count-1', 'ednsoption-8-total-len-8']),
         ]
     query = dns.message.make_query(name, 'A', want_dnssec=True, options=[ecso])
     query.flags |= dns.flags.CD
     res = self.sendUDPQuery(query)
     self.assertResponseMatches(query, expected, res)
コード例 #15
0
    def testSendECSInvalidScope(self):
        # test that the recursor does not cache with a more specific scope than the source it sent
        expected = dns.rrset.from_text(nameECSInvalidScope, ttlECS,
                                       dns.rdataclass.IN, 'TXT',
                                       '192.0.2.0/24')

        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        query = dns.message.make_query(nameECSInvalidScope,
                                       'TXT',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512)

        self.sendECSQuery(query, expected)
コード例 #16
0
    def testWithEDNSNoECS(self):
        """
        ECS: Existing EDNS without ECS

        Send a query with EDNS but no ECS value.
        Check that the query received by the responder
        has a valid ECS value and that the response
        received from dnsdist contains an EDNS pseudo-RR.
        """
        name = 'withednsnoecs.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096)
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               payload=4096,
                                               options=[ecso])
        response = dns.message.make_response(expectedQuery)
        expectedResponse = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)
        expectedResponse.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.assertEquals(expectedQuery, receivedQuery)
        self.assertEquals(expectedResponse, receivedResponse)
        self.assertEquals(receivedResponse.edns, 0)
        self.assertEquals(len(receivedResponse.options), 0)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.assertEquals(expectedQuery, receivedQuery)
        self.assertEquals(expectedResponse, receivedResponse)
        self.assertEquals(receivedResponse.edns, 0)
        self.assertEquals(len(receivedResponse.options), 0)
コード例 #17
0
    def testClosest(self):
        """
        Basic pickclosest() test
        """
        queries = [
            ('1.1.1.0', 24,  '1.1.1.2'),
            ('1.2.3.0', 24,  '1.2.3.4'),
            ('17.1.0.0', 16, '1.1.1.2')
        ]
        name = 'closest.geo.example.org.'
        for (subnet, mask, ip) in queries:
            ecso = clientsubnetoption.ClientSubnetOption(subnet, mask)
            query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
            expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', ip)

            res = self.sendUDPQuery(query)
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertRRsetInAnswer(res, expected)
コード例 #18
0
    def testTooLarge(self):
        qname = 'toolarge.ecs.'
        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 24)
        query = dns.message.make_query(qname, 'TXT', 'IN', use_edns=True, options=[ecso], payload=512)

        # should not have an ECS Option since the packet is too large already
        res = self.sendUDPQuery(query, timeout=5.0)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertEqual(len(res.answer), 1)
        self.assertEqual(res.edns, 0)
        self.assertEqual(len(res.options), 0)

        res = self.sendTCPQuery(query, timeout=5.0)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertEqual(len(res.answer), 1)
        self.assertEqual(res.edns, 0)
        self.assertEqual(len(res.options), 1)
        self.assertEqual(res.options[0].otype, 8)
        self.assertEqual(res.options[0].scope, 0)
コード例 #19
0
def query_nameserver(nameserver, name):
    """
    Do a DNS query against a specified  nameserver
    """
    LOG.debug("Querying {0} for {1}".format(nameserver, name))
    qname = dns.name.from_text(name)
    cso = clientsubnetoption.ClientSubnetOption(get_external_ip())
    message = dns.message.make_query(qname, 'A')
    message.use_edns(options=[cso])
    try:
        r = dns.query.udp(message, nameserver, timeout=DNS_TIMEOUT, port=53)
    except dns.exception.Timeout:
        return 'TIMEOUT'

    ns_rrset = r.find_rrset(r.answer, qname, dns.rdataclass.IN,
                            dns.rdatatype.A)
    for rr in ns_rrset:
        DNS_REQUESTS.inc()
        return rr
コード例 #20
0
    def testWithoutEDNS(self):
        """
        ECS Override: No existing EDNS

        Send a query without EDNS, check that the query
        received by the responder has the correct ECS value
        and that the response received from dnsdist does not
        have an EDNS pseudo-RR.
        """
        name = 'withoutedns.overriden.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name, 'A', 'IN')
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               options=[ecso],
                                               payload=512)
        response = dns.message.make_response(expectedQuery)
        expectedResponse = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)
        expectedResponse.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.assertEquals(expectedQuery, receivedQuery)
        self.assertEquals(expectedResponse, receivedResponse)
        self.assertEquals(receivedResponse.edns, -1)
        self.assertEquals(len(receivedResponse.options), 0)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.assertEquals(expectedQuery, receivedQuery)
        self.assertEquals(expectedResponse, receivedResponse)
        self.assertEquals(receivedResponse.edns, -1)
        self.assertEquals(len(receivedResponse.options), 0)
コード例 #21
0
ファイル: test_Basics.py プロジェクト: wpsocket-com/pdns
    def testAWithECS(self):
        """
        Basics: A query with an ECS value
        """
        name = 'awithecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('1.2.3.4')
        query = dns.message.make_query(name, 'A', 'IN', use_edns=True, options=[ecso])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name,
                                    60,
                                    dns.rdataclass.IN,
                                    dns.rdatatype.A,
                                    '127.0.0.1')

        response.answer.append(rrset)

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            (receivedQuery, receivedResponse) = sender(query, response)
            receivedQuery.id = query.id
            self.assertEquals(query, receivedQuery)
            self.assertEquals(response, receivedResponse)
コード例 #22
0
    def testWithEDNSECS(self):
        """
        ECS: Existing EDNS with ECS

        Send a query with EDNS and a crafted ECS value.
        Check that the query received by the responder
        has the initial ECS value (not overwritten)
        and that the response received from dnsdist contains
        an EDNS pseudo-RR.
        """
        name = 'withednsecs.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('1.2.3.4', 24)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[ecso])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = query.id
        receivedResponse.id = response.id
        self.assertEquals(query, receivedQuery)
        self.assertEquals(response, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = query.id
        receivedResponse.id = response.id
        self.assertEquals(query, receivedQuery)
        self.assertEquals(response, receivedResponse)
コード例 #23
0
def responseCallback(request):
    if len(request.question) != 1:
        print("Skipping query with question count %d" % (len(request.question)))
        return None
    healthCheck = str(request.question[0].name).endswith('a.root-servers.net.')
    if healthCheck:
        response = dns.message.make_response(request)
        return response.to_wire()
    # now we create a broken response
    response = dns.message.make_response(request)
    ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 32)
    response.use_edns(edns=True, payload=4096, options=[ecso])
    rrset = dns.rrset.from_text(request.question[0].name,
                                3600,
                                dns.rdataclass.IN,
                                dns.rdatatype.A,
                                '127.0.0.1')
    response.answer.append(rrset)
    raw = response.to_wire()
    # first label length of this rrset is at 12 (dnsheader) + length(qname) + 2 (leading label length + trailing 0) + 2 (qtype) + 2 (qclass)
    offset = 12 + len(str(request.question[0].name)) + 2 + 2 + 2
    altered = raw[:offset] + b'\xff' + raw[offset+1:]
    return altered
コード例 #24
0
    def testCookie(self):
        """
        EDNS Options: Cookie (adding ECS)
        """
        name = 'cookie.ednsoptions-ecs.tests.powerdns.com.'
        eco = cookiesoption.CookiesOption('deadbeef', 'deadbeef')
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[eco])
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               options=[eco, ecso],
                                               payload=512)
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery, 1)
        self.checkResponseEDNSWithoutECS(response, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery, 1)
        self.checkResponseEDNSWithoutECS(response, receivedResponse)
コード例 #25
0
    def testDOHExistingEDNS(self):
        """
        DOH with ECS: Existing EDNS
        """
        name = 'existing-edns.doh-ecs.tests.powerdns.com.'
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=8192)
        query.id = 0
        rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.0', 24)
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               payload=8192,
                                               options=[rewrittenEcso])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery,
         receivedResponse) = self.sendDOHQuery(self._dohServerPort,
                                               self._serverName,
                                               self._dohBaseURL,
                                               query,
                                               response=response,
                                               caFile=self._caCert)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.assertEquals(expectedQuery, receivedQuery)
        self.assertEquals(response, receivedResponse)
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithoutECS(response, receivedResponse)
コード例 #26
0
    def testClosestMagic(self):
        """
        Basic closestMagic() test
        """
        name = 'www-balanced.example.org.'
        cname = '1-1-1-3.17-1-2-4.1-2-3-5.magic.example.org.'
        queries = [
            ('1.1.1.0', 24,  '1.1.1.3'),
            ('1.2.3.0', 24,  '1.2.3.5'),
            ('17.1.0.0', 16, '17.1.2.4')
        ]
                
        for (subnet, mask, ip) in queries:
            ecso = clientsubnetoption.ClientSubnetOption(subnet, mask)
            query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])

            response = dns.message.make_response(query)

            response.answer.append(dns.rrset.from_text(name, 0, dns.rdataclass.IN, dns.rdatatype.CNAME, cname))
            response.answer.append(dns.rrset.from_text(cname, 0, dns.rdataclass.IN, 'A', ip))

            res = self.sendUDPQuery(query)
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertEqual(res.answer, response.answer)
コード例 #27
0
ファイル: test_ProxyProtocol.py プロジェクト: swoga/pdns
    def testWhoAmI(self):
        """
        See if LUA who picks up the inner address from the PROXY protocol
        """

        for testWithECS in True, False:
            # first test with an unproxied query - should get ignored

            options = []
            expectedText = '192.0.2.1/192.0.2.1'

            if testWithECS:
                ecso = clientsubnetoption.ClientSubnetOption('192.0.2.5', 32)
                options.append(ecso)
                expectedText = '192.0.2.1/192.0.2.5'

            query = dns.message.make_query('myip.example.org',
                                           'TXT',
                                           'IN',
                                           use_edns=testWithECS,
                                           options=options,
                                           payload=512)

            res = self.sendUDPQuery(query)

            self.assertEqual(res, None)  # query was ignored correctly

            # now send a proxied query
            queryPayload = query.to_wire()
            ppPayload = ProxyProtocol.getPayload(False, False, False,
                                                 "192.0.2.1", "10.1.2.3",
                                                 12345, 53, [])
            payload = ppPayload + queryPayload

            # UDP
            self._sock.settimeout(2.0)

            try:
                self._sock.send(payload)
                data = self._sock.recv(4096)
            except socket.timeout:
                data = None
            finally:
                self._sock.settimeout(None)

            res = None
            if data:
                res = dns.message.from_wire(data)

            expected = [
                dns.rrset.from_text('myip.example.org.', 0, dns.rdataclass.IN,
                                    'TXT', expectedText)
            ]
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertEqual(res.answer, expected)

            # TCP
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2.0)
            sock.connect(("127.0.0.1", self._authPort))

            try:
                sock.send(ppPayload)
                sock.send(struct.pack("!H", len(queryPayload)))
                sock.send(queryPayload)
                data = sock.recv(2)
                if data:
                    (datalen, ) = struct.unpack("!H", data)
                    data = sock.recv(datalen)
            except socket.timeout as e:
                print("Timeout: %s" % (str(e)))
                data = None
            except socket.error as e:
                print("Network error: %s" % (str(e)))
                data = None
            finally:
                sock.close()

            res = None
            if data:
                res = dns.message.from_wire(data)

            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertEqual(res.answer, expected)
コード例 #28
0
ファイル: crawler.py プロジェクト: aideyisu/Pop-data-crawler
def main(arguments):

    # default: start from 1.0.0.0
    IP_binary = struct.unpack('!L', socket.inet_aton(arguments.start))[0]
    step = 24  # /24 is the minium step

    mask = step
    suggested_mask = step  # the mask suggested by DNS response

    pool = {}  # the mapping results

    count = 1
    timeout = 0
    failed = 0
    isFailed = False

    # # first, restore the current states from last time
    # if os.path.isfile(CACHE_FILE):
    #     with open(CACHE_FILE, 'rb') as f:
    #         pool = pickle.load(f)

    if os.path.isfile(NOW_FILE):
        with open(NOW_FILE, 'rb') as f:
            IP_binary = pickle.load(f)
    # load geo ip data
    READER = geoip2.database.Reader('./geoip/GeoLite2-City.mmdb')
    print("准备就绪")
    # main loop over all IPs
    # while IP_binary < 255*(1<<24): #255.0.0.0
    while IP_binary < 2 * (1 << 24):  # 1.0.0.0
        IP_pack = struct.pack('!L', IP_binary)
        IP = socket.inet_ntoa(IP_pack)

        # skip private IP
        if not good_IP(IP, READER):
            IP_binary = advance(IP_binary, mask)
            continue
        # skip google IP as their locations are all reported as MTV
        googlemask = isGoogleIP(IP_binary)
        if googlemask > 0:
            IP_binary = advance(IP_binary, googlemask)
            continue
        # creat the query message
        cso = clientsubnetoption.ClientSubnetOption(IP, bits=mask)
        print(IP, cso)
        print("CSO打印完啦")
        # default: 'google'
        message = dns.message.make_query(CDN[arguments.name], 'A')
        message.use_edns(options=[cso])
        print(message)
        print("Message打印完啦")
        try:
            # rotating the DNS server we use
            r = dns.query.udp(message,
                              DNS_servers[count % len(DNS_servers)],
                              timeout=arguments.timeout)
            print(r)
            print("打印完啦")
        except dns.exception.Timeout:
            timeout += 1
            print('timeout:', DNS_servers[count % len(DNS_servers)], IP)
            IP_binary = advance(IP_binary, mask)
            continue

        # only use A record here because it seems enough
        servers = {}
        for ans in r.answer:
            if ans.to_rdataset().rdtype == dns.rdatatype.A:
                # use /24 prefix to represent
                # all the servers in the same location
                server = networkMask(ans[0].to_text(), 24)
                servers[server] = 1
        print(servers)
        # if ENDS0 is used, get the suggested mask.
        for options in r.options:
            if isinstance(options, clientsubnetoption.ClientSubnetOption):
                suggested_mask = int(options.scope)

        if len(servers) > 0:
            for server in servers:
                clients = pool.get(server, [])
                clients.append((IP, suggested_mask))
                pool[server] = clients
                isFailed = False
        else:
            failed += 1
            print(r.answer)
            print ('failed:', DNS_servers[count%len(DNS_servers)],\
                            IP, suggested_mask)
            isFailed = True

        if suggested_mask == 0:
            # suggested == 0 *might* imply EDNS0 is not supported
            mask = step
        elif suggested_mask == 32:
            # suggested == 0 *might* imply
            # the EDNS0 record for this prefix is not set
            mask = 17  # rule of thumb: take a big step forward
        else:
            mask = suggested_mask

        IP_binary = advance(IP_binary, mask)
        count += 1
        print(pool)
        break

        # save and report every 500 prefixes
        if count % 500 == 0:
            print(IP, mask, suggested_mask)
            print("Servers %d, errors %d/%d" % (len(pool), timeout, failed))
            # start another thread to save so that it will not be interrupted
            # by signals such as ctrl+c
            a = Thread(target=save_states, args=(pool, IP_binary))
            a.start()
            a.join()
        if isFailed:
            # might need to slow down because we sent too many requests
            # rule of thumb: 90 seconds should be enough
            time.sleep(arguments.cooldown)
        else:
            time.sleep(arguments.delay)
コード例 #29
0
    def testWithEDNSNoOptions(self):
        """
        EDNS on Self-Generated: EDNS with options in the query
        """
        name = 'edns-options.rcode.edns-self.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512,
                                       want_dnssec=True)
        expectedResponse = dns.message.make_response(query)
        expectedResponse.set_rcode(dns.rcode.REFUSED)

        (_, receivedResponse) = self.sendUDPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        (_, receivedResponse) = self.sendTCPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        name = 'edns-options.tc.edns-self.tests.powerdns.com.'
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512,
                                       want_dnssec=True)
        expectedResponse = dns.message.make_response(query)
        expectedResponse.flags |= dns.flags.TC

        (_, receivedResponse) = self.sendUDPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        (_, receivedResponse) = self.sendTCPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        name = 'edns-options.lua.edns-self.tests.powerdns.com.'
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512,
                                       want_dnssec=True)
        expectedResponse = dns.message.make_response(query)
        expectedResponse.set_rcode(dns.rcode.NXDOMAIN)

        (_, receivedResponse) = self.sendUDPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        (_, receivedResponse) = self.sendTCPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        name = 'edns-options.spoof.edns-self.tests.powerdns.com.'
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       options=[ecso],
                                       payload=512,
                                       want_dnssec=True)
        # dnsdist set RA = RD for spoofed responses
        query.flags &= ~dns.flags.RD
        expectedResponse = dns.message.make_response(query)
        expectedResponse.answer.append(
            dns.rrset.from_text(name, 60, dns.rdataclass.IN, dns.rdatatype.A,
                                '192.0.2.1', '192.0.2.2'))

        (_, receivedResponse) = self.sendUDPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)

        (_, receivedResponse) = self.sendTCPQuery(query,
                                                  response=None,
                                                  useQueue=False)
        self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
        self.assertTrue(receivedResponse.ednsflags & dns.flags.DO)
        self.assertEquals(receivedResponse.payload, 1042)
コード例 #30
0
    def testPacketCache(self):
        # first query, no cookie
        qname = 'a.example.'
        query = dns.message.make_query(qname, 'A', want_dnssec=True)
        expected = dns.rrset.from_text(qname, 0, dns.rdataclass.IN, 'A',
                                       '192.0.2.42')

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            res = sender(query)
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertRRsetInAnswer(res, expected)

        self.checkPacketCacheMetrics(0, 1)

        # we should get a hit over UDP this time
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(1, 1)

        eco1 = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        eco2 = cookiesoption.CookiesOption(b'deadc0de', b'deadc0de')
        ecso1 = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        ecso2 = clientsubnetoption.ClientSubnetOption('192.0.2.2', 32)

        # we add a cookie, should not match anymore
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(1, 2)

        # same cookie, should match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(2, 2)

        # different cookie, should still match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(3, 2)

        # first cookie but with an ECS option, should not match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(3, 3)

        # different cookie but same ECS option, should match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco2, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(4, 3)

        # first cookie but different ECS option, should still match (we ignore EDNS Client Subnet
        # in the recursor's packet cache, but ECS-specific responses are not cached
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1, ecso2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(5, 3)