From 511c486a5e6cb5a45aadc30883afc545cf370337 Mon Sep 17 00:00:00 2001 From: trifatale Date: Wed, 18 Feb 2026 13:22:59 -0900 Subject: [PATCH] fix: add macOS DNS redirect preload for MITM Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- src/standalone/mod.rs | 21 +++++++++++++-------- src/standalone/spawn.rs | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/standalone/mod.rs b/src/standalone/mod.rs index 590f2fa..a75d76e 100644 --- a/src/standalone/mod.rs +++ b/src/standalone/mod.rs @@ -65,12 +65,12 @@ pub fn discover_main_ls_config() -> Result { discovery::discover_main_ls_config() } -/// Build the dns_redirect.so preload library if it doesn't already exist. +/// Build the dns_redirect preload library if it doesn't already exist. /// -/// Linux only — hooks `getaddrinfo()` via LD_PRELOAD to redirect Google API -/// domain lookups to 127.0.0.1. +/// Linux/macOS — hooks `getaddrinfo()` via LD_PRELOAD/DYLD_INSERT_LIBRARIES +/// to redirect Google API domain lookups to 127.0.0.1. /// -/// Returns the path to the .so on success, None on failure. +/// Returns the path to the shared library on success, None on failure. fn build_dns_redirect_so() -> Option { if !platform::supports_ld_preload() { return None; @@ -91,10 +91,15 @@ fn build_dns_redirect_so() -> Option { return None; } - // Compile: gcc -shared -fPIC -o dns_redirect.so dns_redirect.c -ldl - let output = Command::new("gcc") - .args(["-shared", "-fPIC", "-o", so_path.as_str(), &c_path, "-ldl"]) - .output(); + let output = if cfg!(target_os = "macos") { + Command::new("cc") + .args(["-dynamiclib", "-o", so_path.as_str(), &c_path]) + .output() + } else { + Command::new("gcc") + .args(["-shared", "-fPIC", "-o", so_path.as_str(), &c_path, "-ldl"]) + .output() + }; match output { Ok(out) if out.status.success() => { diff --git a/src/standalone/spawn.rs b/src/standalone/spawn.rs index b270c25..76e03e6 100644 --- a/src/standalone/spawn.rs +++ b/src/standalone/spawn.rs @@ -281,15 +281,23 @@ impl StandaloneLS { // even the CodeAssistClient which has Proxy:nil hardcoded. let so_path = build_dns_redirect_so(); 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.clone())); + info!(path = %so, "Enabling DNS redirect preload for headless MITM"); + #[cfg(target_os = "macos")] + { + env_vars.push(("DYLD_INSERT_LIBRARIES".into(), so.clone())); + env_vars.push(("DYLD_FORCE_FLAT_NAMESPACE".into(), "1".into())); + } + #[cfg(not(target_os = "macos"))] + { + 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. + // the pure-Go resolver. Without this, getaddrinfo hooks are + // bypassed because Go resolves DNS internally. env_vars.push(("GODEBUG".into(), "netdns=cgo".into())); }