def test_pickServerWeights(self): """ pickServer calculates running sum of weights and calls randint. This exercises the server selection algorithm specified in RFC 2782 by preparing fake L{random.randint} results and checking the values it was called with. """ record1 = dns.Record_SRV(10, 10, 5222, 'host1.example.org') record2 = dns.Record_SRV(10, 20, 5222, 'host2.example.org') self.connector.orderedServers = [record1, record2] self.connector.servers = [] self.patch(random, 'randint', self._randint) # 1st round self.randIntResults = [11, 0] self.connector.pickServer() self.assertEqual(self.randIntArgs[0], (0, 30)) self.connector.pickServer() self.assertEqual(self.randIntArgs[1], (0, 10)) # 2nd round self.randIntResults = [10, 0] self.connector.pickServer() self.assertEqual(self.randIntArgs[2], (0, 30)) self.connector.pickServer() self.assertEqual(self.randIntArgs[3], (0, 20))
def test_srvDifferentPriorities(self): """ Two records with differing priorities compare on priority (ascending). """ record1 = dns.Record_SRV(10, 0, 5222, "host1.example.org") record2 = dns.Record_SRV(20, 0, 5222, "host2.example.org") self.connector.orderedServers = [record2, record1] self.connector.servers = [] self.patch(random, "randint", self._randint) self.randIntResults = [0, 0] self.assertEqual(("host1.example.org", 5222), self.connector.pickServer()) self.assertEqual(("host2.example.org", 5222), self.connector.pickServer())
def test_disabled_service(self): """ test the behaviour when there is a single record which is ".". """ service_name = b"test_service.example.com" lookup_deferred = Deferred() dns_client_mock = Mock() dns_client_mock.lookupService.return_value = lookup_deferred cache = {} resolver = SrvResolver(dns_client=dns_client_mock, cache=cache) # Old versions of Twisted don't have an ensureDeferred in failureResultOf. resolve_d = defer.ensureDeferred(resolver.resolve_service(service_name)) # returning a single "." should make the lookup fail with a ConenctError lookup_deferred.callback( ( [dns.RRHeader(type=dns.SRV, payload=dns.Record_SRV(target=b"."))], None, None, ) ) self.failureResultOf(resolve_d, ConnectError)
def test_resolve(self): dns_client_mock = Mock() service_name = "test_service.example.com" host_name = "example.com" answer_srv = dns.RRHeader( type=dns.SRV, payload=dns.Record_SRV( target=host_name, ) ) dns_client_mock.lookupService.return_value = defer.succeed( ([answer_srv], None, None), ) cache = {} servers = yield resolve_service( service_name, dns_client=dns_client_mock, cache=cache ) dns_client_mock.lookupService.assert_called_once_with(service_name) self.assertEquals(len(servers), 1) self.assertEquals(servers, cache[service_name]) self.assertEquals(servers[0].host, host_name)
def testSRV(self): """Test DNS 'SRV' record queries""" return self.namesTest( self.resolver.lookupService('http.tcp.test-domain.com'), [ dns.Record_SRV( 257, 16383, 43690, 'some.other.place.fool', ttl=19283784) ])
def test_resolve(self): dns_client_mock = Mock() service_name = "test_service.examle.com" host_name = "example.com" ip_address = "127.0.0.1" answer_srv = dns.RRHeader(type=dns.SRV, payload=dns.Record_SRV(target=host_name, )) answer_a = dns.RRHeader(type=dns.A, payload=dns.Record_A(address=ip_address, )) dns_client_mock.lookupService.return_value = ([answer_srv], None, None) dns_client_mock.lookupAddress.return_value = ([answer_a], None, None) cache = {} servers = yield resolve_service(service_name, dns_client=dns_client_mock, cache=cache) dns_client_mock.lookupService.assert_called_once_with(service_name) dns_client_mock.lookupAddress.assert_called_once_with(host_name) self.assertEquals(len(servers), 1) self.assertEquals(servers, cache[service_name]) self.assertEquals(servers[0].host, ip_address)
def test_non_srv_answer(self): """ test the behaviour when the dns server gives us a spurious non-SRV response """ service_name = b"test_service.example.com" lookup_deferred = Deferred() dns_client_mock = Mock() dns_client_mock.lookupService.return_value = lookup_deferred cache = {} resolver = SrvResolver(dns_client=dns_client_mock, cache=cache) resolve_d = resolver.resolve_service(service_name) self.assertNoResult(resolve_d) lookup_deferred.callback(( [ dns.RRHeader(type=dns.A, payload=dns.Record_A()), dns.RRHeader(type=dns.SRV, payload=dns.Record_SRV(target=b"host")), ], None, None, )) servers = self.successResultOf(resolve_d) self.assertEquals(len(servers), 1) self.assertEquals(servers, cache[service_name]) self.assertEquals(servers[0].host, b"host")
def test_pickServerSamePriorities(self): """ Two records with equal priorities compare on weight (ascending). """ record1 = dns.Record_SRV(10, 10, 5222, 'host1.example.org') record2 = dns.Record_SRV(10, 20, 5222, 'host2.example.org') self.connector.orderedServers = [record2, record1] self.connector.servers = [] self.patch(random, 'randint', self._randint) self.randIntResults = [0, 0] self.assertEqual(('host1.example.org', 5222), self.connector.pickServer()) self.assertEqual(('host2.example.org', 5222), self.connector.pickServer())
def test_srv(self): """ The repr of a L{dns.Record_SRV} instance includes the name and port of the target and the priority, weight, and TTL of the record. """ self.assertEqual( repr(dns.Record_SRV(1, 2, 3, 'example.org', 4)), "<SRV priority=1 weight=2 target=example.org port=3 ttl=4>")
def _lookup(self, name, cls, qtype, timeout): """ do the fake lookup. """ hostname = 'fs-%s.server.com' rr = dns.RRHeader(name=hostname % '0', type=qtype, cls=cls, ttl=60, payload=dns.Record_SRV(target=hostname % '0', port=443)) rr1 = dns.RRHeader(name=hostname % '1', type=qtype, cls=cls, ttl=60, payload=dns.Record_SRV(target=hostname % '1', port=443)) results = [rr, rr1] authority = [] addtional = [] return defer.succeed((results, authority, addtional))
def testSomeRecordsWithTTLs(self): result_soa = copy.copy(my_soa) result_soa.ttl = my_soa.expire return self.namesTest( self.resolver.lookupAllRecords('my-domain.com'), [result_soa, dns.Record_A('1.2.3.4', ttl='1S'), dns.Record_NS('ns1.domain', ttl='2M'), dns.Record_NS('ns2.domain', ttl='3H'), dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', ttl='4D')] )
def _ebServiceUnknown(self, failure): """ Connect to the default port when the service name is unknown. If no SRV records were found, the service name will be passed as the port. If resolving the name fails with L{error.ServiceNameUnknownError}, a final attempt is done using the default port. """ failure.trap(error.ServiceNameUnknownError) self.servers = [dns.Record_SRV(0, 0, self._defaultPort, self.domain)] self.orderedServers = [] self.connect()
def test_SRVPresent(self): """ Test connectTCP gets called with the address from the SRV record. """ payload = dns.Record_SRV(port=6269, target="host.example.org", ttl=60) client.theResolver.results = [ dns.RRHeader( name="example.org", type=dns.SRV, cls=dns.IN, ttl=60, payload=payload ) ] self.connector.connect() self.assertIsNone(self.factory.reason) self.assertEqual(self.reactor.tcpClients.pop()[:2], ("host.example.org", 6269))
def test_someRecordsWithTTLs(self): result_soa = copy.copy(my_soa) result_soa.ttl = my_soa.expire return self.namesTest( self.resolver.lookupAllRecords("my-domain.com"), [ result_soa, dns.Record_A("1.2.3.4", ttl="1S"), dns.Record_NS("ns1.domain", ttl="2M"), dns.Record_NS("ns2.domain", ttl="3H"), dns.Record_SRV( 257, 16383, 43690, "some.other.place.fool", ttl="4D"), ], )
def test_SRVNoService(self): """ Test that connecting fails when no service is present. """ payload = dns.Record_SRV(port=5269, target=b".", ttl=60) client.theResolver.results = [ dns.RRHeader( name="example.org", type=dns.SRV, cls=dns.IN, ttl=60, payload=payload ) ] self.connector.connect() self.assertIsNotNone(self.factory.reason) self.factory.reason.trap(DNSLookupError) self.assertEqual(self.reactor.tcpClients, [])
def test_SRVPresent(self): """ Test connectTCP gets called with the address from the SRV record. """ payload = dns.Record_SRV(port=6269, target='host.example.org', ttl=60) client.theResolver.results = [ dns.RRHeader(name='example.org', type=dns.SRV, cls=dns.IN, ttl=60, payload=payload) ] self.connector.connect() self.assertIdentical(None, self.factory.reason) self.assertEqual('host.example.org', self.reactor.host) self.assertEqual(6269, self.reactor.port)
def test_resolve(self): dns_client_mock = Mock() service_name = b"test_service.example.com" host_name = b"example.com" answer_srv = dns.RRHeader(type=dns.SRV, payload=dns.Record_SRV(target=host_name)) result_deferred = Deferred() dns_client_mock.lookupService.return_value = result_deferred cache = {} resolver = SrvResolver(dns_client=dns_client_mock, cache=cache) @defer.inlineCallbacks def do_lookup(): with LoggingContext("one") as ctx: resolve_d = resolver.resolve_service(service_name) self.assertNoResult(resolve_d) # should have reset to the sentinel context self.assertIs(LoggingContext.current_context(), LoggingContext.sentinel) result = yield resolve_d # should have restored our context self.assertIs(LoggingContext.current_context(), ctx) defer.returnValue(result) test_d = do_lookup() self.assertNoResult(test_d) dns_client_mock.lookupService.assert_called_once_with(service_name) result_deferred.callback(([answer_srv], None, None)) servers = self.successResultOf(test_d) self.assertEquals(len(servers), 1) self.assertEquals(servers, cache[service_name]) self.assertEquals(servers[0].host, host_name)
def srv(localname): info = self.zeroconf.get_service_info(localname, localname, timeout * 1000) if info is None: return [], [], [] answers = [ dns.RRHeader(name=localname[:-6] + domain, ttl=ttl, type=dns.SRV, payload=dns.Record_SRV(info.priority, info.weight, info.port, info.server[:-6] + domain)) ] additional = [ dns.RRHeader(name=info.server[:-6] + domain, ttl=ttl, type=dns.A, payload=dns.Record_A( socket.inet_ntop(socket.AF_INET, addr))) for addr in info.addresses ] return answers, [], additional
def test_srv(self): """ Two L{dns.Record_SRV} instances compare equal if and only if they have the same priority, weight, port, target, and ttl. """ # Vary the priority self._equalityTest(dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(100, 20, 30, 'example.com', 40)) # Vary the weight self._equalityTest(dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 200, 30, 'example.com', 40)) # Vary the port self._equalityTest(dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 300, 'example.com', 40)) # Vary the target self._equalityTest(dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.org', 40)) # Vary the ttl self._equalityTest(dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 40), dns.Record_SRV(10, 20, 30, 'example.com', 400))
def start_local_dns_server(args): all_records = {} def _push_record(name, r): print('pushing record: |%s|' % name) if all_records.get(name) is not None: all_records[name].append(r) return all_records[name] = [r] def _maybe_split_up_txt_data(name, txt_data, r_ttl): start = 0 txt_data_list = [] while len(txt_data[start:]) > 0: next_read = len(txt_data[start:]) if next_read > 255: next_read = 255 txt_data_list.append(txt_data[start:start + next_read]) start += next_read _push_record(name, dns.Record_TXT(*txt_data_list, ttl=r_ttl)) with open(args.records_config_path) as config: test_records_config = yaml.load(config) common_zone_name = test_records_config['resolver_tests_common_zone_name'] for group in test_records_config['resolver_component_tests']: for name in group['records'].keys(): for record in group['records'][name]: r_type = record['type'] r_data = record['data'] r_ttl = int(record['TTL']) record_full_name = '%s.%s' % (name, common_zone_name) assert record_full_name[-1] == '.' record_full_name = record_full_name[:-1] if r_type == 'A': _push_record(record_full_name, dns.Record_A(r_data, ttl=r_ttl)) if r_type == 'AAAA': _push_record(record_full_name, dns.Record_AAAA(r_data, ttl=r_ttl)) if r_type == 'SRV': p, w, port, target = r_data.split(' ') p = int(p) w = int(w) port = int(port) target_full_name = '%s.%s' % (target, common_zone_name) r_data = '%s %s %s %s' % (p, w, port, target_full_name) _push_record( record_full_name, dns.Record_SRV(p, w, port, target_full_name, ttl=r_ttl)) if r_type == 'TXT': _maybe_split_up_txt_data(record_full_name, r_data, r_ttl) # Server health check record _push_record(_SERVER_HEALTH_CHECK_RECORD_NAME, dns.Record_A(_SERVER_HEALTH_CHECK_RECORD_DATA, ttl=0)) soa_record = dns.Record_SOA(mname=common_zone_name) test_domain_com = NoFileAuthority( soa=(common_zone_name, soa_record), records=all_records, ) server = twisted.names.server.DNSServerFactory( authorities=[test_domain_com], verbose=2) server.noisy = 2 twisted.internet.reactor.listenTCP(args.port, server) dns_proto = twisted.names.dns.DNSDatagramProtocol(server) dns_proto.noisy = 2 twisted.internet.reactor.listenUDP(args.port, dns_proto) print('starting local dns server on 127.0.0.1:%s' % args.port) print('starting twisted.internet.reactor') twisted.internet.reactor.suggestThreadPoolSize(1) twisted.internet.reactor.run()
dns.Record_A6(12, '0:0069::0', 'some.network.tld'), dns.Record_A6(8, '0:5634:1294:AFCB:56AC:48EF:34C3:01FF', 'tra.la.la.net'), dns.Record_TXT('Some more text, haha! Yes. \0 Still here?'), dns.Record_MR('mail.redirect.or.whatever'), dns.Record_MINFO(rmailbx='r mail box', emailbx='e mail box'), dns.Record_AFSDB(subtype=1, hostname='afsdb.test-domain.com'), dns.Record_RP(mbox='whatever.i.dunno', txt='some.more.text'), dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP, '\x12\x01\x16\xfe\xc1\x00\x01'), dns.Record_NAPTR(100, 10, "u", "sip+E2U", "!^.*$!sip:[email protected]!"), dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF') ], 'http.tcp.test-domain.com': [dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool')], 'host.test-domain.com': [ dns.Record_A('123.242.1.5'), dns.Record_A('0.255.0.255'), ], 'host-two.test-domain.com': [ # # Python bug # dns.Record_A('255.255.255.255'), # dns.Record_A('255.255.255.254'), dns.Record_A('0.0.0.0') ], 'cname.test-domain.com': [dns.Record_CNAME('test-domain.com')], 'anothertest-domain.com': [dns.Record_A('1.2.3.4')], })
def __build_answer(self, query, db_zone, db_record, is_conditional_response=False): record = None # Calculate the query type (in case it's a request for A but a CNAME is returned). query_type = REV_TYPES[db_record.type] if query_type == dns.A: record = dns.Record_A(address=db_record.property( 'address', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.AAAA: record = dns.Record_AAAA(address=db_record.property( 'address', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.AFSDB: record = dns.Record_AFSDB(subtype=int( db_record.property('subtype', conditional=is_conditional_response)), hostname=db_record.property( 'hostname', conditional=is_conditional_response)) elif query_type == dns.CNAME: record = dns.Record_CNAME(name=db_record.property( 'name', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.DNAME: record = dns.Record_DNAME(name=db_record.property( 'name', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.HINFO: record = dns.Record_HINFO( cpu=db_record.property( 'cpu', conditional=is_conditional_response).encode(), os=db_record.property( 'os', conditional=is_conditional_response).encode()) elif query_type == dns.MX: record = dns.Record_MX(preference=int( db_record.property('preference', conditional=is_conditional_response)), name=db_record.property( 'name', conditional=is_conditional_response)) elif query_type == dns.NAPTR: record = dns.Record_NAPTR( order=int( db_record.property('order', conditional=is_conditional_response)), preference=int( db_record.property('preference', conditional=is_conditional_response)), flags=db_record.property( 'flags', conditional=is_conditional_response).encode(), service=db_record.property( 'service', conditional=is_conditional_response).encode(), regexp=db_record.property( 'regexp', conditional=is_conditional_response).encode(), replacement=db_record.property( 'replacement', conditional=is_conditional_response)) elif query_type == dns.NS: record = dns.Record_NS(name=db_record.property( 'name', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.PTR: record = dns.Record_PTR(name=db_record.property( 'name', conditional=is_conditional_response), ttl=db_record.ttl) elif query_type == dns.RP: record = dns.Record_RP( mbox=db_record.property('mbox', conditional=is_conditional_response), txt=db_record.property('txt', conditional=is_conditional_response)) elif query_type == dns.SOA: record = dns.Record_SOA( mname=db_record.property('mname', conditional=is_conditional_response), rname=db_record.property('rname', conditional=is_conditional_response), serial=int( db_record.property('serial', conditional=is_conditional_response)), refresh=int( db_record.property('refresh', conditional=is_conditional_response)), retry=int( db_record.property('retry', conditional=is_conditional_response)), expire=int( db_record.property('expire', conditional=is_conditional_response)), minimum=int( db_record.property('minimum', conditional=is_conditional_response))) elif query_type == dns.SPF: record = dns.Record_SPF( db_record.property( 'data', conditional=is_conditional_response).encode()) elif query_type == dns.SRV: record = dns.Record_SRV( priority=int( db_record.property('priority', conditional=is_conditional_response)), port=int( db_record.property('port', conditional=is_conditional_response)), weight=int( db_record.property('weight', conditional=is_conditional_response)), target=db_record.property('target', conditional=is_conditional_response)) elif query_type == dns.SSHFP: record = dns.Record_SSHFP( algorithm=int( db_record.property('algorithm', conditional=is_conditional_response)), fingerprintType=int( db_record.property('fingerprint_type', conditional=is_conditional_response)), fingerprint=db_record.property( 'fingerprint', conditional=is_conditional_response).encode()) elif query_type == dns.TSIG: record = dns.Record_TSIG( algorithm=db_record.property( 'algorithm', conditional=is_conditional_response).encode(), timeSigned=int( db_record.property('timesigned', conditional=is_conditional_response)), fudge=int( db_record.property('fudge', conditional=is_conditional_response)), originalID=int( db_record.property('original_id', conditional=is_conditional_response)), MAC=db_record.property( 'mac', conditional=is_conditional_response).encode(), otherData=db_record.property( 'other_data', conditional=is_conditional_response).encode()) elif query_type == dns.TXT: record = dns.Record_TXT( db_record.property( 'data', conditional=is_conditional_response).encode()) else: pass if not record: return None answer = dns.RRHeader(name=query.name.name, type=query_type, cls=query.cls, ttl=db_record.ttl, payload=record) return answer
dns.Record_A6(12, b"0:0069::0", b"some.network.tld"), dns.Record_A6(8, b"0:5634:1294:AFCB:56AC:48EF:34C3:01FF", b"tra.la.la.net"), dns.Record_TXT(b"Some more text, haha! Yes. \0 Still here?"), dns.Record_MR(b"mail.redirect.or.whatever"), dns.Record_MINFO(rmailbx=b"r mail box", emailbx=b"e mail box"), dns.Record_AFSDB(subtype=1, hostname=b"afsdb.test-domain.com"), dns.Record_RP(mbox=b"whatever.i.dunno", txt=b"some.more.text"), dns.Record_WKS(b"12.54.78.12", socket.IPPROTO_TCP, b"\x12\x01\x16\xfe\xc1\x00\x01"), dns.Record_NAPTR(100, 10, b"u", b"sip+E2U", b"!^.*$!sip:[email protected]!"), dns.Record_AAAA(b"AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF"), ], b"http.tcp.test-domain.com": [dns.Record_SRV(257, 16383, 43690, b"some.other.place.fool")], b"host.test-domain.com": [ dns.Record_A(b"123.242.1.5"), dns.Record_A(b"0.255.0.255"), ], b"host-two.test-domain.com": [ # # Python bug # dns.Record_A('255.255.255.255'), # dns.Record_A(b"255.255.255.254"), dns.Record_A(b"0.0.0.0"), ], b"cname.test-domain.com": [dns.Record_CNAME(b"test-domain.com")], b"anothertest-domain.com": [dns.Record_A(b"1.2.3.4")], },