mirror of
https://github.com/andrey271192/amnezia_web.git
synced 2026-09-20 14:41:59 +00:00
feat(community): probe AWG conf/clients paths in autodetect
Auto AWG_PROFILES now docker-execs each amnezia-awg* container to pick wg0.conf vs awg0.conf, fallback find, clientsTable siblings. Fixes legacy layouts where awg0.conf does not exist. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "amnezia-admin",
|
"name": "amnezia-admin",
|
||||||
"version": "1.2.13",
|
"version": "1.2.14",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "amnezia_web — базовая панель AmneziaWG (FREE: просмотр и удаление клиентов; полная версия — PRO).",
|
"description": "amnezia_web — базовая панель AmneziaWG (FREE: просмотр и удаление клиентов; полная версия — PRO).",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
83
server.js
83
server.js
@@ -442,13 +442,63 @@ fi
|
|||||||
`.trim();
|
`.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Пути `conf` / `clientsTable` внутри контейнера Amnezia: не всегда `awg0.conf`
|
||||||
|
* в `/opt/amnezia/awg/` (legacy — `wg0.conf`, второй сервис — подкаталог `awg2`).
|
||||||
|
*/
|
||||||
|
function probeAmneziaTunnelPaths(containerName) {
|
||||||
|
const safe = /^[a-zA-Z0-9_.-]+$/.test(containerName) ? containerName : "";
|
||||||
|
if (!safe) return null;
|
||||||
|
const script = `
|
||||||
|
set -eu
|
||||||
|
CONF=""
|
||||||
|
for f in "/opt/amnezia/awg/awg0.conf" "/opt/amnezia/awg/wg0.conf" "/opt/amnezia/awg2/awg0.conf" "/opt/amnezia/awg2/wg0.conf" "/etc/wireguard/wg0.conf" "/etc/wireguard/awg0.conf"; do
|
||||||
|
if [ -f "$f" ]; then CONF="$f"; break; fi
|
||||||
|
done
|
||||||
|
if [ -z "$CONF" ]; then
|
||||||
|
CONF="$(find /opt/amnezia /etc/wireguard -maxdepth 10 \\( -name 'wg0.conf' -o -name 'awg0.conf' \\) 2>/dev/null | head -n 1)"
|
||||||
|
fi
|
||||||
|
[ -n "$CONF" ] && [ -f "$CONF" ] || exit 10
|
||||||
|
DIR="$(dirname "$CONF")"
|
||||||
|
CLIENTS=""
|
||||||
|
for c in "$DIR/clientsTable" "/opt/amnezia/awg/clientsTable" "/opt/amnezia/awg2/clientsTable"; do
|
||||||
|
if [ -f "$c" ]; then CLIENTS="$c"; break; fi
|
||||||
|
done
|
||||||
|
[ -n "$CLIENTS" ] || exit 11
|
||||||
|
PSK=""
|
||||||
|
for p in "$DIR/wireguard_psk.key" "/opt/amnezia/awg/wireguard_psk.key"; do
|
||||||
|
if [ -f "$p" ]; then PSK="$p"; break; fi
|
||||||
|
done
|
||||||
|
printf '%s|%s|%s\\n' "$CONF" "$CLIENTS" "$PSK"
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const out = execFileSync("docker", ["exec", containerName, "sh", "-c", script], {
|
||||||
|
stdio: ["ignore", "pipe", "ignore"],
|
||||||
|
encoding: "utf8",
|
||||||
|
timeout: 12000,
|
||||||
|
}).trimEnd();
|
||||||
|
const line = (out.split(/\r?\n/).find((l) => l.includes("|")) ?? "").trim();
|
||||||
|
const [confPath = "", clientsPath = "", pskPath = ""] = line.split("|").map((s) => s.trim());
|
||||||
|
if (!confPath || !clientsPath) return null;
|
||||||
|
return {
|
||||||
|
confPath,
|
||||||
|
clientsPath,
|
||||||
|
...(pskPath ? { pskPath } : {}),
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Авто-обнаружение профилей `amnezia-awg*` до старта PRO `install.sh`.
|
* Авто-обнаружение профилей `amnezia-awg*` до старта PRO `install.sh`.
|
||||||
* Возвращает JSON, готовый для `-e AWG_PROFILES=...` или пустую строку,
|
* Возвращает JSON для `-e AWG_PROFILES=...` или пустую строку при сбое.
|
||||||
* если найден ровно один контейнер (fallback panel-side тогда корректен).
|
|
||||||
*
|
*
|
||||||
* Метки берём из публичных портов (`443/udp` → "AmneziaWG (443)"), порядок —
|
* Для каждого контейнера ищутся реальные `confPath`/`clientsTable` (не только дефолт `awg0.conf`).
|
||||||
* по возрастанию первого UDP-порта (если совпадает — по имени).
|
*
|
||||||
|
* Если запущен ровно один `amnezia-awg*`, профиль один — переключатель в UI может не понадаться,
|
||||||
|
* но верные пути всё равно попадают в панель.
|
||||||
*/
|
*/
|
||||||
function autoDiscoverAwgProfilesJson() {
|
function autoDiscoverAwgProfilesJson() {
|
||||||
if (envTruthy(process.env.COMMUNITY_DISABLE_AWG_PROFILES_AUTODETECT)) return "";
|
if (envTruthy(process.env.COMMUNITY_DISABLE_AWG_PROFILES_AUTODETECT)) return "";
|
||||||
@@ -462,7 +512,7 @@ function autoDiscoverAwgProfilesJson() {
|
|||||||
.toString()
|
.toString()
|
||||||
.trim();
|
.trim();
|
||||||
const names = namesOut.split("\n").map((x) => x.trim()).filter(Boolean);
|
const names = namesOut.split("\n").map((x) => x.trim()).filter(Boolean);
|
||||||
if (names.length < 2) return "";
|
if (names.length === 0) return "";
|
||||||
const entries = names
|
const entries = names
|
||||||
.map((name) => {
|
.map((name) => {
|
||||||
let firstUdp = null;
|
let firstUdp = null;
|
||||||
@@ -493,9 +543,26 @@ function autoDiscoverAwgProfilesJson() {
|
|||||||
firstUdp: firstUdp ?? 1 << 30,
|
firstUdp: firstUdp ?? 1 << 30,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.firstUdp - b.firstUdp || a.container.localeCompare(b.container))
|
.sort((a, b) => a.firstUdp - b.firstUdp || a.container.localeCompare(b.container));
|
||||||
.map(({ id, label, container }) => ({ id, label, container }));
|
const resolved = [];
|
||||||
return JSON.stringify(entries);
|
for (const row of entries) {
|
||||||
|
const probed = probeAmneziaTunnelPaths(row.container);
|
||||||
|
if (!probed) {
|
||||||
|
console.warn(
|
||||||
|
`autoDiscover AWG: в контейнере ${row.container} не найдены conf/clientsTable — пропуск авто-AWG_PROFILES`,
|
||||||
|
);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
resolved.push({
|
||||||
|
id: row.id,
|
||||||
|
label: row.label,
|
||||||
|
container: row.container,
|
||||||
|
confPath: probed.confPath,
|
||||||
|
clientsPath: probed.clientsPath,
|
||||||
|
...(probed.pskPath ? { pskPath: probed.pskPath } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return JSON.stringify(resolved);
|
||||||
} catch {
|
} catch {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user