From 60d7cd677ea79553f711068093d7fddd2aca23c1 Mon Sep 17 00:00:00 2001 From: Kazuki-0147 <199524034+Kazuki-0147@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:00:53 +0000 Subject: [PATCH] fix: avoid HTTPS_PROXY when DNS redirect is active in headless mode When LD_PRELOAD DNS redirect is active, setting HTTPS_PROXY causes Go's net/http to send HTTP CONNECT requests through the MITM proxy. However, the MITM proxy expects direct TLS connections for SNI-based interception, not CONNECT tunneling. This mismatch causes all non-gRPC calls (OAuth token refresh, fetchUserInfo, etc.) to fail with EOF/timeout errors. Changes: - Only set HTTPS_PROXY/HTTP_PROXY as fallback when DNS redirect SO is not available - Add GODEBUG=netdns=cgo to force Go's cgo (libc) DNS resolver, since the pure-Go resolver bypasses LD_PRELOAD getaddrinfo() hooks entirely Fixes #4 --- src/standalone/spawn.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/standalone/spawn.rs b/src/standalone/spawn.rs index b9f39e7..b270c25 100644 --- a/src/standalone/spawn.rs +++ b/src/standalone/spawn.rs @@ -275,22 +275,32 @@ impl StandaloneLS { // With iptables, all outbound traffic is transparently redirected at the // kernel level — setting HTTPS_PROXY on top causes double-proxying. if headless || !platform::supports_uid_isolation() { - // proxy_addr already includes the scheme (e.g. "http://127.0.0.1:8742") - env_vars.push(("HTTPS_PROXY".into(), mitm.proxy_addr.clone())); - env_vars.push(("HTTP_PROXY".into(), mitm.proxy_addr.clone())); - // LD_PRELOAD DNS redirect: hooks getaddrinfo() so Google API domains // resolve to 127.0.0.1. Combined with the port-modified endpoint URL, // this makes the LS connect to our MITM proxy for ALL API calls — // even the CodeAssistClient which has Proxy:nil hardcoded. let so_path = build_dns_redirect_so(); - if let Some(so) = so_path { + if let Some(ref so) = so_path { info!(path = %so, "Enabling LD_PRELOAD DNS redirect for headless MITM"); - env_vars.push(("LD_PRELOAD".into(), so)); + env_vars.push(("LD_PRELOAD".into(), so.clone())); env_vars.push(( "DNS_REDIRECT_LOG".into(), format!("{data_dir}/dns-redirect.log"), )); + // Force Go binaries to use cgo (libc) DNS resolver instead of + // the pure-Go resolver. Without this, LD_PRELOAD getaddrinfo() + // hooks are bypassed because Go resolves DNS internally. + env_vars.push(("GODEBUG".into(), "netdns=cgo".into())); + } + + // Only set HTTPS_PROXY as fallback when DNS redirect is NOT available. + // When DNS redirect IS active, HTTPS_PROXY is redundant and harmful: + // Go's net/http sends HTTP CONNECT through the proxy, but the MITM + // proxy expects direct TLS connections (SNI-based interception). + // This causes OAuth token refresh and other non-gRPC calls to fail. + if so_path.is_none() { + env_vars.push(("HTTPS_PROXY".into(), mitm.proxy_addr.clone())); + env_vars.push(("HTTP_PROXY".into(), mitm.proxy_addr.clone())); } } }