Move Tor prompt before cost estimate and factor Tor latency into estimate table

- Tor choice now appears before the estimate table so the displayed time/cost is accurate
- build_estimate_table accepts use_tor; applies 0.2x rate multiplier for nmap/probe modes
- masscan-only excluded from multiplier (masscan bypasses proxychains via raw sockets)
- Added per-mode warnings explaining which traffic actually routes through Tor
This commit is contained in:
n0mad1k
2026-04-30 16:59:24 -04:00
parent 81098d9111
commit 23aabaf520
2 changed files with 25 additions and 11 deletions
+17 -11
View File
@@ -157,8 +157,8 @@ def _get_targets_info(scan_mode: str) -> tuple[str, list[int]]:
return "", sorted(set(ports_list)) or [80, 443, 22]
def _show_estimate_table(total_ips: int, n_ports: int, providers: list[str], scan_mode: str):
rows = build_estimate_table(total_ips, n_ports, providers, scan_mode)
def _show_estimate_table(total_ips: int, n_ports: int, providers: list[str], scan_mode: str, use_tor: bool = False):
rows = build_estimate_table(total_ips, n_ports, providers, scan_mode, use_tor=use_tor)
C = COLORS['CYAN']
W = COLORS['WHITE']
@@ -166,10 +166,11 @@ def _show_estimate_table(total_ips: int, n_ports: int, providers: list[str], sca
G = COLORS['GREEN']
R = COLORS['RESET']
tor_note = " [Tor: estimates reflect nmap/probe latency]" if use_tor else ""
print(f"\n{C}{'' * 70}{R}")
print(f"{C} WEBRUNNER — Cost & Time Estimate{R}")
print(f"{W} Total: {fmt_ip_count(total_ips)} IPs {n_ports} ports Mode: {scan_mode}{R}")
print(f"{W} Providers: {', '.join(PROVIDER_LABELS[p] for p in providers)}{R}")
print(f"{W} Providers: {', '.join(PROVIDER_LABELS[p] for p in providers)}{Y}{tor_note}{R}")
print(f"{C}{'' * 70}{R}")
print(f" {'Preset':<14} {'Nodes':>6} {'IPs/Node':>10} {'Time/Node':>12} {'Total $':>10}")
print(f" {'' * 56}")
@@ -266,8 +267,19 @@ def gather_webrunner_parameters() -> dict | None:
print(f"{COLORS['GREEN']}Total: {fmt_ip_count(total_ips)} IPs across {len(country_codes)} countries{COLORS['RESET']}")
config['total_ips'] = total_ips
# Cost / time estimate
_show_estimate_table(total_ips, len(ports), providers, scan_mode)
# Tor routing — ask before estimate so table reflects the slowdown
tor_raw = input(f"\nRoute scans through Tor? [y/N]: ").strip().lower()
config['use_tor'] = tor_raw in ['y', 'yes']
if config['use_tor']:
if scan_mode == 'masscan-only':
print(f"{COLORS['YELLOW']} Warning: masscan uses raw sockets and bypasses proxychains — Tor has no effect in masscan-only mode.{COLORS['RESET']}")
elif scan_mode in ('geo-scout', 'masscan+nmap'):
print(f"{COLORS['YELLOW']} Note: masscan phase bypasses Tor (raw sockets); nmap and probe phases will use Tor.{COLORS['RESET']}")
else:
print(f"{COLORS['YELLOW']} Tor routing enabled — all nmap traffic will use proxychains → SOCKS5 9050.{COLORS['RESET']}")
# Cost / time estimate — reflects Tor throughput impact
_show_estimate_table(total_ips, len(ports), providers, scan_mode, use_tor=config['use_tor'])
# Preset selection
print(f"{COLORS['BLUE']}Select deployment preset:{COLORS['RESET']}")
@@ -322,12 +334,6 @@ def gather_webrunner_parameters() -> dict | None:
config['node_chunks'] = node_chunks
print(f"{COLORS['GREEN']}Nodes: {len(node_chunks)} ({preset_key}, {fmt_ip_count(chunk_size)}/node){COLORS['RESET']}")
# Tor routing
tor_raw = input(f"\nRoute scans through Tor? [y/N]: ").strip().lower()
config['use_tor'] = tor_raw in ['y', 'yes']
if config['use_tor']:
print(f"{COLORS['YELLOW']} Tor routing enabled — masscan/nmap will use proxychains{COLORS['RESET']}")
# Operator IP
config['operator_ip'] = get_public_ip()
if config['operator_ip']:
+8
View File
@@ -73,13 +73,21 @@ def fmt_ip_count(n: int) -> str:
return str(n)
# Tor adds ~5x latency overhead for TCP probes; masscan bypasses proxychains (raw sockets)
# so only nmap/probe phases are affected — modes that include masscan see partial impact
TOR_RATE_MULTIPLIER = 0.2
def build_estimate_table(
total_ips: int,
n_ports: int,
providers: list[str],
scan_mode: str,
use_tor: bool = False,
) -> list[dict]:
mode_rate = SCAN_MODES.get(scan_mode, {'rate': 3000})['rate']
if use_tor and scan_mode != 'masscan-only':
mode_rate = int(mode_rate * TOR_RATE_MULTIPLIER)
rows = []
for preset_key, preset in PRESETS.items():
n_chunks = max(1, math.ceil(total_ips / preset['chunk_size']))