def resolve(exit_desc, domain, whitelist): """ Resolve a `domain' and compare it to the `whitelist'. If the domain is not part of the whitelist, an error is logged. """ exit = exiturl(exit_desc.fingerprint) sock = torsocks.torsocket() sock.settimeout(10) # Resolve the domain using Tor's SOCKS extension. try: ipv4 = sock.resolve(domain) except error.SOCKSv5Error as err: logger.debug("Exit relay %s could not resolve IPv4 address for " "\"%s\" because: %s" % (exit, domain, err)) return except socket.timeout as err: logger.debug("Socket over exit relay %s timed out: %s" % (exit, err)) return if ipv4 not in whitelist: logger.critical("Exit relay %s returned unexpected IPv4 address %s " "for domain %s" % (exit, ipv4, domain)) else: logger.debug("IPv4 address of domain %s as expected for %s." % (domain, exit))
def resolve(exit_desc, domain, whitelist): """ Resolve a `domain' and compare it to the `whitelist'. If the domain is not part of the whitelist, an error is logged. """ exit = exiturl(exit_desc.fingerprint) sock = torsocks.torsocket() sock.settimeout(10) # Resolve the domain using Tor's SOCKS extension. try: ipv4 = sock.resolve(domain) except error.SOCKSv5Error as err: log.debug("Exit relay %s could not resolve IPv4 address for " "\"%s\" because: %s" % (exit, domain, err)) return except socket.timeout as err: log.debug("Socket over exit relay %s timed out: %s" % (exit, err)) return except EOFError as err: log.debug("EOF error: %s" % err) return if ipv4 not in whitelist: log.critical("Exit relay %s returned unexpected IPv4 address %s " "for domain %s" % (exit, ipv4, domain)) else: log.debug("IPv4 address of domain %s as expected for %s." % (domain, exit))
def test_dnssec(exit_fpr): """ Test if broken DNSSEC domain can be resolved. """ exit_url = util.exiturl(exit_fpr) sock = torsocks.torsocket() sock.settimeout(10) # Resolve domain using Tor's SOCKS extension. try: ipv4 = sock.resolve(BROKEN_DOMAIN) except error.SOCKSv5Error as err: logger.debug("%s did not resolve broken domain because: %s. Good." % (exit_url, err)) return except socket.timeout as err: logger.debug("Socket over exit relay %s timed out: %s" % (exit_url, err)) return except Exception as err: logger.debug("Could not resolve domain because: %s" % err) return logger.critical("%s resolved domain to %s" % (exit_url, ipv4))
def test_dnssec(exit_fpr): """ Test if broken DNSSEC domain can be resolved. """ exit_url = util.exiturl(exit_fpr) sock = torsocks.torsocket() sock.settimeout(10) # Resolve domain using Tor's SOCKS extension. try: ipv4 = sock.resolve(BROKEN_DOMAIN) except error.SOCKSv5Error as err: log.debug("%s did not resolve broken domain because: %s. Good." % (exit_url, err)) return except socket.timeout as err: log.debug("Socket over exit relay %s timed out: %s" % (exit_url, err)) return except Exception as err: log.debug("Could not resolve domain because: %s" % err) return log.critical("%s resolved domain to %s" % (exit_url, ipv4))
def test_authentication(self): """Test whether authentication is correctly handled. Test first whether global variables are correctly set up and then whether authentication handles correctly failed connections. """ sock = torsocks.torsocket() # test proxy and socks_port self.assertRaises(AssertionError, sock._authenticate) torsocks.set_default_proxy("127.0.0.2", 9050) with self.assertRaises(SystemExit) as auth: sock._authenticate() self.assertEqual(auth.exception.code, 1)
def resolve(exit_desc): """ Resolve exit relay-specific domain. """ exit_url = util.exiturl(exit_desc.fingerprint) # Prepend the exit relay's fingerprint so we know which relay issued the # DNS request. fingerprint = exit_desc.fingerprint.encode("ascii", "ignore") domain = "%s.%s.%s" % (fingerprint, time.strftime("%Y-%m-%d-%H"), TARGET_DOMAIN) log.debug("Resolving %s over %s." % (domain, exit_url)) sock = torsocks.torsocket() sock.settimeout(10) # Resolve the domain using Tor's SOCKS extension. log.debug("Resolving %s over %s." % (domain, exit_url)) try: ipv4 = sock.resolve(domain) except error.SOCKSv5Error as err: # This is expected because all domains resolve to 127.0.0.1. log.warning("SOCKSv5 error while resolving domain: %s" % err) ipv4 = "0.0.0.0" pass except socket.timeout as err: log.debug("Socket over exit relay %s timed out: %s" % (exit_url, err)) return log.info("Successfully resolved domain over %s to %s." % (exit_url, ipv4)) # Log a CSV including timestamp, exit fingerprint, exit IP address, and the # domain we resolved. timestamp = time.strftime("%Y-%m-%d_%H:%M:%S_%z") content = "%s, %s, %s, %s\n" % (timestamp, fingerprint, exit_desc.address, ipv4) util.dump_to_file(content, fingerprint)
def resolve_domain(exit_desc, url, tries=0): sock = torsocks.torsocket() sock.settimeout( 10) # 10 second timeout before socket closes the TCP connection try: t = time.time() ipv4 = sock.resolve(url) # Try to resolve the domain except Exception as err: log.debug("Error: " + str(err) + " " + str(url) + " on exit " + str(exit_desc.fingerprint)) if (tries < int(get_tries())): #time.sleep(0.01 * tries) return resolve_domain(exit_desc, url, tries=tries + 1) else: log.warn( str(tries) + " tries, abandoning " + str(url) + " on exit " + str(exit_desc.fingerprint)) return url, -1, tries else: t = time.time() - t log.debug(str(url) + " resolved to " + str(ipv4)) return url, t, tries
def test_malformed_domain(self): """Test whether the torsocks resolver identifies malformed domains.""" sock = torsocks.torsocket() domain = "a" * 256 self.assertRaises(SOCKSv5Error, sock.resolve, domain)
def test_ssh(exit_desc): """ is you or is you not MITMing my ssh? """ exit_fp = exit_desc.fingerprint exit_url = exiturl(exit_fp) log.debug('testing exit %s' % (exit_fp)) fail_count = 0 for host, port in destinations: # construct the tor socket sock = torsocket() sock.settimeout(10) # resolve the ip over tor, like it normally would for a client. try: ipv4 = sock.resolve(host) log.debug("destination %s resolves to: %s" % (host, ipv4)) except SOCKSv5Error as err: log.debug("%s did not resolve broken domain because: %s." % (exit_url, err)) fail_count += 1 continue except socket.timeout as err: log.debug("Socket over exit relay %s timed out: %s" % (exit_url, err)) fail_count += 1 continue except Exception as err: log.debug("Could not resolve domain because: %s" % err) fail_count += 1 continue finally: sock.close() # connect to the actual target sock = torsocket() sock.settimeout(10) address = (ipv4, port) sock.connect(address) # get the over-tor key information try: client = paramiko.transport.Transport(sock) except EOFError as err: log.info('unknown ssh connection error to %s:%s (%s) over exit relay %s: %s' % (host, port, ipv4, exit_fp, err)) fail_count += 1 continue except paramiko.SSHException as err: log.info('ssh exception conneting to %s:%s (%s) over exit relay %s: %s' % (host, port, ipv4, exit_fp, err)) fail_count += 1 continue try: client.start_client() except EOFError as err: log.info('unknown ssh connection error to %s:%s (%s) over exit relay %s: %s' % (host, port, ipv4, exit_fp, err)) fail_count += 1 continue except paramiko.SSHException as err: log.info('ssh connection error to %s:%s (%s) over exit relay %s: %s' % (host, port, ipv4, exit_fp, err)) fail_count += 1 continue tor_version = client.remote_version key = client.get_remote_server_key() client.close() sock.close() tor_key_name = key.get_name() tor_key_base64 = key.get_base64() log.debug('ssh key (tor) name for %s:%s (%s): %s' % (host, port, ipv4, tor_key_name)) log.debug('ssh key (tor) for %s:%s (%s): %s' % (host, port, ipv4, tor_key_base64)) log.debug('ssh version (tor) for %s:%s (%s): %s' % (host, port, ipv4, tor_version)) # do the matching version = details[host]['version'] key_name = details[host]['key_name'] key_base64 = details[host]['key_base64'] if not key_name == tor_key_name: log.critical('tor ssh key name mismatch for %s:%s (%s) over exit relay %s clear wire value: %s, over tor value: %s' % (host, port, ipv4, exit_fp, key_name, tor_key_name)) else: log.debug('tor ssh key name match for %s:%s (%s) over exit relay %s' % (host, port, ipv4, exit_fp)) if not key_base64 == tor_key_base64: log.critical('tor ssh key mismatch for %s:%s (%s) over exit relay %s' % (host, port, ipv4, exit_fp)) log.critical('clear wire key: %s' % (key_base64)) log.critical('clear wire version: %s' % (version)) log.critical('over tor key: %s' % (tor_key_base64)) log.critical('over tor version: %s' % (tor_version)) log.info('atlas link: https://atlas.torproject.org/#details/%s' % (exit_fp)) else: log.debug('tor ssh key match for %s:%s (%s) over exit relay %s' % (host, port, ipv4, exit_fp)) # if EVERY host is unable to be connected to, this could indicate a broken/misconfigured exit if fail_count == len(details): log.warning('exit %s appears to be having issues connecting over ssh. misconfiguration?' % (exit_fp)) log.info('atlas link: https://atlas.torproject.org/#details/%s' % (exit_fp)) if fail_count > 0: log.warning('%s of %s ssh connections have failed over exit %s' % (fail_count, len(details), exit_fp))