|
|
|
@ -48,7 +48,7 @@ exclusion: the ```--contact``` commandline arg is a comma sep list of conditions
|
|
|
|
|
More may be added later.
|
|
|
|
|
|
|
|
|
|
Because you don't want to exclude the introduction points to any onion
|
|
|
|
|
you want to connect to, ```--white_services``` should whitelist the
|
|
|
|
|
you want to connect to, ```--white_onions``` should whitelist the
|
|
|
|
|
introduction points to a comma sep list of onions, but is
|
|
|
|
|
currently broken in stem 1.8.0: see:
|
|
|
|
|
* https://github.com/torproject/stem/issues/96
|
|
|
|
@ -88,7 +88,7 @@ import time
|
|
|
|
|
import argparse
|
|
|
|
|
import string
|
|
|
|
|
from io import StringIO
|
|
|
|
|
import ipaddr
|
|
|
|
|
import ipaddress
|
|
|
|
|
# list(ipaddress._find_address_range(ipaddress.IPv4Network('172.16.0.0/12'))
|
|
|
|
|
|
|
|
|
|
from urllib3.util.ssl_match_hostname import CertificateError
|
|
|
|
@ -98,15 +98,23 @@ from stem.control import Controller
|
|
|
|
|
from stem.connection import IncorrectPassword
|
|
|
|
|
from stem.util.tor_tools import is_valid_fingerprint
|
|
|
|
|
try:
|
|
|
|
|
import yaml
|
|
|
|
|
from ruamel.yaml import YAML
|
|
|
|
|
yaml = YAML()
|
|
|
|
|
safe_load = yaml.load
|
|
|
|
|
except:
|
|
|
|
|
yaml = None
|
|
|
|
|
if yaml is None:
|
|
|
|
|
try:
|
|
|
|
|
import yaml
|
|
|
|
|
safe_load = yaml.safe_load
|
|
|
|
|
except:
|
|
|
|
|
yaml = None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from unbound import ub_ctx,RR_TYPE_TXT,RR_CLASS_IN
|
|
|
|
|
except:
|
|
|
|
|
ub_ctx = RR_TYPE_TXT = RR_CLASS_IN = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
global LOG
|
|
|
|
|
import logging
|
|
|
|
|
import warnings
|
|
|
|
@ -158,7 +166,7 @@ def lYamlBadNodes(sFile,
|
|
|
|
|
if not yaml: return l
|
|
|
|
|
if os.path.exists(sFile):
|
|
|
|
|
with open(sFile, 'rt') as oFd:
|
|
|
|
|
oBAD_NODES = yaml.safe_load(oFd)
|
|
|
|
|
oBAD_NODES = safe_load(oFd)
|
|
|
|
|
|
|
|
|
|
# BROKEN
|
|
|
|
|
# root = 'ExcludeNodes'
|
|
|
|
@ -170,7 +178,7 @@ def lYamlBadNodes(sFile,
|
|
|
|
|
|
|
|
|
|
root = 'ExcludeDomains'
|
|
|
|
|
if root not in oBAD_NODES[oBAD_ROOT] or not oBAD_NODES[oBAD_ROOT][root]:
|
|
|
|
|
lMAYBE_NODNS = yaml.safe_load(StringIO(yKNOWN_NODNS))
|
|
|
|
|
lMAYBE_NODNS = safe_load(StringIO(yKNOWN_NODNS))
|
|
|
|
|
else:
|
|
|
|
|
lMAYBE_NODNS = oBAD_NODES[oBAD_ROOT][root]
|
|
|
|
|
return l
|
|
|
|
@ -184,7 +192,7 @@ def lYamlGoodNodes(sFile='/etc/tor/torrc-goodnodes.yaml'):
|
|
|
|
|
if not yaml: return l
|
|
|
|
|
if os.path.exists(sFile):
|
|
|
|
|
with open(sFile, 'rt') as oFd:
|
|
|
|
|
o = yaml.safe_load(oFd)
|
|
|
|
|
o = safe_load(oFd)
|
|
|
|
|
oGOOD_NODES = o
|
|
|
|
|
if 'GuardNodes' in o[oGOOD_ROOT].keys():
|
|
|
|
|
l = o[oGOOD_ROOT]['GuardNodes']
|
|
|
|
@ -271,7 +279,7 @@ def aVerifyContact(a, fp, https_cafile, timeout=20, host='127.0.0.1', port=9050)
|
|
|
|
|
LOG.warn(f"{domain} is bad from {a['url']}")
|
|
|
|
|
LOG.debug(f"{fp} is bad from {a}")
|
|
|
|
|
return a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ip = zResolveDomain(domain)
|
|
|
|
|
if ip == '':
|
|
|
|
|
aFP_EMAIL[fp] = a['email']
|
|
|
|
@ -373,7 +381,7 @@ def aParseContact(contact, fp):
|
|
|
|
|
s += '\n'.join([f" {line}\"".replace(':',': \"', 1)
|
|
|
|
|
for line in l])
|
|
|
|
|
oFd = StringIO(s)
|
|
|
|
|
a = yaml.safe_load(oFd)
|
|
|
|
|
a = safe_load(oFd)
|
|
|
|
|
return a
|
|
|
|
|
|
|
|
|
|
def oMainArgparser(_=None):
|
|
|
|
@ -414,10 +422,10 @@ def oMainArgparser(_=None):
|
|
|
|
|
help='proxy download connect timeout')
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--good_nodes', type=str,
|
|
|
|
|
default=os.path.join(ETC_DIR, 'torrc-goodnodes.yaml'),
|
|
|
|
|
default=os.path.join(ETC_DIR, 'goodnodes.yaml'),
|
|
|
|
|
help="Yaml file of good info that should not be excluded")
|
|
|
|
|
parser.add_argument('--bad_nodes', type=str,
|
|
|
|
|
default=os.path.join(ETC_DIR, 'torrc-badnodes.yaml'),
|
|
|
|
|
default=os.path.join(ETC_DIR, 'badnodes.yaml'),
|
|
|
|
|
help="Yaml file of bad nodes that should also be excluded")
|
|
|
|
|
parser.add_argument('--contact', type=str, default='Empty,NoEmail',
|
|
|
|
|
help="comma sep list of conditions - Empty,NoEmail")
|
|
|
|
@ -437,13 +445,13 @@ def oMainArgparser(_=None):
|
|
|
|
|
parser.add_argument('--bad_sections', type=str,
|
|
|
|
|
default='MyBadExit',
|
|
|
|
|
help="sections of the badnodes.yaml to use, comma separated, '' BROKEN")
|
|
|
|
|
parser.add_argument('--white_services', type=str,
|
|
|
|
|
parser.add_argument('--white_onions', type=str,
|
|
|
|
|
default='',
|
|
|
|
|
help="comma sep. list of onions to whitelist their introduction points - BROKEN")
|
|
|
|
|
parser.add_argument('--torrc_output', type=str,
|
|
|
|
|
default=os.path.join(ETC_DIR, 'torrc.new'),
|
|
|
|
|
help="Write the torrc configuration to a file")
|
|
|
|
|
parser.add_argument('--proof_output', type=str, default=os.path.join(ETC_DIR, 'proof.yaml'),
|
|
|
|
|
parser.add_argument('--proof_output', type=str, default=os.path.join(ETC_DIR, 'goodcontacts.yaml'),
|
|
|
|
|
help="Write the proof data of the included nodes to a YAML file")
|
|
|
|
|
return parser
|
|
|
|
|
|
|
|
|
@ -493,8 +501,7 @@ def iMain(lArgs):
|
|
|
|
|
if sFile and os.path.exists(sFile):
|
|
|
|
|
try:
|
|
|
|
|
with open(sFile, 'rt') as oFd:
|
|
|
|
|
aTRUST_DB = yaml.safe_load(oFd)
|
|
|
|
|
assert type(aTRUST_DB) == dict
|
|
|
|
|
aTRUST_DB = safe_load(oFd)
|
|
|
|
|
LOG.info(f"{len(aTRUST_DB.keys())} trusted contacts from {sFile}")
|
|
|
|
|
# reverse lookup of fps to contacts
|
|
|
|
|
# but...
|
|
|
|
@ -541,10 +548,17 @@ def iMain(lArgs):
|
|
|
|
|
t = set()
|
|
|
|
|
if 'IntroductionPoints' in oGOOD_NODES[oGOOD_ROOT]['Relays'].keys():
|
|
|
|
|
t = set(oGOOD_NODES[oGOOD_ROOT]['Relays']['IntroductionPoints'])
|
|
|
|
|
# not working = maybe when stem is updated
|
|
|
|
|
w = set(oGOOD_NODES[oGOOD_ROOT]['Services'])
|
|
|
|
|
if oArgs.white_services:
|
|
|
|
|
w.update(oArgs.white_services.split(','))
|
|
|
|
|
w = set()
|
|
|
|
|
if 'Services' in oGOOD_NODES[oGOOD_ROOT].keys():
|
|
|
|
|
# 'Onions' can I use the IntroductionPoints for Services too?
|
|
|
|
|
# w = set(oGOOD_NODES[oGOOD_ROOT]['Services'])
|
|
|
|
|
pass
|
|
|
|
|
if 'Onions' in oGOOD_NODES[oGOOD_ROOT].keys():
|
|
|
|
|
# Provides the descriptor for a hidden service. The **address** is the
|
|
|
|
|
# '.onion' address of the hidden service
|
|
|
|
|
w = set(oGOOD_NODES[oGOOD_ROOT]['Onions'])
|
|
|
|
|
if oArgs.white_onions:
|
|
|
|
|
w.update(oArgs.white_onions.split(','))
|
|
|
|
|
if oArgs.points_timeout > 0:
|
|
|
|
|
LOG.info(f"{len(w)} services will be checked from IntroductionPoints")
|
|
|
|
|
t.update(lIntroductionPoints(controller, w, itimeout=oArgs.points_timeout))
|
|
|
|
|