From cb230fe50e2a41b7f486a87a70a5de8a781cf9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=B1=D1=8B=D1=80=D0=B5=D0=B2=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B4=D1=80=D0=B5=D0=B9?= Date: Fri, 23 Oct 2026 01:44:20 +0300 Subject: [PATCH] docs: split old Notes into 09.3.N, fix 00 (news bot), move check scripts to scripts/checks Co-Authored-By: Claude Opus 5.5 --- .gitignore | 1 + 00. НАЧНИ ОТСЮДА.md | 4 +- 09. История и грабли.md | 1 + 09.3 Старые исправления июня 2026.md | 17 ++++++ ... Canonical public amnezia_web-PRO 06.06.md | 17 ++++++ ...10 Sync app-created Amnezia users 21.06.md | 23 ++++++++ ...1 Fix legacy clientsTable formats 21.06.md | 17 ++++++ ...Fix Amnezia source auto-discovery 22.06.md | 20 +++++++ 09.3.13 Fix awg binary not found 22.06.md | 15 +++++ ... Canonical amnezia_web-PRO status 21.06.md | 20 +++++++ 09.3.3 Fix AWG auto profiles 21.06.md | 22 +++++++ ....4 Fix stale AWG profile snapshot 21.06.md | 9 +++ ...Client import from Amnezia backup 21.06.md | 24 ++++++++ 09.3.6 Fix duplicate AWG instances 21.06.md | 22 +++++++ 09.3.7 Fix AWG instance labels 21.06.md | 15 +++++ 09.3.8 Fix clients selected profile 21.06.md | 18 ++++++ ....9 Fix peers missing clientsTable 21.06.md | 18 ++++++ scripts/checks/audit2.py | 53 +++++++++++++++++ scripts/checks/audit_conf.py | 56 ++++++++++++++++++ scripts/checks/check_conf.py | 38 ++++++++++++ scripts/checks/check_garbage.py | 30 ++++++++++ scripts/checks/test_create.py | 59 +++++++++++++++++++ 22 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 09.3 Старые исправления июня 2026.md create mode 100644 09.3.1 Canonical public amnezia_web-PRO 06.06.md create mode 100644 09.3.10 Sync app-created Amnezia users 21.06.md create mode 100644 09.3.11 Fix legacy clientsTable formats 21.06.md create mode 100644 09.3.12 Fix Amnezia source auto-discovery 22.06.md create mode 100644 09.3.13 Fix awg binary not found 22.06.md create mode 100644 09.3.2 Canonical amnezia_web-PRO status 21.06.md create mode 100644 09.3.3 Fix AWG auto profiles 21.06.md create mode 100644 09.3.4 Fix stale AWG profile snapshot 21.06.md create mode 100644 09.3.5 Client import from Amnezia backup 21.06.md create mode 100644 09.3.6 Fix duplicate AWG instances 21.06.md create mode 100644 09.3.7 Fix AWG instance labels 21.06.md create mode 100644 09.3.8 Fix clients selected profile 21.06.md create mode 100644 09.3.9 Fix peers missing clientsTable 21.06.md create mode 100644 scripts/checks/audit2.py create mode 100644 scripts/checks/audit_conf.py create mode 100644 scripts/checks/check_conf.py create mode 100644 scripts/checks/check_garbage.py create mode 100644 scripts/checks/test_create.py diff --git a/.gitignore b/.gitignore index b1d9ed3..16278c9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ npm-debug.log* *.swp .env .env.* +Новости/ diff --git a/00. НАЧНИ ОТСЮДА.md b/00. НАЧНИ ОТСЮДА.md index 35b5431..116848a 100644 --- a/00. НАЧНИ ОТСЮДА.md +++ b/00. НАЧНИ ОТСЮДА.md @@ -1,8 +1,10 @@ # 00. НАЧНИ ОТСЮДА — amnezia_web-PRO **Промпт для нового чата:** -> Проект «Открытые проекты/amnezia_web-PRO» — полностью открытая веб-панель Amnezia (Node, `server.js` + `public/`). Закрытой версии нет (старая — в `Архив/amnezia_web-PRO_test`). Прочитай `PROJECT_INDEX.md` и `09. История и грабли`. Тесты — на school-friends (сервер) и school-it-kruzhok (клиент) через svault. Релиз: тег + GitHub API, затем Gitea, Notes, новость в @PCAdministration ботом PCA_jarvis_bot (токен `TG_BOT_TOKEN` в `~/jarvis-ru-windows/.env`). +> Проект «Открытые проекты/amnezia_web-PRO» — полностью открытая веб-панель Amnezia (Node, `server.js` + `public/`). Закрытой версии нет (старая — в `Архив/amnezia_web-PRO_test`). Прочитай `PROJECT_INDEX.md` и `09. История и грабли`. Тесты — на school-friends (сервер) и school-it-kruzhok (клиент) через svault. Релиз: тег + GitHub API, затем Gitea, Notes, новость в группу PCA, тема «Новости» (chat_id -1003902709196, message_thread_id=131) ботом @PCAdmin27_bot (токен `TELEGRAM_MOD_BOT_TOKEN` в «Закрытые продукты/home_Friends_It/ДОСТУПЫ.md»); PCA_jarvis_bot не использовать. Gitea — pull-зеркало, обновлять mirror-sync. ## Оглавление - `PROJECT_INDEX.md` — что где лежит, установка - `09. История и грабли` — оглавление записей 09.N +- `scripts/checks/` — проверки парка AWG (запускать внутри контейнера панели, читают /app/data/data.json) +- `Новости/` — тексты новостей релизов (не в git) diff --git a/09. История и грабли.md b/09. История и грабли.md index eebdfa2..7842685 100644 --- a/09. История и грабли.md +++ b/09. История и грабли.md @@ -2,4 +2,5 @@ - [09.1 Версия 1.3.0 — протоколы с сайта, каскад, домен, тема](<09.1 Версия 1.3.0 — протоколы с сайта, каскад, домен, тема.md>) — 23.10.2026 - [09.2 Версия 1.4.0 — Xray VLESS, всё открыто](<09.2 Версия 1.4.0 — Xray VLESS, всё открыто.md>) — 23.10.2026 +- [09.3 Старые исправления июня 2026](<09.3 Старые исправления июня 2026.md>) — 13 частей 09.3.N, перенесены из Notes 23.10.2026 - 04.10.2026 — проект переехал в папку-группу; код не менялся. diff --git a/09.3 Старые исправления июня 2026.md b/09.3 Старые исправления июня 2026.md new file mode 100644 index 0000000..9b0216f --- /dev/null +++ b/09.3 Старые исправления июня 2026.md @@ -0,0 +1,17 @@ +# 09.3 Старые исправления июня 2026 + +Оглавление частей: заметки из Notes до регламента (июнь–июль 2026), по одной на исправление. + +- [09.3.1 Canonical public amnezia_web-PRO 06.06](<09.3.1 Canonical public amnezia_web-PRO 06.06.md>) +- [09.3.2 Canonical amnezia_web-PRO status 21.06](<09.3.2 Canonical amnezia_web-PRO status 21.06.md>) +- [09.3.3 Fix AWG auto profiles 21.06](<09.3.3 Fix AWG auto profiles 21.06.md>) +- [09.3.4 Fix stale AWG profile snapshot 21.06](<09.3.4 Fix stale AWG profile snapshot 21.06.md>) +- [09.3.5 Client import from Amnezia backup 21.06](<09.3.5 Client import from Amnezia backup 21.06.md>) +- [09.3.6 Fix duplicate AWG instances 21.06](<09.3.6 Fix duplicate AWG instances 21.06.md>) +- [09.3.7 Fix AWG instance labels 21.06](<09.3.7 Fix AWG instance labels 21.06.md>) +- [09.3.8 Fix clients selected profile 21.06](<09.3.8 Fix clients selected profile 21.06.md>) +- [09.3.9 Fix peers missing clientsTable 21.06](<09.3.9 Fix peers missing clientsTable 21.06.md>) +- [09.3.10 Sync app-created Amnezia users 21.06](<09.3.10 Sync app-created Amnezia users 21.06.md>) +- [09.3.11 Fix legacy clientsTable formats 21.06](<09.3.11 Fix legacy clientsTable formats 21.06.md>) +- [09.3.12 Fix Amnezia source auto-discovery 22.06](<09.3.12 Fix Amnezia source auto-discovery 22.06.md>) +- [09.3.13 Fix awg binary not found 22.06](<09.3.13 Fix awg binary not found 22.06.md>) diff --git a/09.3.1 Canonical public amnezia_web-PRO 06.06.md b/09.3.1 Canonical public amnezia_web-PRO 06.06.md new file mode 100644 index 0000000..3c03cfa --- /dev/null +++ b/09.3.1 Canonical public amnezia_web-PRO 06.06.md @@ -0,0 +1,17 @@ +# 09.3.1 Canonical public amnezia_web-PRO 06.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +amnezia_web-PRO canonical public repo — 06.06 +Keep one public project: https://github.com/andrey271192/amnezia_web-PRO +Install +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash +Defaults +Fresh login: admin +Fresh password: admin +Change password after first login. +GitHub +Repo is public. +Private download flow removed. +Separate deploy bundle removed from active docs and notes. +Commit: 05e6d00 docs: make pro repo public install source. diff --git a/09.3.10 Sync app-created Amnezia users 21.06.md b/09.3.10 Sync app-created Amnezia users 21.06.md new file mode 100644 index 0000000..8d46548 --- /dev/null +++ b/09.3.10 Sync app-created Amnezia users 21.06.md @@ -0,0 +1,23 @@ +# 09.3.10 Sync app-created Amnezia users 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: dfeabe0 feat: sync app-created peers into clients table +Version: v1.2.36 +Задача +Клиенты уже были созданы в приложении Amnezia. Их нужно подтянуть в веб-панель, а не создавать заново. +Решение +Добавлена кнопка Пользователи → Подтянуть из awg0.conf. +POST /api/clients/sync-peers берёт активные [Peer] текущего инстанса и создаёт недостающие строки clientsTable. +VPN-конфиг не пересоздаётся, контейнеры клиентов не трогаются. +Имена создаются как Клиент IP или Peer KEY, потом можно переименовать. +Экспорт .conf появится после импорта клиентского .conf, потому приватный ключ клиента есть только в приложении. +Команда +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Потом Ctrl+F5 → выбрать Инстанс → Пользователи → Подтянуть из awg0.conf. +Проверено +node --check server.js +node --check public/app.js +bash -n scripts/*.sh +npm audit --audit-level=moderate: 0 vulnerabilities +git diff --check diff --git a/09.3.11 Fix legacy clientsTable formats 21.06.md b/09.3.11 Fix legacy clientsTable formats 21.06.md new file mode 100644 index 0000000..54344ad --- /dev/null +++ b/09.3.11 Fix legacy clientsTable formats 21.06.md @@ -0,0 +1,17 @@ +# 09.3.11 Fix legacy clientsTable formats 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: 4e6ab2d fix: parse legacy clients table formats +Version: v1.2.37 +Причина +Старые клиенты могли не подтягиваться, если clientsTable не был массивом [{clientId,userData}], а имел object/map/nested формат другой версии Amnezia. +Исправлено +parseClientsTable поддерживает array, object map, nested clients/users/rows/items/data/clientList/clientsTable. +clientRowId понимает clientId/id/publicKey/public_key/key/client_id и вложенные userData поля. +Добавлен GET /api/clients/source-report для диагностики источников без полных ключей. +Команда +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Потом Ctrl+F5 → выбрать Инстанс → Пользователи → Подтянуть из awg0.conf. +Если всё равно пусто +Открыть в браузере после логина: /api/clients/source-report?profileId=awg и /api/clients/source-report?profileId=awg2 diff --git a/09.3.12 Fix Amnezia source auto-discovery 22.06.md b/09.3.12 Fix Amnezia source auto-discovery 22.06.md new file mode 100644 index 0000000..724b810 --- /dev/null +++ b/09.3.12 Fix Amnezia source auto-discovery 22.06.md @@ -0,0 +1,20 @@ +# 09.3.12 Fix Amnezia source auto-discovery 22.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: b360095 fix: auto-discover amnezia client sources +Version: v1.2.38 +Root cause +Amnezia installs can keep old clients in /opt/amnezia/awg/wg0.conf, while profile pointed to /opt/amnezia/awg/awg0.conf. clientsTable can also live in /opt/amnezia/wireguard/clientsTable or have non-array format. +Fix +Runtime now scans config candidates: awg0.conf, wg0.conf, wireguard/wg0.conf. +Chooses config with max [Peer] count. +Runtime scans clientsTable candidates: awg/clientsTable and wireguard/clientsTable. +Chooses clientsTable with max parsed client count. +iface is inferred from selected config filename. +source-report shows resolved confPath/clientsPath/iface. +Command +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Then Ctrl+F5 → select Instance → Users → Pull from awg0.conf. +Source +Amnezia issue #1615 mentions manual flow with /opt/amnezia/awg/wg0.conf and clientsTable; issue #2238 confirms clientsTable field variance. diff --git a/09.3.13 Fix awg binary not found 22.06.md b/09.3.13 Fix awg binary not found 22.06.md new file mode 100644 index 0000000..84d46b3 --- /dev/null +++ b/09.3.13 Fix awg binary not found 22.06.md @@ -0,0 +1,15 @@ +# 09.3.13 Fix awg binary not found 22.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: 8e5d51a fix: auto-detect wg binary in containers +Version: v1.2.39 +Symptom +При добавлении/подтягивании старых .conf ошибка: sh: awg: not found. В amneziawg контейнере awg binary отсутствует. +Fix +Runtime auto-detects binary inside container: preferred wgBinary, then wg for wg0.conf, then awg, then wg. +show/pubkey/genkey/syncconf use resolved binary, not hardcoded profile.wgBinary. +source-report and /api/clients expose resolved wgBinary. +Command +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Then Ctrl+F5 → Instance → Users → Pull from awg0.conf. diff --git a/09.3.2 Canonical amnezia_web-PRO status 21.06.md b/09.3.2 Canonical amnezia_web-PRO status 21.06.md new file mode 100644 index 0000000..a0001ec --- /dev/null +++ b/09.3.2 Canonical amnezia_web-PRO status 21.06.md @@ -0,0 +1,20 @@ +# 09.3.2 Canonical amnezia_web-PRO status 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Важно: amnezia_web-PRO_test — отдельный продукт/тестовая ветка. Canonical public product сейчас: amnezia_web-PRO. +GitHub: https://github.com/andrey271192/amnezia_web-PRO +Local: /Users/andrejbobyrev/andrey271192-repos/amnezia_web-PRO +Last pushed commit: c202f0b — chore: add npm lockfile +Правило +amnezia_web-PRO — основной публичный продукт. +amnezia_web-PRO_test — отдельный тестовый продукт, не смешивать с public PRO. +amnezia-web-pro-deploy — legacy/старый deploy repo, не использовать как основной продукт. +Install +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash +Defaults +Fresh login: admin +Fresh password: admin +Change password after first login. +AWG issue from client +Install-check видит два контейнера: amnezia-awg2 и amnezia-awg. Если веб показывает только awg2, причина в runtime-discovery/cache/UI-filter, не в Docker. Надо проверить конкретный VPS: docker ps, panel API/status, logs, затем исправить отображение обоих AWG profiles без ручного AWG_PROFILES. diff --git a/09.3.3 Fix AWG auto profiles 21.06.md b/09.3.3 Fix AWG auto profiles 21.06.md new file mode 100644 index 0000000..883cc4c --- /dev/null +++ b/09.3.3 Fix AWG auto profiles 21.06.md @@ -0,0 +1,22 @@ +# 09.3.3 Fix AWG auto profiles 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Repo: https://github.com/andrey271192/amnezia_web-PRO +Commit: cbc20a1 — fix: auto-detect awg profiles on install +Что исправлено +Переустановка из GitHub работает для /opt/amnezia-admin без .git. +Установщик сохраняет текущий порт панели. +Установщик сохраняет текущий Docker volume /data. +Перед заменой /opt/amnezia-admin создаётся backup папки. +Если найден один контейнер amnezia-awg*, он становится AWG_CONTAINER. +Если найдено 2+ контейнера amnezia-awg*, AWG_PROFILES создаётся автоматически и сохраняется в /root/amnezia-admin.awg-profiles.json. +Dockerfile использует npm ci по package-lock.json. +Что сказать пользователю +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash +После установки: обновить страницу Ctrl+F5. AWG контейнеры не удаляются и не пересоздаются. +Проверено +bash -n scripts/install.sh +bash -n scripts/uninstall.sh +node --check server.js +npm audit --audit-level=moderate diff --git a/09.3.4 Fix stale AWG profile snapshot 21.06.md b/09.3.4 Fix stale AWG profile snapshot 21.06.md new file mode 100644 index 0000000..147187b --- /dev/null +++ b/09.3.4 Fix stale AWG profile snapshot 21.06.md @@ -0,0 +1,9 @@ +# 09.3.4 Fix stale AWG profile snapshot 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: 8ba2a26 — fix: refresh stale awg profile snapshots +Причина повтора бага: старый /root/amnezia-admin.awg-profiles.json мог содержать один профиль. Installer восстанавливал его и не пересобирал profiles по двум контейнерам. +Теперь если контейнеров amnezia-awg* два или больше, а восстановленный AWG_PROFILES содержит меньше двух container, installer автоматически пересобирает profiles и перезаписывает snapshot. +rm -f /root/amnezia-admin.awg-profiles.json +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s) | sudo env SKIP_LANDING=1 bash diff --git a/09.3.5 Client import from Amnezia backup 21.06.md b/09.3.5 Client import from Amnezia backup 21.06.md new file mode 100644 index 0000000..c9f35a6 --- /dev/null +++ b/09.3.5 Client import from Amnezia backup 21.06.md @@ -0,0 +1,24 @@ +# 09.3.5 Client import from Amnezia backup 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Project: amnezia_web-PRO +Repo: https://github.com/andrey271192/amnezia_web-PRO +Commit: cff27e2 feat: import clients from amnezia configs +Что добавлено +В панели появился блок Импорт клиента. +Можно вставить готовый клиентский .conf или JSON backup Amnezia, если внутри есть текстовый .conf. +Если peer уже есть в awg0.conf, дубль не создаётся: восстанавливается/обновляется строка clientsTable. +Если peer отсутствует, он добавляется в текущий выбранный Инстанс. +Исходный .conf сохраняется в userData.last_config, чтобы дальше работали экспорт и управление из веба. +Добавлена защита: импортируемый .conf должен относиться к текущему серверу/инстансу по PublicKey сервера. +Команда переустановки для пользователя +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Проверено +node --check server.js +node --check public/app.js +bash -n для всех scripts/*.sh +npm audit --audit-level=moderate: 0 vulnerabilities +git diff --check +Что сказать пользователю +Обновите панель командой выше, зайдите в веб, выберите нужный Инстанс и откройте блок Импорт клиента. Вставьте экспортированный клиентский .conf из приложения Amnezia или backup, где внутри есть этот .conf. После импорта клиент появится в таблице, а старые peer-дубли создаваться не будут. diff --git a/09.3.6 Fix duplicate AWG instances 21.06.md b/09.3.6 Fix duplicate AWG instances 21.06.md new file mode 100644 index 0000000..a8b27c1 --- /dev/null +++ b/09.3.6 Fix duplicate AWG instances 21.06.md @@ -0,0 +1,22 @@ +# 09.3.6 Fix duplicate AWG instances 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Project: amnezia_web-PRO +Commit: 8c67d7d fix: dedupe duplicate awg instances +Version: v1.2.32 +Причина +После переустановки один и тот же AWG контейнер мог попасть в список дважды: из AWG_PROFILES и из saved managed instances. Старый dedup был только по id, поэтому при разных id веб показывал две одинаковые карточки. +Исправлено +Dedup профилей по container + confPath + iface + clientsPath. +/api/instances дополнительно дедупит runtime target после auto-resolve контейнера. +load/save managed profiles чистит дубли из instances.json. +Docs обновлены: раздел Инстансы задублировались. +Команда для пользователя +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +После установки: Ctrl+F5 в браузере. +Проверено +node --check server.js +node --check public/app.js +npm audit --audit-level=moderate: 0 vulnerabilities +git diff --check diff --git a/09.3.7 Fix AWG instance labels 21.06.md b/09.3.7 Fix AWG instance labels 21.06.md new file mode 100644 index 0000000..88d5d53 --- /dev/null +++ b/09.3.7 Fix AWG instance labels 21.06.md @@ -0,0 +1,15 @@ +# 09.3.7 Fix AWG instance labels 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: a9a67af fix: show distinct awg instance labels +Version: v1.2.33 +Причина +У пользователя реально два контейнера: amnezia-awg2 и amnezia-awg. Порты и число клиентов разные, значит это не дубль. Но UI рисовал title по variant, поэтому обе карточки выглядели как AmneziaWG 2.0. +Исправлено +Карточка инстанса показывает profile label, а не только variant title. +Backend лучше определяет variant по profile/container/label до чтения конфига. +Docs уточнены: два разных контейнера с разными портами — нормальные два инстанса. +Команда +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Потом Ctrl+F5. diff --git a/09.3.8 Fix clients selected profile 21.06.md b/09.3.8 Fix clients selected profile 21.06.md new file mode 100644 index 0000000..2369131 --- /dev/null +++ b/09.3.8 Fix clients selected profile 21.06.md @@ -0,0 +1,18 @@ +# 09.3.8 Fix clients selected profile 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: cb5fca3 fix: load clients for selected profile +Version: v1.2.34 +Симптом +Переключатель Инстанс показывает правильный контейнер, но таблица Пользователи показывает клиентов от другого/старого инстанса. +Причина +Создание/экспорт уже передавали profileId явно, но /api/clients и операции таблицы опирались на cookie выбранного профиля. Cookie мог не примениться/устареть, поэтому список клиентов приходил не от выбранного инстанса. +Исправлено +GET /api/clients принимает явный profileId. +disable/enable/rename/delete/disconnect-date используют runtimeFromExportRequest и body.profileId. +Frontend передаёт profileId во все запросы таблицы клиентов. +Docs обновлены. +Команда +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Потом Ctrl+F5. diff --git a/09.3.9 Fix peers missing clientsTable 21.06.md b/09.3.9 Fix peers missing clientsTable 21.06.md new file mode 100644 index 0000000..42314e1 --- /dev/null +++ b/09.3.9 Fix peers missing clientsTable 21.06.md @@ -0,0 +1,18 @@ +# 09.3.9 Fix peers missing clientsTable 21.06 + +_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._ + +Commit: fd66b0a fix: show peers missing clients table +Version: v1.2.35 +Симптом +Инстанс выбран правильно, но старые клиенты не появляются в таблице Пользователи. +Причина +UI строил список только из clientsTable. У старых/созданных приложением клиентов peer может быть в awg0.conf, а запись clientsTable отсутствовать или иметь другой формат. +Исправлено +GET /api/clients теперь возвращает union clientsTable + Peer из awg0.conf. +Peer-only строки показываются как Peer xxxx… и помечаются missingClientTable. +Rename/date/disable/delete умеют работать с peer-only строками. +Для экспорта .conf всё равно нужен импорт клиентского .conf, потому приватный ключ клиента сервер не знает. +Команда +curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash +Потом Ctrl+F5. diff --git a/scripts/checks/audit2.py b/scripts/checks/audit2.py new file mode 100644 index 0000000..db660b8 --- /dev/null +++ b/scripts/checks/audit2.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Сверяем ПОДНЯТЫЕ интерфейсы с их собственными конфигами. + +Первый заход сравнивал wg0.conf с интерфейсом wg0, а в контейнере amnezia-awg +поднят awg0 — отсюда ложные «расхождения». +""" +import json, sys +sys.path.insert(0, "/app") +from managers.ssh_manager import SSHManager + +PROBE = r""" +for c in $(docker ps --format '{{.Names}}' 2>/dev/null | grep '^amnezia-' | grep -vE 'nginx|frontend|backend|landing|xray|socks|ipsec|openvpn'); do + for bin in awg wg; do + docker exec $c sh -c "command -v $bin >/dev/null" 2>/dev/null || continue + for i in $(docker exec $c sh -c "$bin show interfaces 2>/dev/null"); do + live=$(docker exec $c sh -c "$bin show $i peers 2>/dev/null | grep -c ." | tr -d '\n') + conf="" + for f in /opt/amnezia/awg/$i.conf /opt/amnezia/awg/awg0.conf /opt/amnezia/awg/wg0.conf; do + docker exec $c test -f $f 2>/dev/null && { conf=$f; break; } + done + [ -n "$conf" ] || { echo "$c $i live=$live конфиг=НЕ НАЙДЕН"; continue; } + infile=$(docker exec $c grep -c '^\[Peer\]' $conf 2>/dev/null | tr -d '\n') + echo "$c $i live=$live файл=$infile ($conf)" + done + done +done +""" + +d = json.load(open("/app/data/data.json")) +плохо = 0 +for s in d["servers"]: + try: + with SSHManager(s["host"], s.get("ssh_port", 22), s["username"], + password=s.get("password") or None, + private_key=s.get("private_key") or None, + connect_timeout=8) as ssh: + out, err, _ = ssh.run_command(PROBE, timeout=60) + строки = [x.strip() for x in (out or "").splitlines() if x.strip()] + if not строки: + print(" ? %-26s нет поднятых интерфейсов" % s["name"][:26]) + continue + for стр in строки: + беда = False + if "live=" in стр and "файл=" in стр: + l = int(стр.split("live=")[1].split()[0]) + f = int(стр.split("файл=")[1].split()[0]) + беда = (l != f) + плохо += 1 if беда else 0 + print(" %s %-26s %s" % ("!!" if беда else "ok", s["name"][:26], стр)) + except Exception as e: + плохо += 1 + print(" !! %-26s НЕ ДОСТУЧАЛСЯ: %s" % (s["name"][:26], str(e)[:60])) +print("\nрасхождений:", плохо) diff --git a/scripts/checks/audit_conf.py b/scripts/checks/audit_conf.py new file mode 100644 index 0000000..8ea686b --- /dev/null +++ b/scripts/checks/audit_conf.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Целостность конфигов awg по всему парку: склейки, финальный перевод строки, +проходит ли awg-quick strip и совпадает ли число пиров с живым интерфейсом.""" +import json, sys +sys.path.insert(0, "/app") +from managers.ssh_manager import SSHManager + +PROBE = r""" +for c in amnezia-awg2 amnezia-awg amnezia-awg31 amnezia-awg3 amnezia-awg-legacy; do + docker ps --format '{{.Names}}' 2>/dev/null | grep -qx $c || continue + for f in awg0.conf wg0.conf; do + p=/opt/amnezia/awg/$f + docker exec $c test -f $p 2>/dev/null || continue + glue=$(docker exec $c grep -c '/32\[Peer\]' $p 2>/dev/null | tr -d '\n') + end=$(docker exec $c sh -c "tail -c 1 $p | od -An -c | tr -d ' \n'") + peers=$(docker exec $c grep -c '^\[Peer\]' $p 2>/dev/null | tr -d '\n') + mode=$(docker exec $c stat -c %a $p 2>/dev/null | tr -d '\n') + bin=wg; iface=wg0 + case $f in awg0.conf) bin=awg; iface=awg0;; esac + if docker exec $c sh -c "$bin-quick strip $p > /dev/null 2>&1"; then strip=ok; else strip=СБОЙ; fi + live=$(docker exec $c sh -c "$bin show $iface peers 2>/dev/null | grep -c ." | tr -d '\n') + echo "$c/$f peers=$peers live=$live glue=$glue end=$end mode=$mode strip=$strip" + done +done +""" + +d = json.load(open("/app/data/data.json")) +беда = 0 +for s in d["servers"]: + try: + with SSHManager(s["host"], s.get("ssh_port", 22), s["username"], + password=s.get("password") or None, + private_key=s.get("private_key") or None, + connect_timeout=8) as ssh: + out, err, _ = ssh.run_command(PROBE, timeout=60) + строки = [x.strip() for x in (out or "").splitlines() if x.strip()] + if not строки: + print(" ? %-26s нет контейнеров awg (%s)" % (s["name"][:26], (err or "")[:40])) + continue + for стр in строки: + плохо = ("glue=0" not in стр) or ("strip=ok" not in стр) or ("end=\\n" not in стр) + if "peers=" in стр and "live=" in стр: + try: + p = int(стр.split("peers=")[1].split()[0]) + l = int(стр.split("live=")[1].split()[0]) + if p != l: + плохо = True + стр += " ← файл и интерфейс расходятся" + except Exception: + pass + беда += 1 if плохо else 0 + print(" %s %-26s %s" % ("!!" if плохо else "ok", s["name"][:26], стр)) + except Exception as e: + беда += 1 + print(" !! %-26s НЕ ДОСТУЧАЛСЯ: %s" % (s["name"][:26], str(e)[:60])) +print("\nпроблемных строк:", беда) diff --git a/scripts/checks/check_conf.py b/scripts/checks/check_conf.py new file mode 100644 index 0000000..789320c --- /dev/null +++ b/scripts/checks/check_conf.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Ищем склеенные строки в конфигах awg на всех серверах панели. + +Имена переменных в пробе латиницей: sh внутри контейнеров кириллицу не берёт. +""" +import json, sys +sys.path.insert(0, "/app") +from managers.ssh_manager import SSHManager + +ПРОБА = ( + "for c in amnezia-awg2 amnezia-awg amnezia-awg31 amnezia-awg3 amnezia-awg-legacy; do " + " docker ps --format '{{.Names}}' 2>/dev/null | grep -qx $c || continue; " + " for f in awg0.conf wg0.conf; do " + " p=/opt/amnezia/awg/$f; " + " docker exec $c test -f $p 2>/dev/null || continue; " + " glue=$(docker exec $c grep -c '/32\\[Peer\\]' $p 2>/dev/null || echo 0); " + " endnl=$(docker exec $c sh -c \"tail -c 1 $p | od -An -c | tr -d ' '\" 2>/dev/null); " + " peers=$(docker exec $c grep -c '^\\[Peer\\]' $p 2>/dev/null || echo 0); " + " echo \"$c/$f peers=$peers glue=$glue end=$endnl\"; " + " done; done" +) + +d = json.load(open("/app/data/data.json")) +for s in d["servers"]: + try: + with SSHManager(s["host"], s.get("ssh_port", 22), s["username"], + password=s.get("password") or None, + private_key=s.get("private_key") or None, + connect_timeout=8) as ssh: + out, err, _ = ssh.run_command(ПРОБА, timeout=40) + for строка in (out or err).splitlines(): + строка = строка.strip() + if not строка: + continue + плохо = ("glue=0" not in строка) or ("end=\\n" not in строка) + print("%s %-26s %s" % (" !!" if плохо else " ", s["name"][:26], строка)) + except Exception as e: + print(" %-26s СБОЙ: %s" % (s["name"][:26], str(e)[:50])) diff --git a/scripts/checks/check_garbage.py b/scripts/checks/check_garbage.py new file mode 100644 index 0000000..8bbbfb2 --- /dev/null +++ b/scripts/checks/check_garbage.py @@ -0,0 +1,30 @@ +"""Не осталось ли от проверок тестовых клиентов в clientsTable и в data.json.""" +import json, sys +sys.path.insert(0, "/app") +from managers.ssh_manager import SSHManager + +МЕТКА = "__проверка_связи" +d = json.load(open("/app/data/data.json")) + +в_панели = [c for c in json.dumps(d, ensure_ascii=False).split('"') if МЕТКА in c] +print("следов в data.json панели:", len(в_панели)) + +ПРОБА = ( + "for c in $(docker ps --format '{{.Names}}' 2>/dev/null | grep -E 'amnezia-(awg|wireguard|xray)'); do " + " n=$(docker exec $c sh -c \"grep -o '%s[^\\\"]*' /opt/amnezia/awg/clientsTable /opt/amnezia/xray/clientsTable 2>/dev/null | wc -l\"); " + " [ \"$n\" != \"0\" ] && echo \"$c: $n\"; done; echo готово" % МЕТКА +) +всего = 0 +for s in d["servers"]: + try: + with SSHManager(s["host"], s.get("ssh_port", 22), s["username"], + password=s.get("password") or None, + private_key=s.get("private_key") or None, connect_timeout=8) as ssh: + o, _, _ = ssh.run_command(ПРОБА, timeout=40) + строки = [x for x in (o or "").splitlines() if x.strip() and "готово" not in x] + if строки: + всего += len(строки) + print(" !!", s["name"], строки) + except Exception as e: + print(" ?", s["name"][:26], str(e)[:40]) +print("серверов с остатками:", всего) diff --git a/scripts/checks/test_create.py b/scripts/checks/test_create.py new file mode 100644 index 0000000..98337dc --- /dev/null +++ b/scripts/checks/test_create.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Боевая проверка: на каждом сервере и каждом протоколе создаём тестового +клиента и тут же удаляем. Именно так работает кнопка «Добавить подключение». + +Считаем пиров до и после: если после удаления число не вернулось — значит +за нами остался мусор, и это надо видеть. +""" +import json, sys, time +sys.path.insert(0, "/app") +from managers.ssh_manager import SSHManager +from managers.awg_manager import AWGManager + +ИМЯ = "__проверка_связи_" + time.strftime("%d%m_%H%M") +ПРОТОКОЛЫ = ("awg", "awg2", "awg3", "awg31", "wireguard") + +d = json.load(open("/app/data/data.json")) +итог = {"ok": 0, "сбой": 0, "мусор": 0} + +for s in d["servers"]: + протоколы = [p for p in ПРОТОКОЛЫ + if (s.get("protocols", {}).get(p) or {}).get("installed")] + if not протоколы: + print(" – %-26s протоколов AWG не заведено" % s["name"][:26]) + continue + for proto in протоколы: + метка = "%s / %s" % (s["name"][:22], proto) + try: + ssh = SSHManager(s["host"], s.get("ssh_port", 22), s["username"], + password=s.get("password") or None, + private_key=s.get("private_key") or None, + connect_timeout=10, connect_retries=1) + ssh.connect() + try: + m = AWGManager(ssh) + было = len(m._get_used_ips(proto)) + порт = (s["protocols"][proto] or {}).get("port", "55424") + r = m.add_client(proto, ИМЯ, s["host"], порт) + cid = r.get("client_id") or r.get("clientId") + есть_конфиг = bool(r.get("config")) + стало = len(m._get_used_ips(proto)) + m.remove_client(proto, cid) + после = len(m._get_used_ips(proto)) + finally: + ssh.disconnect() + + если_чисто = (после == было) + итог["ok" if (есть_конфиг and стало == было + 1) else "сбой"] += 1 + if not если_чисто: + итог["мусор"] += 1 + print(" %s %-30s пиров %d → %d → %d конфиг=%s" % ( + "ok" if (есть_конфиг and стало == было + 1 and если_чисто) else "!!", + метка, было, стало, после, "есть" if есть_конфиг else "НЕТ")) + except Exception as e: + итог["сбой"] += 1 + print(" !! %-30s %s" % (метка, str(e)[:70])) + +print("\nсоздалось и убралось начисто: %d, сбоев: %d, осталось мусора: %d" + % (итог["ok"], итог["сбой"], итог["мусор"]))