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:
@@ -157,8 +157,8 @@ def _get_targets_info(scan_mode: str) -> tuple[str, list[int]]:
|
|||||||
return "", sorted(set(ports_list)) or [80, 443, 22]
|
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):
|
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)
|
rows = build_estimate_table(total_ips, n_ports, providers, scan_mode, use_tor=use_tor)
|
||||||
|
|
||||||
C = COLORS['CYAN']
|
C = COLORS['CYAN']
|
||||||
W = COLORS['WHITE']
|
W = COLORS['WHITE']
|
||||||
@@ -166,10 +166,11 @@ def _show_estimate_table(total_ips: int, n_ports: int, providers: list[str], sca
|
|||||||
G = COLORS['GREEN']
|
G = COLORS['GREEN']
|
||||||
R = COLORS['RESET']
|
R = COLORS['RESET']
|
||||||
|
|
||||||
|
tor_note = " [Tor: estimates reflect nmap/probe latency]" if use_tor else ""
|
||||||
print(f"\n{C}{'─' * 70}{R}")
|
print(f"\n{C}{'─' * 70}{R}")
|
||||||
print(f"{C} WEBRUNNER — Cost & Time Estimate{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} 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"{C}{'─' * 70}{R}")
|
||||||
print(f" {'Preset':<14} {'Nodes':>6} {'IPs/Node':>10} {'Time/Node':>12} {'Total $':>10}")
|
print(f" {'Preset':<14} {'Nodes':>6} {'IPs/Node':>10} {'Time/Node':>12} {'Total $':>10}")
|
||||||
print(f" {'─' * 56}")
|
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']}")
|
print(f"{COLORS['GREEN']}Total: {fmt_ip_count(total_ips)} IPs across {len(country_codes)} countries{COLORS['RESET']}")
|
||||||
config['total_ips'] = total_ips
|
config['total_ips'] = total_ips
|
||||||
|
|
||||||
# Cost / time estimate
|
# Tor routing — ask before estimate so table reflects the slowdown
|
||||||
_show_estimate_table(total_ips, len(ports), providers, scan_mode)
|
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
|
# Preset selection
|
||||||
print(f"{COLORS['BLUE']}Select deployment preset:{COLORS['RESET']}")
|
print(f"{COLORS['BLUE']}Select deployment preset:{COLORS['RESET']}")
|
||||||
@@ -322,12 +334,6 @@ def gather_webrunner_parameters() -> dict | None:
|
|||||||
config['node_chunks'] = node_chunks
|
config['node_chunks'] = node_chunks
|
||||||
print(f"{COLORS['GREEN']}Nodes: {len(node_chunks)} ({preset_key}, {fmt_ip_count(chunk_size)}/node){COLORS['RESET']}")
|
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
|
# Operator IP
|
||||||
config['operator_ip'] = get_public_ip()
|
config['operator_ip'] = get_public_ip()
|
||||||
if config['operator_ip']:
|
if config['operator_ip']:
|
||||||
|
|||||||
@@ -73,13 +73,21 @@ def fmt_ip_count(n: int) -> str:
|
|||||||
return str(n)
|
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(
|
def build_estimate_table(
|
||||||
total_ips: int,
|
total_ips: int,
|
||||||
n_ports: int,
|
n_ports: int,
|
||||||
providers: list[str],
|
providers: list[str],
|
||||||
scan_mode: str,
|
scan_mode: str,
|
||||||
|
use_tor: bool = False,
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
mode_rate = SCAN_MODES.get(scan_mode, {'rate': 3000})['rate']
|
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 = []
|
rows = []
|
||||||
for preset_key, preset in PRESETS.items():
|
for preset_key, preset in PRESETS.items():
|
||||||
n_chunks = max(1, math.ceil(total_ips / preset['chunk_size']))
|
n_chunks = max(1, math.ceil(total_ips / preset['chunk_size']))
|
||||||
|
|||||||
Reference in New Issue
Block a user