fix(awg): infer wg0 iface from wg0.conf; chmod600 before syncconf

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Андрей Бобырев
2026-05-15 01:09:09 +03:00
parent 6faf696650
commit 65e10ae625
2 changed files with 22 additions and 3 deletions

View File

@@ -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`**.
---
## Лицензия

View File

@@ -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 = "";
}