feat: add nordvpn wireguard sudo helper
This commit is contained in:
@@ -35,7 +35,7 @@ node skills/nordvpn-client/scripts/nordvpn-client.js disconnect
|
|||||||
- `NORDVPN_TOKEN` or `NORDVPN_TOKEN_FILE`
|
- `NORDVPN_TOKEN` or `NORDVPN_TOKEN_FILE`
|
||||||
- `wireguard-go`
|
- `wireguard-go`
|
||||||
- `wireguard-tools`
|
- `wireguard-tools`
|
||||||
- non-interactive `sudo` for `wg-quick`
|
- non-interactive `sudo` for `~/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh`
|
||||||
- `NordVPN.app` may stay installed but is only the manual fallback
|
- `NordVPN.app` may stay installed but is only the manual fallback
|
||||||
- the app login is not reused by the automated WireGuard backend
|
- the app login is not reused by the automated WireGuard backend
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,6 @@ For an automated macOS flow:
|
|||||||
- `NORDVPN_TOKEN` or `NORDVPN_TOKEN_FILE`
|
- `NORDVPN_TOKEN` or `NORDVPN_TOKEN_FILE`
|
||||||
- `wireguard-go`
|
- `wireguard-go`
|
||||||
- `wireguard-tools`
|
- `wireguard-tools`
|
||||||
- non-interactive `sudo` for `wg-quick`
|
- non-interactive `sudo` for `~/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh`
|
||||||
- `NordVPN.app` login on macOS is not reused by the WireGuard backend.
|
- `NordVPN.app` login on macOS is not reused by the WireGuard backend.
|
||||||
- The Homebrew `nordvpn` app does not need to be uninstalled. It can coexist with the WireGuard backend.
|
- The Homebrew `nordvpn` app does not need to be uninstalled. It can coexist with the WireGuard backend.
|
||||||
|
|||||||
@@ -22,6 +22,15 @@ const OPENCLAW_NORDVPN_CREDENTIALS_DIR = path.join(
|
|||||||
);
|
);
|
||||||
const DEFAULT_TOKEN_FILE = path.join(OPENCLAW_NORDVPN_CREDENTIALS_DIR, "token.txt");
|
const DEFAULT_TOKEN_FILE = path.join(OPENCLAW_NORDVPN_CREDENTIALS_DIR, "token.txt");
|
||||||
const DEFAULT_PASSWORD_FILE = path.join(OPENCLAW_NORDVPN_CREDENTIALS_DIR, "password.txt");
|
const DEFAULT_PASSWORD_FILE = path.join(OPENCLAW_NORDVPN_CREDENTIALS_DIR, "password.txt");
|
||||||
|
const MAC_WG_HELPER_PATH = path.join(
|
||||||
|
os.homedir(),
|
||||||
|
".openclaw",
|
||||||
|
"workspace",
|
||||||
|
"skills",
|
||||||
|
"nordvpn-client",
|
||||||
|
"scripts",
|
||||||
|
"nordvpn-wireguard-helper.sh"
|
||||||
|
);
|
||||||
const DEFAULT_DNS_IPV4 = "103.86.96.100";
|
const DEFAULT_DNS_IPV4 = "103.86.96.100";
|
||||||
const DEFAULT_DNS_IPV6 = "2400:bb40:4444::100";
|
const DEFAULT_DNS_IPV6 = "2400:bb40:4444::100";
|
||||||
const CLIENT_IPV4 = "10.5.0.2";
|
const CLIENT_IPV4 = "10.5.0.2";
|
||||||
@@ -274,7 +283,8 @@ async function probeMacWireguard() {
|
|||||||
const wgPath = commandExists("wg");
|
const wgPath = commandExists("wg");
|
||||||
const wgQuickPath = commandExists("wg-quick");
|
const wgQuickPath = commandExists("wg-quick");
|
||||||
const wireguardGoPath = commandExists("wireguard-go");
|
const wireguardGoPath = commandExists("wireguard-go");
|
||||||
const sudoProbe = await runExec("sudo", ["-n", "true"]);
|
const helperPath = fileExists(MAC_WG_HELPER_PATH) ? MAC_WG_HELPER_PATH : null;
|
||||||
|
const sudoProbe = helperPath ? await runExec("sudo", ["-n", helperPath, "probe"]) : { ok: false };
|
||||||
let active = false;
|
let active = false;
|
||||||
let showRaw = "";
|
let showRaw = "";
|
||||||
let endpoint = "";
|
let endpoint = "";
|
||||||
@@ -293,6 +303,7 @@ async function probeMacWireguard() {
|
|||||||
wgPath: wgPath || null,
|
wgPath: wgPath || null,
|
||||||
wgQuickPath: wgQuickPath || null,
|
wgQuickPath: wgQuickPath || null,
|
||||||
wireguardGoPath: wireguardGoPath || null,
|
wireguardGoPath: wireguardGoPath || null,
|
||||||
|
helperPath,
|
||||||
dependenciesReady: Boolean(wgPath && wgQuickPath && wireguardGoPath),
|
dependenciesReady: Boolean(wgPath && wgQuickPath && wireguardGoPath),
|
||||||
sudoReady: sudoProbe.ok,
|
sudoReady: sudoProbe.ok,
|
||||||
interfaceName: MAC_WG_INTERFACE,
|
interfaceName: MAC_WG_INTERFACE,
|
||||||
@@ -390,7 +401,7 @@ function buildStateSummary(installProbe, ipInfo) {
|
|||||||
recommendedAction = installProbe.tokenAvailable
|
recommendedAction = installProbe.tokenAvailable
|
||||||
? installProbe.wireguard.sudoReady
|
? installProbe.wireguard.sudoReady
|
||||||
? "Use token-based WireGuard automation on macOS."
|
? "Use token-based WireGuard automation on macOS."
|
||||||
: "WireGuard tooling and token are available, but connect/disconnect require non-interactive sudo for wg-quick. Authorize sudo for wg-quick, then rerun login/connect."
|
: `WireGuard tooling and token are available, but connect/disconnect require non-interactive sudo for ${MAC_WG_HELPER_PATH}. Allow that helper in sudoers, then rerun login/connect.`
|
||||||
: `Set NORDVPN_TOKEN, NORDVPN_TOKEN_FILE, or place the token at ${DEFAULT_TOKEN_FILE} for automated macOS NordLynx/WireGuard connects.`;
|
: `Set NORDVPN_TOKEN, NORDVPN_TOKEN_FILE, or place the token at ${DEFAULT_TOKEN_FILE} for automated macOS NordLynx/WireGuard connects.`;
|
||||||
} else if (installProbe.platform === "darwin" && installProbe.appInstalled) {
|
} else if (installProbe.platform === "darwin" && installProbe.appInstalled) {
|
||||||
controlMode = "app-manual";
|
controlMode = "app-manual";
|
||||||
@@ -436,6 +447,7 @@ function buildStateSummary(installProbe, ipInfo) {
|
|||||||
wgPath: installProbe.wireguard.wgPath,
|
wgPath: installProbe.wireguard.wgPath,
|
||||||
wgQuickPath: installProbe.wireguard.wgQuickPath,
|
wgQuickPath: installProbe.wireguard.wgQuickPath,
|
||||||
wireguardGoPath: installProbe.wireguard.wireguardGoPath,
|
wireguardGoPath: installProbe.wireguard.wireguardGoPath,
|
||||||
|
helperPath: installProbe.wireguard.helperPath,
|
||||||
authCache: installProbe.wireguard.authCache,
|
authCache: installProbe.wireguard.authCache,
|
||||||
lastConnection: installProbe.wireguard.lastConnection,
|
lastConnection: installProbe.wireguard.lastConnection,
|
||||||
}
|
}
|
||||||
@@ -769,12 +781,12 @@ async function connectViaCli(cliPath, target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function runSudoWireguard(installProbe, action) {
|
async function runSudoWireguard(installProbe, action) {
|
||||||
const wgQuickPath = installProbe.wireguard && installProbe.wireguard.wgQuickPath;
|
const helperPath = installProbe.wireguard && installProbe.wireguard.helperPath;
|
||||||
if (!wgQuickPath) throw new Error("wg-quick is not installed.");
|
if (!helperPath) throw new Error(`WireGuard helper is missing at ${MAC_WG_HELPER_PATH}.`);
|
||||||
if (!installProbe.wireguard.sudoReady) {
|
if (!installProbe.wireguard.sudoReady) {
|
||||||
throw new Error("Non-interactive sudo is required for macOS WireGuard connect/disconnect. Authorize sudo first, then retry.");
|
throw new Error(`Non-interactive sudo is required for macOS WireGuard connect/disconnect. Allow sudo for ${MAC_WG_HELPER_PATH}, then rerun login/connect.`);
|
||||||
}
|
}
|
||||||
return runExec("sudo", ["-n", "env", `PATH=${process.env.PATH || ""}`, wgQuickPath, action, WG_CONFIG_PATH]);
|
return runExec("sudo", ["-n", helperPath, action]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function connectViaMacWireguard(installProbe, target) {
|
async function connectViaMacWireguard(installProbe, target) {
|
||||||
|
|||||||
24
skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh
Executable file
24
skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ACTION="${1:-}"
|
||||||
|
case "$ACTION" in
|
||||||
|
probe|up|down)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: nordvpn-wireguard-helper.sh [probe|up|down]" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
WG_QUICK="/opt/homebrew/bin/wg-quick"
|
||||||
|
WG_CONFIG="/Users/stefano/.nordvpn-client/wireguard/nordvpnctl.conf"
|
||||||
|
PATH="/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
if [ "$ACTION" = "probe" ]; then
|
||||||
|
test -x "$WG_QUICK"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$WG_QUICK" "$ACTION" "$WG_CONFIG"
|
||||||
Reference in New Issue
Block a user