Compare commits
	
		
			2 commits
		
	
	
		
			6cf32758c1
			...
			d6200d6302
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d6200d6302 | ||
|   | 36e0102dcd | 
					 5 changed files with 189 additions and 50 deletions
				
			
		
							
								
								
									
										76
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										76
									
								
								README.md
									
										
									
									
									
								
							|  | @ -71,3 +71,79 @@ You can expect it to take an hour or two the first time this is run: | ||||||
| >700 domains. | >700 domains. | ||||||
| 
 | 
 | ||||||
| For usage, do ```python3 exclude_badExits.py --help` | For usage, do ```python3 exclude_badExits.py --help` | ||||||
|  | 
 | ||||||
|  | ## Usage | ||||||
|  | ``` | ||||||
|  | usage: exclude_badExits.py [-h] [--https_cafile HTTPS_CAFILE] | ||||||
|  |                            [--proxy_host PROXY_HOST] [--proxy_port PROXY_PORT] | ||||||
|  |                            [--proxy_ctl PROXY_CTL] [--torrc TORRC] | ||||||
|  |                            [--timeout TIMEOUT] [--good_nodes GOOD_NODES] | ||||||
|  |                            [--bad_nodes BAD_NODES] [--contact CONTACT] | ||||||
|  |                            [--bad_contacts BAD_CONTACTS] | ||||||
|  |                            [--strict_nodes {0,1}] [--wait_boot WAIT_BOOT] | ||||||
|  |                            [--points_timeout POINTS_TIMEOUT] | ||||||
|  |                            [--log_level LOG_LEVEL] | ||||||
|  |                            [--bad_sections BAD_SECTIONS] | ||||||
|  |                            [--white_services WHITE_SERVICES] | ||||||
|  |                            [--torrc_output TORRC_OUTPUT] | ||||||
|  |                            [--proof_output PROOF_OUTPUT] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Optional arguments: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  |   -h, --help            show this help message and exit | ||||||
|  |   --https_cafile HTTPS_CAFILE | ||||||
|  |                         Certificate Authority file (in PEM) | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --proxy_host PROXY_HOST, --proxy-host PROXY_HOST | ||||||
|  |                         proxy host | ||||||
|  |   --proxy_port PROXY_PORT, --proxy-port PROXY_PORT | ||||||
|  |                         proxy control port | ||||||
|  |   --proxy_ctl PROXY_CTL, --proxy-ctl PROXY_CTL | ||||||
|  |                         control socket - or port | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --torrc TORRC         torrc to check for suggestions | ||||||
|  |   --timeout TIMEOUT     proxy download connect timeout | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --good_nodes GOOD_NODES | ||||||
|  |                         Yaml file of good info that should not be excluded | ||||||
|  |   --bad_nodes BAD_NODES | ||||||
|  |                         Yaml file of bad nodes that should also be excluded | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --contact CONTACT     comma sep list of conditions - Empty,NoEmail | ||||||
|  |   --bad_contacts BAD_CONTACTS | ||||||
|  |                         Yaml file of bad contacts that bad FPs are using | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --strict_nodes {0,1}  Set StrictNodes: 1 is less anonymous but more secure, | ||||||
|  |                         although some sites may be unreachable | ||||||
|  |   --wait_boot WAIT_BOOT | ||||||
|  |                         Seconds to wait for Tor to booststrap | ||||||
|  |   --points_timeout POINTS_TIMEOUT | ||||||
|  |                         Timeout for getting introduction points - must be long | ||||||
|  |                         >120sec. 0 means disabled looking for IPs | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --log_level LOG_LEVEL | ||||||
|  |                         10=debug 20=info 30=warn 40=error | ||||||
|  |   --bad_sections BAD_SECTIONS | ||||||
|  |                         sections of the badnodes.yaml to use, comma separated, | ||||||
|  |                         '' BROKEN | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --white_services WHITE_SERVICES | ||||||
|  |                         comma sep. list of onions to whitelist their | ||||||
|  |                         introduction points - BROKEN | ||||||
|  | ``` | ||||||
|  | ``` | ||||||
|  |   --torrc_output TORRC_OUTPUT | ||||||
|  |                         Write the torrc configuration to a file | ||||||
|  |   --proof_output PROOF_OUTPUT | ||||||
|  |                         Write the proof data of the included nodes to a YAML | ||||||
|  |                         file | ||||||
|  | ``` | ||||||
|  |  | ||||||
							
								
								
									
										41
									
								
								exclude_badExits.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								exclude_badExits.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | # -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*- | ||||||
|  | 
 | ||||||
|  | PROG=exclude_badExits.py | ||||||
|  | SOCKS_PORT=9050 | ||||||
|  | CAFILE=/etc/ssl/certs/ca-certificates.crt | ||||||
|  | 
 | ||||||
|  | # an example of running exclude_badExits with full debugging | ||||||
|  | # expected to take an hour or so | ||||||
|  | declare -a LARGS | ||||||
|  | LARGS=( | ||||||
|  |     --log_level 10 | ||||||
|  |     ) | ||||||
|  | # you may have a special python for installed packages | ||||||
|  | EXE=`which python3.bash` | ||||||
|  | LARGS+=( | ||||||
|  |     --strict_nodes 0 | ||||||
|  |     --points_timeout 120 | ||||||
|  |     --proxy-host 127.0.0.1 | ||||||
|  |     --proxy-port $SOCKS_PORT | ||||||
|  |     --https_cafile $CAFILE | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | if [ -f '/run/tor/control' ] ; then | ||||||
|  |     LARGS+=(--proxy-ctl '/run/tor/control' ) | ||||||
|  | else | ||||||
|  |     LARGS+=(--proxy-ctl 9051 ) | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | ddg=duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad | ||||||
|  | # for example, whitelist the introduction points to DuckDuckGo | ||||||
|  | LARGS+=( --white_onions $ddg ) | ||||||
|  | 
 | ||||||
|  | # you may need to be the tor user to read /run/tor/control | ||||||
|  | grep -q ^debian-tor /etc/group && TORU=debian-tor || { | ||||||
|  |     grep -q ^tor /etc/group && TORU=tor | ||||||
|  | } | ||||||
|  | sudo -u $TORU $EXE exclude_badExits.py "${LARGS[@]}" \ | ||||||
|  |    2>&1|tee exclude_badExits6.log | ||||||
|  | 
 | ||||||
|  | # The DEBUG statements contain the detail of why the relay was considered bad. | ||||||
|  | @ -48,7 +48,7 @@ exclusion: the ```--contact``` commandline arg is a comma sep list of conditions | ||||||
| More may be added later. | More may be added later. | ||||||
| 
 | 
 | ||||||
| Because you don't want to exclude the introduction points to any onion | 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 | introduction points to a  comma sep list of onions, but is | ||||||
| currently broken in stem 1.8.0: see: | currently broken in stem 1.8.0: see: | ||||||
| * https://github.com/torproject/stem/issues/96 | * https://github.com/torproject/stem/issues/96 | ||||||
|  | @ -65,7 +65,7 @@ not just exclude Exit. | ||||||
| If the Contact info is good we add the list of fingerprints to add | If the Contact info is good we add the list of fingerprints to add | ||||||
| to ExitNodes, a whitelist of relays to use as exits. | to ExitNodes, a whitelist of relays to use as exits. | ||||||
| 
 | 
 | ||||||
| ```--proof_output``` will write the contact info as a ciiss dictionary | ```--good_contacts``` will write the contact info as a ciiss dictionary | ||||||
| to a YAML file. If the proof is uri-rsa, the well-known file of fingerprints | to a YAML file. If the proof is uri-rsa, the well-known file of fingerprints | ||||||
| is downloaded and the fingerprints are added on a 'fps' field we create | is downloaded and the fingerprints are added on a 'fps' field we create | ||||||
| of that fingerprint's entry of the YAML dictionary. This file is read at the | of that fingerprint's entry of the YAML dictionary. This file is read at the | ||||||
|  | @ -88,7 +88,7 @@ import time | ||||||
| import argparse | import argparse | ||||||
| import string | import string | ||||||
| from io import StringIO | from io import StringIO | ||||||
| import ipaddr | import ipaddress | ||||||
| # list(ipaddress._find_address_range(ipaddress.IPv4Network('172.16.0.0/12')) | # list(ipaddress._find_address_range(ipaddress.IPv4Network('172.16.0.0/12')) | ||||||
| 
 | 
 | ||||||
| from urllib3.util.ssl_match_hostname import CertificateError | from urllib3.util.ssl_match_hostname import CertificateError | ||||||
|  | @ -98,15 +98,24 @@ from stem.control import Controller | ||||||
| from stem.connection import IncorrectPassword | from stem.connection import IncorrectPassword | ||||||
| from stem.util.tor_tools import is_valid_fingerprint | from stem.util.tor_tools import is_valid_fingerprint | ||||||
| try: | try: | ||||||
|     import yaml |     from ruamel.yaml import YAML | ||||||
|  |     yaml = YAML(typ='rt') | ||||||
|  |     yaml.indent(mapping=2, sequence=2) | ||||||
|  |     safe_load = yaml.load | ||||||
| except: | except: | ||||||
|     yaml = None |     yaml = None | ||||||
|  | if yaml is None: | ||||||
|  |     try: | ||||||
|  |         import yaml | ||||||
|  |         safe_load = yaml.safe_load | ||||||
|  |     except: | ||||||
|  |         yaml = None | ||||||
|  | 
 | ||||||
| try: | try: | ||||||
|     from unbound import ub_ctx,RR_TYPE_TXT,RR_CLASS_IN |     from unbound import ub_ctx,RR_TYPE_TXT,RR_CLASS_IN | ||||||
| except: | except: | ||||||
|     ub_ctx = RR_TYPE_TXT = RR_CLASS_IN = None |     ub_ctx = RR_TYPE_TXT = RR_CLASS_IN = None | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| global LOG | global LOG | ||||||
| import logging | import logging | ||||||
| import warnings | import warnings | ||||||
|  | @ -158,7 +167,7 @@ def lYamlBadNodes(sFile, | ||||||
|     if not yaml: return l |     if not yaml: return l | ||||||
|     if os.path.exists(sFile): |     if os.path.exists(sFile): | ||||||
|         with open(sFile, 'rt') as oFd: |         with open(sFile, 'rt') as oFd: | ||||||
|             oBAD_NODES = yaml.safe_load(oFd) |             oBAD_NODES = safe_load(oFd) | ||||||
| 
 | 
 | ||||||
|     # BROKEN |     # BROKEN | ||||||
| #    root = 'ExcludeNodes' | #    root = 'ExcludeNodes' | ||||||
|  | @ -170,7 +179,7 @@ def lYamlBadNodes(sFile, | ||||||
| 
 | 
 | ||||||
|     root = 'ExcludeDomains' |     root = 'ExcludeDomains' | ||||||
|     if root not in oBAD_NODES[oBAD_ROOT] or not oBAD_NODES[oBAD_ROOT][root]: |     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: |     else: | ||||||
|         lMAYBE_NODNS = oBAD_NODES[oBAD_ROOT][root] |         lMAYBE_NODNS = oBAD_NODES[oBAD_ROOT][root] | ||||||
|     return l |     return l | ||||||
|  | @ -184,7 +193,7 @@ def lYamlGoodNodes(sFile='/etc/tor/torrc-goodnodes.yaml'): | ||||||
|     if not yaml: return l |     if not yaml: return l | ||||||
|     if os.path.exists(sFile): |     if os.path.exists(sFile): | ||||||
|         with open(sFile, 'rt') as oFd: |         with open(sFile, 'rt') as oFd: | ||||||
|             o = yaml.safe_load(oFd) |             o = safe_load(oFd) | ||||||
|             oGOOD_NODES = o |             oGOOD_NODES = o | ||||||
|         if 'GuardNodes' in o[oGOOD_ROOT].keys(): |         if 'GuardNodes' in o[oGOOD_ROOT].keys(): | ||||||
|             l = o[oGOOD_ROOT]['GuardNodes'] |             l = o[oGOOD_ROOT]['GuardNodes'] | ||||||
|  | @ -271,7 +280,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.warn(f"{domain} is bad from {a['url']}") | ||||||
|         LOG.debug(f"{fp} is bad from {a}") |         LOG.debug(f"{fp} is bad from {a}") | ||||||
|         return a |         return a | ||||||
|      | 
 | ||||||
|     ip = zResolveDomain(domain) |     ip = zResolveDomain(domain) | ||||||
|     if ip == '': |     if ip == '': | ||||||
|         aFP_EMAIL[fp] = a['email'] |         aFP_EMAIL[fp] = a['email'] | ||||||
|  | @ -373,7 +382,7 @@ def aParseContact(contact, fp): | ||||||
|     s += '\n'.join([f"  {line}\"".replace(':',': \"', 1) |     s += '\n'.join([f"  {line}\"".replace(':',': \"', 1) | ||||||
|                     for line in l]) |                     for line in l]) | ||||||
|     oFd = StringIO(s) |     oFd = StringIO(s) | ||||||
|     a = yaml.safe_load(oFd) |     a = safe_load(oFd) | ||||||
|     return a |     return a | ||||||
| 
 | 
 | ||||||
| def oMainArgparser(_=None): | def oMainArgparser(_=None): | ||||||
|  | @ -414,10 +423,10 @@ def oMainArgparser(_=None): | ||||||
|                         help='proxy download connect timeout') |                         help='proxy download connect timeout') | ||||||
| 
 | 
 | ||||||
|     parser.add_argument('--good_nodes', type=str, |     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") |                         help="Yaml file of good info that should not be excluded") | ||||||
|     parser.add_argument('--bad_nodes', type=str, |     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") |                         help="Yaml file of bad nodes that should also be excluded") | ||||||
|     parser.add_argument('--contact', type=str, default='Empty,NoEmail', |     parser.add_argument('--contact', type=str, default='Empty,NoEmail', | ||||||
|                         help="comma sep list of conditions - Empty,NoEmail") |                         help="comma sep list of conditions - Empty,NoEmail") | ||||||
|  | @ -437,13 +446,13 @@ def oMainArgparser(_=None): | ||||||
|     parser.add_argument('--bad_sections', type=str, |     parser.add_argument('--bad_sections', type=str, | ||||||
|                         default='MyBadExit', |                         default='MyBadExit', | ||||||
|                         help="sections of the badnodes.yaml to use, comma separated, '' BROKEN") |                         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='', |                         default='', | ||||||
|                         help="comma sep. list of onions to whitelist their introduction points - BROKEN") |                         help="comma sep. list of onions to whitelist their introduction points - BROKEN") | ||||||
|     parser.add_argument('--torrc_output', type=str, |     parser.add_argument('--torrc_output', type=str, | ||||||
|                         default=os.path.join(ETC_DIR, 'torrc.new'), |                         default=os.path.join(ETC_DIR, 'torrc.new'), | ||||||
|                         help="Write the torrc configuration to a file") |                         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('--good_contacts', type=str, default=os.path.join(ETC_DIR, 'goodcontacts.yaml'), | ||||||
|                         help="Write the proof data of the included nodes to a YAML file") |                         help="Write the proof data of the included nodes to a YAML file") | ||||||
|     return parser |     return parser | ||||||
| 
 | 
 | ||||||
|  | @ -452,7 +461,7 @@ def vwrite_badnodes(oArgs, oBAD_NODES, slen): | ||||||
|         tmp = oArgs.bad_nodes +'.tmp' |         tmp = oArgs.bad_nodes +'.tmp' | ||||||
|         bak = oArgs.bad_nodes +'.bak' |         bak = oArgs.bad_nodes +'.bak' | ||||||
|         with open(tmp, 'wt') as oFYaml: |         with open(tmp, 'wt') as oFYaml: | ||||||
|             yaml.dump(oBAD_NODES, indent=2, stream=oFYaml) |             yaml.dump(oBAD_NODES, oFYaml) | ||||||
|             LOG.info(f"Wrote {slen}  to {oArgs.bad_nodes}") |             LOG.info(f"Wrote {slen}  to {oArgs.bad_nodes}") | ||||||
|             oFYaml.close() |             oFYaml.close() | ||||||
|         if os.path.exists(oArgs.bad_nodes): |         if os.path.exists(oArgs.bad_nodes): | ||||||
|  | @ -464,7 +473,7 @@ def vwrite_goodnodes(oArgs, oGOOD_NODES, ilen): | ||||||
|         tmp = oArgs.good_nodes +'.tmp' |         tmp = oArgs.good_nodes +'.tmp' | ||||||
|         bak = oArgs.good_nodes +'.bak' |         bak = oArgs.good_nodes +'.bak' | ||||||
|         with open(tmp, 'wt') as oFYaml: |         with open(tmp, 'wt') as oFYaml: | ||||||
|             yaml.dump(oGOOD_NODES, indent=2, stream=oFYaml) |             yaml.dump(oGOOD_NODES, oFYaml) | ||||||
|             LOG.info(f"Wrote {ilen} good relays to {oArgs.good_nodes}") |             LOG.info(f"Wrote {ilen} good relays to {oArgs.good_nodes}") | ||||||
|             oFYaml.close() |             oFYaml.close() | ||||||
|         if os.path.exists(oArgs.good_nodes): |         if os.path.exists(oArgs.good_nodes): | ||||||
|  | @ -489,12 +498,11 @@ def iMain(lArgs): | ||||||
|         icheck_torrc(sFile, oArgs) |         icheck_torrc(sFile, oArgs) | ||||||
| 
 | 
 | ||||||
|     twhitelist_set = set() |     twhitelist_set = set() | ||||||
|     sFile = oArgs.proof_output |     sFile = oArgs.good_contacts | ||||||
|     if sFile and os.path.exists(sFile): |     if sFile and os.path.exists(sFile): | ||||||
|         try: |         try: | ||||||
|             with open(sFile, 'rt') as oFd: |             with open(sFile, 'rt') as oFd: | ||||||
|                 aTRUST_DB = yaml.safe_load(oFd) |                 aTRUST_DB = safe_load(oFd) | ||||||
|             assert type(aTRUST_DB) == dict |  | ||||||
|             LOG.info(f"{len(aTRUST_DB.keys())} trusted contacts from {sFile}") |             LOG.info(f"{len(aTRUST_DB.keys())} trusted contacts from {sFile}") | ||||||
|             # reverse lookup of fps to contacts |             # reverse lookup of fps to contacts | ||||||
|             # but... |             # but... | ||||||
|  | @ -520,8 +528,8 @@ def iMain(lArgs): | ||||||
| 
 | 
 | ||||||
|     vwait_for_controller(controller, oArgs.wait_boot) |     vwait_for_controller(controller, oArgs.wait_boot) | ||||||
| 
 | 
 | ||||||
|     if oArgs.proof_output: |     if oArgs.good_contacts: | ||||||
|         proof_output_tmp = oArgs.proof_output + '.tmp' |         good_contacts_tmp = oArgs.good_contacts + '.tmp' | ||||||
| 
 | 
 | ||||||
|     elt = controller.get_conf('UseMicrodescriptors') |     elt = controller.get_conf('UseMicrodescriptors') | ||||||
|     if elt != '0' : |     if elt != '0' : | ||||||
|  | @ -541,10 +549,17 @@ def iMain(lArgs): | ||||||
|     t = set() |     t = set() | ||||||
|     if 'IntroductionPoints' in oGOOD_NODES[oGOOD_ROOT]['Relays'].keys(): |     if 'IntroductionPoints' in oGOOD_NODES[oGOOD_ROOT]['Relays'].keys(): | ||||||
|         t = set(oGOOD_NODES[oGOOD_ROOT]['Relays']['IntroductionPoints']) |         t = set(oGOOD_NODES[oGOOD_ROOT]['Relays']['IntroductionPoints']) | ||||||
|     # not working = maybe when stem is updated |     w = set() | ||||||
|     w = set(oGOOD_NODES[oGOOD_ROOT]['Services']) |     if 'Services' in oGOOD_NODES[oGOOD_ROOT].keys(): | ||||||
|     if oArgs.white_services: |         # 'Onions' can I use the IntroductionPoints for Services too? | ||||||
|         w.update(oArgs.white_services.split(',')) |         # 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: |     if oArgs.points_timeout > 0: | ||||||
|         LOG.info(f"{len(w)} services will be checked from IntroductionPoints") |         LOG.info(f"{len(w)} services will be checked from IntroductionPoints") | ||||||
|         t.update(lIntroductionPoints(controller, w, itimeout=oArgs.points_timeout)) |         t.update(lIntroductionPoints(controller, w, itimeout=oArgs.points_timeout)) | ||||||
|  | @ -697,10 +712,10 @@ def iMain(lArgs): | ||||||
|             aTRUST_DB[relay.fingerprint] = b |             aTRUST_DB[relay.fingerprint] = b | ||||||
|             for elt in b['fps']: |             for elt in b['fps']: | ||||||
|                 aTRUST_DB_INDEX[elt] = b |                 aTRUST_DB_INDEX[elt] = b | ||||||
|             if oArgs.proof_output and oArgs.log_level <= 20: |             if oArgs.good_contacts and oArgs.log_level <= 20: | ||||||
|                 # as we go along then clobber |                 # as we go along then clobber | ||||||
|                 with open(proof_output_tmp, 'wt') as oFYaml: |                 with open(good_contacts_tmp, 'wt') as oFYaml: | ||||||
|                     yaml.dump(aTRUST_DB, indent=2, stream=oFYaml) |                     yaml.dump(aTRUST_DB, oFYaml) | ||||||
|                     oFYaml.close() |                     oFYaml.close() | ||||||
| 
 | 
 | ||||||
|     LOG.info(f"Filtered {len(twhitelist_set)} whitelisted relays") |     LOG.info(f"Filtered {len(twhitelist_set)} whitelisted relays") | ||||||
|  | @ -709,16 +724,6 @@ def iMain(lArgs): | ||||||
|     texclude_set = texclude_set.difference(tdns_urls) |     texclude_set = texclude_set.difference(tdns_urls) | ||||||
|     LOG.info(f"{len(list(aTRUST_DB.keys()))} good contacts out of {iTotalContacts}") |     LOG.info(f"{len(list(aTRUST_DB.keys()))} good contacts out of {iTotalContacts}") | ||||||
| 
 | 
 | ||||||
|     if oArgs.proof_output and aTRUST_DB: |  | ||||||
|         with open(proof_output_tmp, 'wt') as oFYaml: |  | ||||||
|             yaml.dump(aTRUST_DB, indent=2, stream=oFYaml) |  | ||||||
|             oFYaml.close() |  | ||||||
|         if os.path.exists(oArgs.proof_output): |  | ||||||
|             bak = oArgs.proof_output +'.bak' |  | ||||||
|             os.rename(oArgs.proof_output, bak) |  | ||||||
|         os.rename(proof_output_tmp, oArgs.proof_output) |  | ||||||
|         LOG.info(f"Wrote {len(list(aTRUST_DB.keys()))} good contact details to {oArgs.proof_output}") |  | ||||||
| 
 |  | ||||||
|     if oArgs.torrc_output and texclude_set: |     if oArgs.torrc_output and texclude_set: | ||||||
|         with open(oArgs.torrc_output, 'wt') as oFTorrc: |         with open(oArgs.torrc_output, 'wt') as oFTorrc: | ||||||
|             oFTorrc.write(f"{sEXCLUDE_EXIT_KEY} {','.join(texclude_set)}\n") |             oFTorrc.write(f"{sEXCLUDE_EXIT_KEY} {','.join(texclude_set)}\n") | ||||||
|  | @ -730,9 +735,19 @@ def iMain(lArgs): | ||||||
|     if oArgs.bad_contacts and aBadContacts: |     if oArgs.bad_contacts and aBadContacts: | ||||||
|         # for later analysis |         # for later analysis | ||||||
|         with open(oArgs.bad_contacts, 'wt') as oFYaml: |         with open(oArgs.bad_contacts, 'wt') as oFYaml: | ||||||
|             yaml.dump(aBadContacts, indent=2, stream=oFYaml) |             yaml.dump(aBadContacts, oFYaml) | ||||||
|             oFYaml.close() |             oFYaml.close() | ||||||
| 
 | 
 | ||||||
|  |     if oArgs.good_contacts != '' and aTRUST_DB: | ||||||
|  |         with open(good_contacts_tmp, 'wt') as oFYaml: | ||||||
|  |             yaml.dump(aTRUST_DB, oFYaml) | ||||||
|  |             oFYaml.close() | ||||||
|  |         if os.path.exists(oArgs.good_contacts): | ||||||
|  |             bak = oArgs.good_contacts +'.bak' | ||||||
|  |             os.rename(oArgs.good_contacts, bak) | ||||||
|  |         os.rename(good_contacts_tmp, oArgs.good_contacts) | ||||||
|  |         LOG.info(f"Wrote {len(list(aTRUST_DB.keys()))} good contact details to {oArgs.good_contacts}") | ||||||
|  | 
 | ||||||
|     oBAD_NODES[oBAD_ROOT]['ExcludeNodes']['BadExit'] = list(texclude_set) |     oBAD_NODES[oBAD_ROOT]['ExcludeNodes']['BadExit'] = list(texclude_set) | ||||||
|     oBAD_NODES[oBAD_ROOT]['ExcludeDomains'] = lKNOWN_NODNS |     oBAD_NODES[oBAD_ROOT]['ExcludeDomains'] = lKNOWN_NODNS | ||||||
|     vwrite_badnodes(oArgs, oBAD_NODES, str(len(texclude_set))) |     vwrite_badnodes(oArgs, oBAD_NODES, str(len(texclude_set))) | ||||||
|  | @ -740,6 +755,7 @@ def iMain(lArgs): | ||||||
|     oGOOD_NODES['GoodNodes']['Relays']['ExitNodes'] = list(aTRUST_DB_INDEX.keys()) |     oGOOD_NODES['GoodNodes']['Relays']['ExitNodes'] = list(aTRUST_DB_INDEX.keys()) | ||||||
|     # GuardNodes are readonl |     # GuardNodes are readonl | ||||||
|     vwrite_goodnodes(oArgs, oGOOD_NODES, len(aTRUST_DB_INDEX.keys())) |     vwrite_goodnodes(oArgs, oGOOD_NODES, len(aTRUST_DB_INDEX.keys())) | ||||||
|  |      | ||||||
|     retval = 0 |     retval = 0 | ||||||
|     try: |     try: | ||||||
|         logging.getLogger('stem').setLevel(30) |         logging.getLogger('stem').setLevel(30) | ||||||
|  | @ -776,9 +792,6 @@ def iMain(lArgs): | ||||||
|             LOG.errro(f"Failed setting {sINCLUDE_EXIT_KEY} good exit nodes in Tor") |             LOG.errro(f"Failed setting {sINCLUDE_EXIT_KEY} good exit nodes in Tor") | ||||||
|             retval += 1 |             retval += 1 | ||||||
| 
 | 
 | ||||||
|         sys.stdout.write("dns-rsa domains:\n" +'\n'.join(tdns_urls) +'\n') |  | ||||||
|         return retval |  | ||||||
| 
 |  | ||||||
|     except InvalidRequest as e: |     except InvalidRequest as e: | ||||||
|         # Unacceptable option value: Invalid router list. |         # Unacceptable option value: Invalid router list. | ||||||
|         LOG.error(str(e)) |         LOG.error(str(e)) | ||||||
|  | @ -802,6 +815,9 @@ def iMain(lArgs): | ||||||
|             controller.close() |             controller.close() | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             LOG.warn(str(e)) |             LOG.warn(str(e)) | ||||||
|  |              | ||||||
|  |     sys.stdout.write("dns-rsa domains:\n" +'\n'.join(tdns_urls) +'\n') | ||||||
|  |     return retval | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     try: |     try: | ||||||
|  |  | ||||||
|  | @ -14,10 +14,12 @@ if False: | ||||||
|     import cepa as stem |     import cepa as stem | ||||||
|     from cepa.control import Controller |     from cepa.control import Controller | ||||||
|     from cepa.connection import MissingPassword |     from cepa.connection import MissingPassword | ||||||
|  |     from cepa.util.tor_tools import is_valid_fingerprint | ||||||
| else: | else: | ||||||
|     import stem |     import stem | ||||||
|     from stem.control import Controller |     from stem.control import Controller | ||||||
|     from stem.connection import MissingPassword |     from stem.connection import MissingPassword | ||||||
|  |     from stem.util.tor_tools import is_valid_fingerprint | ||||||
| 
 | 
 | ||||||
| global LOG | global LOG | ||||||
| import logging | import logging | ||||||
|  | @ -96,7 +98,7 @@ def oGetStemController(log_level=10, sock_or_pair='/run/tor/control'): | ||||||
|         controller.authenticate(p) |         controller.authenticate(p) | ||||||
|     oSTEM_CONTROLER = controller |     oSTEM_CONTROLER = controller | ||||||
|     LOG.debug(f"{controller}") |     LOG.debug(f"{controller}") | ||||||
|     return oSTEM_CONTROLER  |     return oSTEM_CONTROLER | ||||||
| 
 | 
 | ||||||
| def bAreWeConnected(): | def bAreWeConnected(): | ||||||
|     # FixMe: Linux only |     # FixMe: Linux only | ||||||
|  | @ -144,7 +146,11 @@ def bin_to_hex(raw_id, length=None): | ||||||
|     return res.upper() |     return res.upper() | ||||||
| 
 | 
 | ||||||
| def lIntroductionPoints(controller=None, lOnions=[], itimeout=120, log_level=10): | def lIntroductionPoints(controller=None, lOnions=[], itimeout=120, log_level=10): | ||||||
|     """now working !!! stem 1.8.x timeout must be huge >120""" |     """now working !!! stem 1.8.x timeout must be huge >120 | ||||||
|  |     'Provides the descriptor for a hidden service. The **address** is the | ||||||
|  |     '.onion' address of the hidden service ' | ||||||
|  |     What about Services? | ||||||
|  |     """ | ||||||
|     try: |     try: | ||||||
|         from cryptography.utils import int_from_bytes |         from cryptography.utils import int_from_bytes | ||||||
|     except ImportError: |     except ImportError: | ||||||
|  | @ -154,12 +160,12 @@ def lIntroductionPoints(controller=None, lOnions=[], itimeout=120, log_level=10) | ||||||
|     # this will fai if the trick above didnt work |     # this will fai if the trick above didnt work | ||||||
|     from stem.prereq import is_crypto_available |     from stem.prereq import is_crypto_available | ||||||
|     is_crypto_available(ed25519 = True) |     is_crypto_available(ed25519 = True) | ||||||
|      | 
 | ||||||
|     from stem.descriptor.hidden_service import HiddenServiceDescriptorV3 |     from stem.descriptor.hidden_service import HiddenServiceDescriptorV3 | ||||||
|     from stem.client.datatype import LinkByFingerprint |     from stem.client.datatype import LinkByFingerprint | ||||||
|     from stem import Timeout |     from stem import Timeout | ||||||
|     from queue import Empty |     from queue import Empty | ||||||
|      | 
 | ||||||
|     if type(lOnions) not in [set, tuple, list]: |     if type(lOnions) not in [set, tuple, list]: | ||||||
|         lOnions = list(lOnions) |         lOnions = list(lOnions) | ||||||
|     if controller is None: |     if controller is None: | ||||||
|  | @ -277,7 +283,7 @@ def sTorResolve(target, | ||||||
|         LOG.info(sLabel +f"{i} on {sHost}:{iPort}" ) |         LOG.info(sLabel +f"{i} on {sHost}:{iPort}" ) | ||||||
|         sock.close() |         sock.close() | ||||||
|         raise SystemExit(5) |         raise SystemExit(5) | ||||||
|      | 
 | ||||||
|     assert len(data) >= 8 |     assert len(data) >= 8 | ||||||
|     packet_sf = data[1] |     packet_sf = data[1] | ||||||
|     if packet_sf == 90: |     if packet_sf == 90: | ||||||
|  | @ -292,7 +298,7 @@ def sTorResolve(target, | ||||||
| #    os.system("strace tor-resolve -4 "+target+" 2>&1|grep '^sen\|^rec'") | #    os.system("strace tor-resolve -4 "+target+" 2>&1|grep '^sen\|^rec'") | ||||||
| 
 | 
 | ||||||
|     return '' |     return '' | ||||||
|      | 
 | ||||||
| def getaddrinfo(sHost, sPort): | def getaddrinfo(sHost, sPort): | ||||||
|     # do this the explicit way = Ive seen the compact connect fail |     # do this the explicit way = Ive seen the compact connect fail | ||||||
|     # >>> sHost, sPort = 'l27.0.0.1', 33446 |     # >>> sHost, sPort = 'l27.0.0.1', 33446 | ||||||
|  | @ -393,4 +399,4 @@ def lExitExcluder(oArgs, iPort=9051, log_level=10): | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     target = 'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad' |     target = 'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad' | ||||||
|     controller = oGetStemController(log_level=10) |     controller = oGetStemController(log_level=10) | ||||||
|     lIntroductionPoints(controller, [target], itimeout=120)     |     lIntroductionPoints(controller, [target], itimeout=120) | ||||||
|  |  | ||||||
|  | @ -355,7 +355,7 @@ def _my_match_hostname(cert, asserted_hostname): | ||||||
|     try: |     try: | ||||||
|         my_match_hostname(cert, asserted_hostname) |         my_match_hostname(cert, asserted_hostname) | ||||||
|     except CertificateError as e: |     except CertificateError as e: | ||||||
|         log.warning( |         LOG.warning( | ||||||
|             "Certificate did not match hostname: %s. Certificate: %s", |             "Certificate did not match hostname: %s. Certificate: %s", | ||||||
|             asserted_hostname, |             asserted_hostname, | ||||||
|             cert, |             cert, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue