diff --git a/README.md b/README.md index c12d252..145de8f 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,10 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scrip Если на хосте уже что-то слушает **TCP 80**, установщик сообщит об этом и, при дефолтном **`LANDING_PORT=80`**, сам попробует другой свободный порт (обычно начиная с **8081**). Либо явно: **`LANDING_PORT=8083`**, либо **`SKIP_LANDING=1`**. +### AmneziaWG Legacy: удаление клиента не срабатывает (`wg0.conf is world accessible` / `No such device`) + +Панель синхронизирует живой интерфейс через **`wg-quick strip` + `syncconf`**. У Legacy конфиг часто **`/opt/amnezia/awg/wg0.conf`**, интерфейс — **`wg0`**, не **`awg0`**. В актуальном коде интерфейс выводится из **имени файла** (**`wg0.conf` → `wg0`**). Если путь другой — задайте в профиле **`AWG_IFACE`** / в **`AWG_PROFILES`** поле **`iface`**. Предупреждение про world-accessible: перед применением конфига файл на стороне контейнера выставляется в **`chmod 600`**. + --- ## Лицензия diff --git a/server.js b/server.js index 246d62d..5d80aba 100644 --- a/server.js +++ b/server.js @@ -707,11 +707,23 @@ function peerUsesWarp(peer, selectedSet) { return false; } +/** Имя интерфейса для `awg|wg syncconf` и `… show`: при Legacy часто `/…/wg0.conf`, а в env остаётся дефолт `awg0`. */ +function resolveTunnelIface(profile) { + const cp = String(profile.confPath || ""); + const m = cp.match(/\/([^/.]+)\.conf$/); + if (m) { + const stem = m[1]; + const low = stem.toLowerCase(); + if (low === "wg0" || low === "awg0") return stem; + } + return profile.iface; +} + function createRuntime(profile) { const container = profile.container; const confPath = profile.confPath; const clientsPath = profile.clientsPath; - const iface = profile.iface; + const iface = resolveTunnelIface(profile); const wgBinary = profile.wgBinary; const pskPath = profile.pskPath; @@ -749,7 +761,9 @@ function createRuntime(profile) { async function applySyncconf() { await dockerExec( - `wg-quick strip '${confPath}' > /tmp/wg-admin-strip.conf && ${wgBinary} syncconf ${iface} /tmp/wg-admin-strip.conf` + `chmod 600 '${confPath}' 2>/dev/null || true` + + `; wg-quick strip '${confPath}' > /tmp/wg-admin-strip.conf` + + ` && ${wgBinary} syncconf ${iface} /tmp/wg-admin-strip.conf` ); } @@ -776,6 +790,7 @@ function createRuntime(profile) { return { profile, + tunnelIface: iface, dockerExec, dockerReadFile, dockerWriteFile, @@ -1741,7 +1756,7 @@ app.get("/api/clients", requireAuth, async (req, res) => { try { let wgShow = ""; try { - wgShow = await rt.dockerExec(`${rt.profile.wgBinary} show ${rt.profile.iface}`); + wgShow = await rt.dockerExec(`${rt.profile.wgBinary} show ${rt.tunnelIface}`); } catch { wgShow = ""; }