From ca33b2d74a0d9c8edf0a64978c1c434b9e7372b5 Mon Sep 17 00:00:00 2001 From: Stefano Fiorini Date: Thu, 12 Mar 2026 01:20:02 -0500 Subject: [PATCH] fix: avoid mac wireguard dns rewrites --- docs/nordvpn-client.md | 2 ++ skills/nordvpn-client/SKILL.md | 1 + .../nordvpn-client/scripts/nordvpn-client.js | 5 ----- .../scripts/nordvpn-client.test.js | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/nordvpn-client.md b/docs/nordvpn-client.md index 2c51d65..c4eeead 100644 --- a/docs/nordvpn-client.md +++ b/docs/nordvpn-client.md @@ -36,6 +36,8 @@ node skills/nordvpn-client/scripts/nordvpn-client.js disconnect - `wireguard-go` - `wireguard-tools` - non-interactive `sudo` for `~/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh` +- the macOS WireGuard config intentionally omits `DNS = ...` + - reason: `wg-quick` on macOS rewrites system DNS across services when `DNS` is present, which can break connectivity and other tunnels - `NordVPN.app` may stay installed but is only the manual fallback - the app login is not reused by the automated WireGuard backend diff --git a/skills/nordvpn-client/SKILL.md b/skills/nordvpn-client/SKILL.md index c63b790..0ca098a 100644 --- a/skills/nordvpn-client/SKILL.md +++ b/skills/nordvpn-client/SKILL.md @@ -42,6 +42,7 @@ node scripts/nordvpn-client.js disconnect - `install` bootstraps those tools with Homebrew - equivalent Homebrew command: `brew install wireguard-go wireguard-tools` - `login` validates `NORDVPN_TOKEN` / `NORDVPN_TOKEN_FILE` for the WireGuard backend + - the generated WireGuard config intentionally omits `DNS = ...` so `wg-quick` does not rewrite system resolvers or break other interfaces such as Tailscale - `NordVPN.app` can remain installed, but it is only the manual fallback ## Credentials diff --git a/skills/nordvpn-client/scripts/nordvpn-client.js b/skills/nordvpn-client/scripts/nordvpn-client.js index 7f8dd39..b1d25bc 100644 --- a/skills/nordvpn-client/scripts/nordvpn-client.js +++ b/skills/nordvpn-client/scripts/nordvpn-client.js @@ -33,8 +33,6 @@ const MAC_WG_HELPER_PATH = path.join( "scripts", "nordvpn-wireguard-helper.sh" ); -const DEFAULT_DNS_IPV4 = "103.86.96.100"; -const DEFAULT_DNS_IPV6 = "2400:bb40:4444::100"; const CLIENT_IPV4 = "10.5.0.2"; const DNS_FALLBACK_RESOLVERS = ["1.1.1.1", "8.8.8.8"]; @@ -797,13 +795,11 @@ function buildWireguardConfig(server, privateKey) { const ipAddresses = getServerIpAddresses(server); const ipv6 = ipAddresses.find((value) => `${value}`.includes(":")); const addresses = [CLIENT_IPV4]; - const dnsServers = [DEFAULT_DNS_IPV4]; const allowedIps = ["0.0.0.0/0"]; if (ipv6) { const clientIpv6 = deriveClientIpv6(ipv6); if (clientIpv6) addresses.push(clientIpv6); - dnsServers.push(DEFAULT_DNS_IPV6); allowedIps.push("::/0"); } @@ -816,7 +812,6 @@ function buildWireguardConfig(server, privateKey) { "[Interface]", `PrivateKey = ${privateKey}`, `Address = ${addresses.join(", ")}`, - `DNS = ${dnsServers.join(", ")}`, "", "[Peer]", `PublicKey = ${publicKey}`, diff --git a/skills/nordvpn-client/scripts/nordvpn-client.test.js b/skills/nordvpn-client/scripts/nordvpn-client.test.js index 7cc440d..8e7f71e 100644 --- a/skills/nordvpn-client/scripts/nordvpn-client.test.js +++ b/skills/nordvpn-client/scripts/nordvpn-client.test.js @@ -9,6 +9,8 @@ function loadInternals() { const source = fs.readFileSync(scriptPath, "utf8").replace(/\nmain\(\);\s*$/, "\n"); const wrapped = `${source} module.exports = { + buildWireguardConfig: + typeof buildWireguardConfig === "function" ? buildWireguardConfig : undefined, buildLookupResult: typeof buildLookupResult === "function" ? buildLookupResult : undefined, detectMacWireguardActiveFromIfconfig: @@ -60,6 +62,23 @@ test("buildLookupResult supports lookup all=true mode", () => { assert.equal(JSON.stringify(buildLookupResult("104.26.9.44", { all: false })), JSON.stringify(["104.26.9.44", 4])); }); +test("buildWireguardConfig omits DNS so macOS wg-quick does not rewrite system resolvers", () => { + const { buildWireguardConfig } = loadInternals(); + assert.equal(typeof buildWireguardConfig, "function"); + + const config = buildWireguardConfig( + { + hostname: "tr73.nordvpn.com", + ips: [{ ip: { version: 4, ip: "45.89.52.1" } }], + technologies: [{ identifier: "wireguard_udp", metadata: [{ name: "public_key", value: "PUBKEY" }] }], + }, + "PRIVATEKEY" + ); + + assert.equal(config.includes("DNS ="), false); + assert.equal(config.includes("AllowedIPs = 0.0.0.0/0"), true); +}); + test("verifyConnectionWithRetry retries transient reachability failures", async () => { const { verifyConnectionWithRetry } = loadInternals(); assert.equal(typeof verifyConnectionWithRetry, "function");