Save-as-final-hop button, browser proxy policy + QUIC kill, HTTPS tunnel probe

Fixes 'exit proxy never used in chain' and 'browsers break when chain is green'. Chain Builder gets a Save-as-final-hop button that appends the typed exit proxy to the manual chain. On engage, Chromium browsers get pinned to our proxy via HKLM policy (ProxyMode=fixed_servers, ProxyServer, ProxyBypassList) and QuicAllowed=0 so HTTP/3 doesn't bypass HTTP proxies and stall under the kill-switch. Chain start now runs check_https_tunnel and warns clearly when proxies forward HTTP but refuse CONNECT — the real cause of green-chain-yet-blank-browser.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Indiana Holmes
2026-05-16 23:30:29 -07:00
parent 094e0577fb
commit f9c548872b
5 changed files with 160 additions and 4 deletions

View File

@@ -237,3 +237,41 @@ async def get_direct_ip(check_url: str, timeout_seconds: float = 15.0) -> str |
except asyncio.TimeoutError:
log.debug("get_direct_ip timed out after %.1fs", budget)
return None
async def check_https_tunnel(
listen_proxy: str,
timeout_seconds: float = 12.0,
) -> tuple[bool, str]:
"""Return (ok, message). True means the chain successfully tunneled HTTPS.
Many free proxies pass plain HTTP but refuse HTTP ``CONNECT`` (the method
required to tunnel TLS). The chain can look healthy on an IP-check via
plain HTTP yet break every HTTPS page a browser tries to load. This probe
catches that case at start time so the user gets a clear warning instead
of a mystery "browser broken".
"""
per = max(5.0, min(20.0, float(timeout_seconds)))
t = httpx.Timeout(per, connect=min(8.0, per))
# Use a tiny, fast, very-common HTTPS endpoint.
targets = [
"https://www.google.com/generate_204",
"https://www.cloudflare.com/cdn-cgi/trace",
"https://duckduckgo.com/",
]
last_err = ""
try:
async with httpx.AsyncClient(
proxy=listen_proxy, timeout=t, verify=False, follow_redirects=True,
) as c:
for url in targets:
try:
r = await c.get(url)
if 200 <= r.status_code < 400:
return True, f"HTTPS OK via {url} ({r.status_code})"
except Exception as e:
last_err = f"{type(e).__name__}: {e}"
continue
except Exception as e:
last_err = f"{type(e).__name__}: {e}"
return False, last_err or "all HTTPS targets failed"