135 lines
5.5 KiB
Python
Executable File
135 lines
5.5 KiB
Python
Executable File
#!/usr/local/bin/python3.sh
|
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
|
# https://stem.torproject.org/tutorials/over_the_river.html
|
|
|
|
__doc__ = """
|
|
Hidden services give you a way of providing a service without exposing your address. These services are only accessible through Tor or Tor2web, and useful for a surprising number of things...
|
|
|
|
Hosting an anonymized site. This is usually the first thing that comes to mind, and something we'll demonstrate in a sec.
|
|
Providing an endpoint Tor users can reach without exiting the Tor network. This eliminates the risk of an unreliable or malicious exit getting in the way. Great examples of this are Facebook (facebookcorewwwi.onion) and DuckDuckGo (3g2upl4pq6kufc4m.onion).
|
|
Personal services. For instance you can host your home SSH server as a hidden service to prevent eavesdroppers from knowing where you live while traveling abroad.
|
|
|
|
Tor2web provides a quick and easy way of seeing if your hidden service is working. To use it simply replace the .onion of your address with .tor2web.org...
|
|
|
|
This script tests if you can reach a hidden service, passed as an onion address
|
|
as an argument. If no argument is given, 3 common onion sites are tested:
|
|
Facebook, DuckDuckGo.
|
|
|
|
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import getpass
|
|
import logging
|
|
import binascii
|
|
|
|
import stem
|
|
from stem.control import Controller
|
|
from stem import Timeout
|
|
from stem.client.datatype import LinkByFingerprint
|
|
from stem.descriptor.hidden_service import HiddenServiceDescriptorV3
|
|
|
|
from stem_examples.tor_controller import get_controller
|
|
from stem.descriptor.hidden_service import HiddenServiceDescriptorV3
|
|
|
|
LOG = logging.getLogger()
|
|
TIMEOUT = 60
|
|
lKNOWN_ONIONS = [
|
|
'facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd', # facebook
|
|
'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad', # ddg
|
|
'zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad', # keys.openpgp.org
|
|
'libera75jm6of4wxpxt4aynol3xjmbtxgfyjpu34ss4d7r7q2v5zrpyd',
|
|
'oftcnet6xg6roj6d7id4y4cu6dchysacqj2ldgea73qzdagufflqxrid',
|
|
]
|
|
|
|
def bin_to_hex(raw_id:int, length: int|None = None) -> str:
|
|
if length is None: length = len(raw_id)
|
|
res = ''.join('{:02x}'.format(raw_id[i]) for i in range(length))
|
|
return res.upper()
|
|
|
|
def iMain(lArgs=None):
|
|
lRetval = lMain(lArgs)
|
|
if lRetval is None:
|
|
return -1
|
|
return 0
|
|
|
|
def lMain(lArgs=None, timeout=TIMEOUT) -> list:
|
|
lRetval = []
|
|
if not lArgs:
|
|
lArgs = lKNOWN_ONIONS
|
|
try:
|
|
password = os.environ.get('TOR_CONTROLLER_PASSWORD', '')
|
|
if os.path.exists('/run/tor/control'):
|
|
controller = get_controller(password=password, unix='/run/tor/control')
|
|
else:
|
|
controller = get_controller(password=password, port=9051)
|
|
|
|
for elt in lArgs:
|
|
LOG.info(f"onion: {elt}")
|
|
try:
|
|
desc = controller.get_hidden_service_descriptor(elt,
|
|
await_result=True,
|
|
timeout=timeout)
|
|
except Exception as e:
|
|
LOG.warn (f"{elt} EXCEPTION {e}")
|
|
continue
|
|
if desc.descriptor_id is None or desc.version is None:
|
|
# reparse as HSv3
|
|
inner_layer = HiddenServiceDescriptorV3.from_str(str(desc)).decrypt(elt)
|
|
if hasattr(inner_layer, 'introduction_points'):
|
|
LOG.info (f"{elt} reparsed desc.decrypt len={len(desc.introduction_points())}")
|
|
|
|
l = inner_layer.introduction_points
|
|
else:
|
|
LOG.warn (f"{elt} reparsed desc.decrypt={dir(inner_layer)}")
|
|
sys.exit(1)
|
|
|
|
#LOG.info(f"version: {desc.version}\n")
|
|
#LOG.info(f"lifetime: {desc.lifetime}\n")
|
|
else:
|
|
LOG.info(f"published: {desc.published}\n")
|
|
l = desc.introduction_points()
|
|
if not l:
|
|
LOG.warn(f"{elt} NO introduction points {l}\n")
|
|
continue
|
|
|
|
lp = []
|
|
for introduction_point in l:
|
|
for linkspecifier in introduction_point.link_specifiers:
|
|
# if isinstance(linkspecifier, LinkByFingerprint):
|
|
# LOG.log(40, f"Getting fingerprint for {linkspecifier}")
|
|
if hasattr(linkspecifier, 'fingerprint') and \
|
|
len(linkspecifier.value) == 20:
|
|
lp += [bin_to_hex(linkspecifier.value)]
|
|
elif hasattr(introduction_point, 'address'):
|
|
LOG.info('IP: %s:%s => %s' % (introduction_point.address,
|
|
introduction_point.port,
|
|
introduction_point.identifier))
|
|
else:
|
|
pass # LOG.warn(f"{elt} introduction_point type={type(linkspecifier)}")
|
|
LOG.info(f"{elt} {len(lp)} introduction points {lp}")
|
|
except Exception as e:
|
|
LOG.exception(f"Exception: {e}")
|
|
finally:
|
|
del controller
|
|
return lRetval
|
|
|
|
if __name__ == '__main__':
|
|
from stem_examples.stem_utils import vsetup_logging
|
|
if os.environ.get('DEBUG', ''):
|
|
log_level = 10
|
|
else:
|
|
log_level = 20
|
|
vsetup_logging(LOG, log_level)
|
|
try:
|
|
l = lMain(sys.argv[1:])
|
|
if l: print('IPs: ', l)
|
|
i = 0
|
|
except KeyboardInterrupt as e:
|
|
LOG.exception(f"Exception {e}")
|
|
i = 0
|
|
except Exception as e:
|
|
i = 1
|
|
sys.exit(i)
|