From 839a364cacbdd14d6fd82388c31b9d0c3c30686f Mon Sep 17 00:00:00 2001 From: ospab Date: Thu, 28 May 2026 01:09:10 +0300 Subject: [PATCH] fix(client): resolve server domain to IP before starting TUN to prevent DNS deadlock on reconnects --- ostp-client/src/runner.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ostp-client/src/runner.rs b/ostp-client/src/runner.rs index bf48eda..f6e7d22 100644 --- a/ostp-client/src/runner.rs +++ b/ostp-client/src/runner.rs @@ -143,7 +143,7 @@ pub async fn run_client(config: crate::config::ClientConfig) -> Result<()> { } pub async fn run_client_core( - config: crate::config::ClientConfig, + mut config: crate::config::ClientConfig, metrics: Arc, mut shutdown_rx_ext: watch::Receiver, ) -> Result<()> { @@ -154,6 +154,21 @@ pub async fn run_client_core( log_to_core_file(&format!("[core] Starting run_client_core in mode: {}", config.mode)); + // Resolve the server IP before we override system routing and DNS. + // This prevents DNS deadlock if the VPN disconnects and tries to reconnect, + // and also ensures we add the direct route to the exact IP the bridge connects to. + let resolved_addrs: Vec = tokio::net::lookup_host(&config.ostp.server_addr) + .await + .map_err(|e| anyhow::anyhow!("Failed to resolve server address {}: {}", config.ostp.server_addr, e))? + .collect(); + + let target_addr = resolved_addrs.first() + .ok_or_else(|| anyhow::anyhow!("No IP addresses resolved for {}", config.ostp.server_addr))?; + + log_to_core_file(&format!("[core] Resolved server address to {}", target_addr)); + config.ostp.server_addr = target_addr.to_string(); + + #[cfg(target_os = "linux")] if config.mode == "tun" { println!("\n[ostp] ===========================================================================");