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
This commit is contained in:
Kazuki-0147
2026-02-18 19:00:53 +00:00
parent 29bebd79ea
commit 60d7cd677e

View File

@@ -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()));
}
}
}