Add ban tester, signup prep, exit IP intel, and sticky-exit hold.

New GUI tabs probe popular sites for exit-IP bans and prep signup autofill through the chain; Live tab shows geo/ASN/datacenter flags, and sticky-exit keeps the same egress IP during signup flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Indiana Holmes
2026-05-19 15:37:28 -07:00
parent 8258ca0997
commit 26863fc2a5
8 changed files with 1587 additions and 3 deletions

View File

@@ -79,6 +79,9 @@ class ChainService:
self._proc = None
self._settings = load_settings()
self._current_chain: list[str] = []
# Sticky-exit: while time.monotonic() < self._sticky_until, leak-based
# auto-rotation is skipped so signup flows keep the same egress IP.
self._sticky_until: float = 0.0
# Shuffle-and-drain pool state — never repeat a proxy within a cycle
self._available: list[str] = [] # proxies not yet used this cycle
@@ -142,6 +145,21 @@ class ChainService:
def rotate_now(self) -> None:
self._force_rotate.set()
def set_sticky(self, seconds: float) -> None:
"""Hold current exit for ``seconds`` (suppresses leak-driven rotation).
Manual rotation still works. Pass 0 to clear sticky mode immediately.
"""
if seconds <= 0:
self._sticky_until = 0.0
return
self._sticky_until = time.monotonic() + float(seconds)
def sticky_remaining(self) -> float:
"""Seconds remaining on sticky-exit hold (0.0 if not sticky)."""
rem = self._sticky_until - time.monotonic()
return rem if rem > 0 else 0.0
# ─────────────────────────────────────────────────────────────────────────
def _teardown_network(self) -> None:
@@ -588,6 +606,17 @@ class ChainService:
if is_chain_leak(exit_ip, real_ip, self._vpn.active):
reason = leak_reason(exit_ip, real_ip, self._vpn.active)
rem = self.sticky_remaining()
if rem > 0:
self._notify({
"type": "log",
"text": (
f"Health check flagged ({reason}) — STICKY EXIT active "
f"({int(rem)}s left), skipping rotation."
),
})
self._notify({"type": "hops", "hops": chain, "status": "healthy", "exit_ip": exit_ip})
continue
self._notify({"type": "hops", "hops": chain, "status": "dead", "exit_ip": exit_ip})
self._notify({"type": "log", "text": f"Health check failed ({reason}) — rotating."})
break