def test_lookup(self): """ We perform an A lookup on the DNS test servers for the domains to be tested and an A lookup on the known good DNS server. We then compare the results from test_resolvers and that from control_resolver and see if the match up. If they match up then no censorship is happening (tampering: false). If they do not we do a reverse lookup (PTR) on the test_resolvers and the control resolver for every IP address we got back and check to see if anyone of them matches the control ones. If they do then we take not of the fact that censorship is probably not happening (tampering: reverse-match). If they do not match then censorship is probably going on (tampering: true). """ log.msg("Doing the test lookups on %s" % self.input) list_of_ds = [] hostname = self.input dns_query = [dns.Query(hostname, dns.IN, dns.A)] dns_server = [(self.localOptions['backend'], self.localOptions['backendport'])] resolver = Resolver(servers=dns_server) control_d = resolver.queryUDP(dns_query, timeout=self.lookupTimeout) control_d.addCallback(self.process_a_answers, 'control') control_d.addErrback(self.a_lookup_error, 'control') for test_resolver in self.test_resolvers: log.msg("Going for %s" % test_resolver) dns_server = [(test_resolver, 53)] resolver = Resolver(servers=dns_server) d = resolver.queryUDP(dns_query, timeout=self.lookupTimeout) d.addCallback(self.process_a_answers, test_resolver) d.addErrback(self.a_lookup_error, test_resolver) # This is required to cancel the delayed calls of the # twisted.names.client resolver list_of_ds.append(d) list_of_ds.append(control_d) dl = defer.DeferredList(list_of_ds) dl.addCallback(self.do_reverse_lookups) dl.addBoth(self.compare_results) return dl
def performALookup(self, hostname, dns_server): """ Performs an A lookup and returns an array containg all the dotted quad IP addresses in the response. :hostname: is the hostname to perform the A lookup on :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ query = [dns.Query(hostname, dns.A, dns.IN)] def gotResponse(message): addrs = [] answers = [] for answer in message.answers: if answer.type is 1: addr = answer.payload.dottedQuad() addrs.append(addr) answers.append(representAnswer(answer)) DNSTest.addToReport(self, query, resolver=dns_server, query_type='A', answers=answers, addrs=addrs) return addrs def gotError(failure): failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type='A', failure=failure) return failure resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def test_a_lookup_ooni_query(self): def done_query(message, *arg): answer = message.answers[0] self.assertEqual(answer.type, 1) dns_query = [dns.Query('ooni.nu', type=dns.A)] resolver = Resolver(servers=[('8.8.8.8', 53)]) d = resolver.queryUDP(dns_query) d.addCallback(done_query) return d
def dnsLookup(self, hostname, dns_type, dns_server = None): """ Performs a DNS lookup and returns the response. :hostname: is the hostname to perform the DNS lookup on :dns_type: type of lookup 'NS'/'A'/'SOA' :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ types={'NS':dns.NS,'A':dns.A,'SOA':dns.SOA,'PTR':dns.PTR} dnsType=types[dns_type] query = [dns.Query(hostname, dnsType, dns.IN)] def gotResponse(message): log.debug(dns_type+" Lookup successful") log.debug(str(message)) addrs = [] answers = [] if dns_server: msg = message.answers else: msg = message[0] for answer in msg: if answer.type is dnsType: if dnsType is dns.SOA: addr = (answer.name.name,answer.payload.serial) elif dnsType in [dns.NS,dns.PTR]: addr = answer.payload.name.name elif dnsType is dns.A: addr = answer.payload.dottedQuad() else: addr = None addrs.append(addr) answers.append(representAnswer(answer)) DNSTest.addToReport(self, query, resolver=dns_server, query_type=dns_type, answers=answers, addrs=addrs) return addrs def gotError(failure): failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type=dns_type, failure=failure) return failure if dns_server: resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) else: lookupFunction={'NS':client.lookupNameservers, 'SOA':client.lookupAuthority, 'A':client.lookupAddress, 'PTR':client.lookupPointer} d = lookupFunction[dns_type](hostname) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performALookup(self, hostname, dns_server): """ Performs an A lookup and returns an array containg all the dotted quad IP addresses in the response. :hostname: is the hostname to perform the A lookup on :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ query = [dns.Query(hostname, dns.IN, dns.A)] def gotResponse(message): addrs = [] answers = [] for answer in message.answers: if answer.type is 1: addr = answer.payload.dottedQuad() addrs.append(addr) # We store the resource record and the answer payload in a # tuple r = (repr(answer), repr(answer.payload)) answers.append(r) result = {} result['resolver'] = dns_server result['query_type'] = 'A' result['query'] = repr(query) result['answers'] = answers result['addrs'] = addrs self.report['queries'].append(result) return addrs def gotError(failure): log.exception(failure) result = {} result['resolver'] = dns_server result['query_type'] = 'A' result['query'] = repr(query) result['error'] = str(failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performPTRLookup(self, address, dns_server): """ Does a reverse DNS lookup on the input ip address :address: the IP Address as a dotted quad to do a reverse lookup on. :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ ptr = '.'.join(address.split('.')[::-1]) + '.in-addr.arpa' query = [dns.Query(ptr, dns.PTR, dns.IN)] def gotResponse(message): log.debug("Lookup successful") log.debug(message) answers = [] name = '' for answer in message.answers: if answer.type is 12: name = str(answer.payload.name) answers.append(representAnswer(answer)) DNSTest.addToReport(self, query, resolver=dns_server, query_type='PTR', answers=answers, name=name) return name def gotError(failure): log.err("Failed to perform lookup") log.exception(failure) failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type='PTR', failure=failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performALookup(self, hostname, dns_server): """ Performs an A lookup and returns an array containg all the dotted quad IP addresses in the response. :hostname: is the hostname to perform the A lookup on :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ query = [dns.Query(hostname, dns.IN, dns.A)] def gotResponse(message): addrs = [] answers = [] for answer in message.answers: if answer.type is 1: addr = answer.payload.dottedQuad() addrs.append(addr) # We store the resource record and the answer payload in a # tuple r = (repr(answer), repr(answer.payload)) answers.append(r) result = {} result['resolver'] = dns_server result['query_type'] = 'A' result['query'] = repr(query) result['answers'] = answers result['addrs'] = addrs self.report['queries'].append(result) return addrs def gotError(failure): log.exception(failure) result = {} result['resolver'] = dns_server result['query_type'] = 'A' result['query'] = repr(query) result['error'] = str(failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performALookup(self, hostname, dns_server): """ Performs an A lookup and returns an array containg all the dotted quad IP addresses in the response. :hostname: is the hostname to perform the A lookup on :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ query = [dns.Query(hostname, dns.A, dns.IN)] def gotResponse(message): addrs = [] answers = [] for answer in message.answers: if answer.type is 1: addr = answer.payload.dottedQuad() addrs.append(addr) answers.append(representAnswer(answer)) DNSTest.addToReport(self, query, resolver=dns_server, query_type='A', answers=answers, addrs=addrs) return addrs def gotError(failure): failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type='A', failure=failure) return failure resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performPTRLookup(self, address, dns_server): """ Does a reverse DNS lookup on the input ip address :address: the IP Address as a dotted quad to do a reverse lookup on. :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ ptr = '.'.join(address.split('.')[::-1]) + '.in-addr.arpa' query = [dns.Query(ptr, dns.IN, dns.PTR)] def gotResponse(message): answers = [] name = None for answer in message.answers: if answer.type is 12: name = answer.payload.name result = {} result['resolver'] = dns_server result['query_type'] = 'PTR' result['query'] = repr(query) result['answers'] = answers result['name'] = name self.report['queries'].append(result) return name def gotError(failure): log.exception(failure) result = {} result['resolver'] = dns_server result['query_type'] = 'PTR' result['query'] = repr(query) result['error'] = str(failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performPTRLookup(self, address, dns_server): """ Does a reverse DNS lookup on the input ip address :address: the IP Address as a dotted quad to do a reverse lookup on. :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ ptr = '.'.join(address.split('.')[::-1]) + '.in-addr.arpa' query = [dns.Query(ptr, dns.IN, dns.PTR)] def gotResponse(message): answers = [] name = None for answer in message.answers: if answer.type is 12: name = answer.payload.name result = {} result['resolver'] = dns_server result['query_type'] = 'PTR' result['query'] = repr(query) result['answers'] = answers result['name'] = name self.report['queries'].append(result) return name def gotError(failure): log.exception(failure) result = {} result['resolver'] = dns_server result['query_type'] = 'PTR' result['query'] = repr(query) result['error'] = str(failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def performPTRLookup(self, address, dns_server): """ Does a reverse DNS lookup on the input ip address :address: the IP Address as a dotted quad to do a reverse lookup on. :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ ptr = '.'.join(address.split('.')[::-1]) + '.in-addr.arpa' query = [dns.Query(ptr, dns.PTR, dns.IN)] def gotResponse(message): log.debug("Lookup successful") log.debug(message) answers = [] name = '' for answer in message.answers: if answer.type is 12: name = str(answer.payload.name) answers.append(representAnswer(answer)) DNSTest.addToReport(self, query, resolver=dns_server, query_type = 'PTR', answers=answers, name=name) return name def gotError(failure): log.err("Failed to perform lookup") log.exception(failure) failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type = 'PTR', failure=failure) return None resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) d.addCallback(gotResponse) d.addErrback(gotError) return d
def dnsLookup(self, hostname, dns_type, dns_server = None): """ Performs a DNS lookup and returns the response. :hostname: is the hostname to perform the DNS lookup on :dns_type: type of lookup 'NS'/'A'/'SOA' :dns_server: is the dns_server that should be used for the lookup as a tuple of ip port (ex. ("127.0.0.1", 53)) """ types = { 'NS': dns.NS, 'A': dns.A, 'SOA': dns.SOA, 'PTR': dns.PTR } dnsType = types[dns_type] query = [dns.Query(hostname, dnsType, dns.IN)] def gotResponse(message): log.debug(dns_type + " Lookup successful") log.debug(str(message)) if dns_server: msg = message.answers else: msg = message[0] answers = [] addrs = [] for answer in msg: addr = None if answer.type is dns.SOA: addr = (answer.name.name,answer.payload.serial) elif answer.type in [dns.NS, dns.PTR, dns.CNAME]: addr = answer.payload.name.name elif answer.type is dns.A: addr = answer.payload.dottedQuad() else: log.debug("Unidentified answer %s" % answer) addrs.append(addr) answers.append(representAnswer(answer)) if dns_type == 'SOA': for authority in message.authority: answers.append(representAnswer(authority)) DNSTest.addToReport(self, query, resolver=dns_server, query_type=dns_type, answers=answers) return addrs def gotError(failure): failure.trap(gaierror, TimeoutError) DNSTest.addToReport(self, query, resolver=dns_server, query_type=dns_type, failure=failure) return failure if dns_server: resolver = Resolver(servers=[dns_server]) d = resolver.queryUDP(query, timeout=self.queryTimeout) else: lookupFunction = { 'NS': client.lookupNameservers, 'SOA': client.lookupAuthority, 'A': client.lookupAddress, 'PTR': client.lookupPointer } d = lookupFunction[dns_type](hostname) d.addCallback(gotResponse) d.addErrback(gotError) return d