# WireGuard Manager: план MVP ## 1. Назначение проекта WireGuard Manager — локальный Bash-скрипт для администрирования WireGuard на том же Linux-сервере, где запущен WireGuard. Основные задачи проекта: - просмотр состояния WireGuard; - просмотр списка клиентов; - добавление клиентов; - удаление клиентов; - получение клиентского конфига и QR-кода; - диагностика конфигурации, сервиса и сети; - ведение локального журнала административных операций; - создание резервных копий перед изменением конфигурации. Существующий `add-user.sh` используется как исходный пример, но его логика будет переработана в безопасные переиспользуемые функции. ## 2. Модель распространения и запуска Проект не устанавливается в систему и не добавляется в `PATH`. Скрипт и сопутствующие файлы находятся в переносимой директории, например: ```text /root/wireguard-manager/ ├── wg-manager.sh ├── wg-manager.conf ├── add-user.sh ├── bin/ │ └── gum ├── backups/ ├── logs/ └── tests/ ``` Основная точка входа: ```bash sudo /root/wireguard-manager/wg-manager.sh ``` CLI-команды вызываются через тот же файл: ```bash sudo /root/wireguard-manager/wg-manager.sh status sudo /root/wireguard-manager/wg-manager.sh list sudo /root/wireguard-manager/wg-manager.sh add alice sudo /root/wireguard-manager/wg-manager.sh diagnose ``` Скрипт определяет свою директорию через `BASH_SOURCE`, поэтому всю директорию проекта можно перемещать. Скрипты `install.sh` и `uninstall.sh` не нужны. Установку или размещение зависимостей выполняет администратор сервера. ## 3. TUI Для терминального интерфейса используется `gum`. Встроенный TUI на чистом Bash, а также интерфейсы на `dialog` и `whiptail` в MVP не планируются. Поиск бинарника `gum` выполняется в следующем порядке: 1. Путь из переменной окружения `WG_MANAGER_GUM`. 2. `${SCRIPT_DIR}/bin/gum` рядом со скриптом. 3. Команда `gum` из `PATH`. Если `gum` отсутствует: - CLI-команды продолжают работать; - при попытке открыть TUI выводится понятное сообщение об ошибке; - скрипт не устанавливает и не скачивает `gum` автоматически. ### Главное меню ```text WireGuard Manager Интерфейс: wg0 Состояние: активен Клиентов: 12 Активны недавно: 4 1. Состояние WireGuard 2. Список клиентов 3. Добавить клиента 4. Информация о клиенте 5. Показать QR-код / конфиг 6. Удалить клиента 7. Диагностика 8. Журнал операций 9. Резервные копии 0. Выход ``` TUI должен использовать возможности `gum` для меню, фильтрации списка клиентов, ввода данных, таблиц, подтверждений, просмотра длинного текста и индикации выполнения операций. ## 4. Архитектурный принцип TUI не содержит бизнес-логику. Он только собирает ввод пользователя и вызывает те же функции, которые доступны через CLI. Логические слои внутри `wg-manager.sh`: 1. Загрузка и проверка конфигурации. 2. Проверка прав и зависимостей. 3. Чтение состояния WireGuard. 4. Управление клиентами. 5. Безопасное изменение серверного конфига. 6. Резервное копирование и восстановление. 7. Диагностика. 8. Audit log. 9. CLI-маршрутизация. 10. TUI на `gum`. Для MVP эти функции могут находиться в одном `wg-manager.sh`. Если файл станет слишком большим, их можно будет позднее вынести в `lib/*.sh`, сохранив прежнюю точку входа. ## 5. Конфигурация менеджера Из `add-user.sh` необходимо убрать жёстко заданные параметры и перенести их в `wg-manager.conf`. Пример состава конфигурации: ```bash WG_INTERFACE="wg0" WG_CONF="/etc/wireguard/wg0.conf" CLIENT_DIR="/etc/wireguard/clients" SERVER_ENDPOINT="vpn.example.com" SERVER_PORT="51820" SERVER_VPN_IP="10.9.0.1" CLIENT_DNS="10.9.0.1,192.168.0.200" VPN_SUBNET_PREFIX="10.9.0" START_HOST="2" END_HOST="254" USE_IPV6="0" IPV6_PREFIX="fd05:13:53::" DEFAULT_CLIENT_MODE="full-tunnel" RECENT_HANDSHAKE_SECONDS="180" ``` Конфигурация должна проверяться до выполнения любой операции. Неизвестные или небезопасные значения не должны напрямую подставляться в команды. Рекомендуемые права: ```bash chmod 700 /root/wireguard-manager chmod 700 /root/wireguard-manager/wg-manager.sh chmod 600 /root/wireguard-manager/wg-manager.conf ``` ## 6. Функции MVP ### 6.1. Состояние WireGuard Экран состояния показывает: - имя интерфейса; - состояние интерфейса и `wg-quick`-сервиса; - публичный ключ сервера; - UDP-порт; - количество peers; - время работы или доступную информацию о запуске сервиса; - наличие предупреждений диагностики. ### 6.2. Список клиентов Для каждого клиента показываются: - имя; - VPN-адрес; - сокращённый публичный ключ; - endpoint, если он известен; - время последнего handshake; - принятый и переданный трафик; - вычисляемое состояние; - признак, управляется ли клиент этим скриптом. Предлагаемые состояния: - `active` — handshake был недавно; - `inactive` — клиент ранее подключался, но давно неактивен; - `never` — handshake ещё не было; - `unmanaged` — peer найден в WireGuard, но его имя и метаданные неизвестны менеджеру. Источником текущего состояния является `wg show ... dump`. Серверный конфиг используется для постоянных параметров и сопоставления peers. ### 6.3. Добавление клиента Операция добавления: 1. Проверяет имя клиента. 2. Проверяет отсутствие клиента, ключей и файлов с таким именем. 3. Находит свободный IP в заданном диапазоне. 4. Проверяет конфликты во всех `AllowedIPs`. 5. Создаёт private key, public key и preshared key. 6. Формирует серверный peer-блок. 7. Формирует клиентский конфиг. 8. Проверяет будущую серверную конфигурацию. 9. Создаёт резервную копию. 10. Атомарно сохраняет и применяет конфигурацию. 11. Сохраняет метаданные клиента. 12. Записывает административное действие в журнал. Имя клиента допускает только безопасный ограниченный набор символов: латинские буквы, цифры, точку, подчёркивание и дефис. MVP поддерживает два режима маршрутизации клиента: - `full-tunnel` — весь IPv4-трафик идёт через VPN; - `split-tunnel` — через VPN идут только указанные сети. ### 6.4. Просмотр и экспорт клиента Для выбранного клиента доступны: - сведения о peer; - путь к клиентскому конфигу; - просмотр конфига после отдельного подтверждения; - QR-код через `qrencode`, если команда доступна; - понятное сообщение и путь к конфигу, если `qrencode` отсутствует. Приватные ключи и содержимое клиентских конфигов не записываются в audit log. ### 6.5. Удаление клиента Удаление требует выбора клиента и явного подтверждения. Перед изменением создаётся резервная копия. Операция: 1. Находит peer по сохранённому публичному ключу, а не только по имени. 2. Удаляет peer из будущей серверной конфигурации. 3. Проверяет новый конфиг. 4. Применяет изменение. 5. Удаляет или архивирует клиентские файлы согласно выбранной политике. 6. Записывает действие в audit log без секретов. Для MVP безопаснее по умолчанию перемещать клиентские файлы в локальный архив, а не уничтожать безвозвратно. ### 6.6. Диагностика Диагностика проверяет: - запуск с необходимыми правами; - наличие `wg`, `wg-quick`, `ip` и других обязательных команд; - наличие серверного конфига; - права на конфиги и ключи; - наличие и состояние интерфейса; - состояние `wg-quick@` при использовании systemd; - возможность прочитать активную конфигурацию; - корректность адресов и `AllowedIPs`; - дублирующиеся адреса и пересекающиеся сети; - включён ли IPv4 forwarding; - IPv6 forwarding, если IPv6 включён в настройках; - маршруты сервера; - наличие ожидаемых NAT/firewall-правил; - прослушивание настроенного UDP-порта; - расхождение между конфигом на диске и активным состоянием; - последние релевантные сообщения systemd journal. Результат каждой проверки имеет статус `OK`, `WARN`, `FAIL` или `SKIP`. Команда диагностики возвращает ненулевой exit code при критических ошибках. WireGuard не предоставляет полноценную историю клиентских подключений. Менеджер показывает текущее состояние, последние handshake и доступные системные журналы, но не заявляет их как полную историю активности пользователей. ### 6.7. Журнал операций Локальный audit log содержит: - дату и время; - выполненную операцию; - имя клиента, если применимо; - результат; - краткое описание ошибки; - пользователя или UID, запустившего операцию. В журнал запрещено записывать: - private keys; - preshared keys; - полные клиентские конфиги; - команды, содержащие секретные значения. ### 6.8. Резервные копии Перед каждым изменением создаётся резервная копия серверного конфига и относящихся к операции метаданных. MVP предоставляет: - создание резервной копии; - список резервных копий; - восстановление выбранной копии с подтверждением; - автоматический rollback при ошибке применения нового конфига; - ограничение количества автоматически сохраняемых копий. ## 7. Безопасное изменение конфигурации Изменение `wg0.conf` должно быть транзакционным: 1. Получить эксклюзивную блокировку через `flock`. 2. Повторно прочитать актуальное состояние после получения блокировки. 3. Проверить входные данные. 4. Создать backup. 5. Сформировать новый конфиг во временном файле с `umask 077`. 6. Проверить синтаксис и возможность преобразования конфига средствами WireGuard. 7. Установить правильные права и владельца. 8. Атомарно заменить рабочий файл. 9. Применить конфигурацию через `wg syncconf` и `wg-quick strip`. 10. Проверить итоговое активное состояние. 11. При ошибке восстановить предыдущий файл и активную конфигурацию. 12. Освободить блокировку и записать результат в журнал. Нельзя сначала дописывать peer непосредственно в рабочий конфиг, как это сейчас делает `add-user.sh`, а затем надеяться, что применение завершится успешно. ## 8. CLI Минимальный набор команд: ```text wg-manager.sh Открыть TUI wg-manager.sh status Состояние WireGuard wg-manager.sh list Список клиентов wg-manager.sh add NAME Добавить клиента wg-manager.sh show NAME Информация о клиенте wg-manager.sh config NAME Показать путь к клиентскому конфигу wg-manager.sh qr NAME Показать QR-код wg-manager.sh remove NAME Удалить клиента wg-manager.sh diagnose Выполнить диагностику wg-manager.sh backup Создать резервную копию wg-manager.sh backups Показать резервные копии wg-manager.sh restore BACKUP Восстановить резервную копию wg-manager.sh log Показать audit log wg-manager.sh help Показать справку ``` CLI должен иметь стабильные exit codes и пригодный для чтения текстовый вывод. Структурированный JSON-вывод не входит в обязательный объём MVP. ## 9. Метаданные клиентов Комментарии вида `### Client NAME` можно поддерживать для читаемости и совместимости с существующим `add-user.sh`, но они не должны быть единственным источником данных. Для управляемого клиента необходимо хранить как минимум: - имя; - публичный ключ; - VPN-адрес; - дату создания; - путь к клиентскому конфигу; - режим маршрутизации; - статус управления. Формат метаданных должен быть простым и обрабатываться стандартными средствами Bash без обязательной зависимости от `jq`. Серверный конфиг и фактическое состояние `wg` остаются источниками истины для сетевых параметров. ## 10. Зависимости Обязательные: - Bash; - WireGuard tools: `wg`, `wg-quick`; - стандартные Linux-команды, используемые скриптом; - `flock` для защиты от параллельных изменений. Для TUI: - `gum`, предоставляемый или устанавливаемый администратором. Необязательные: - `qrencode` для QR-кодов; - `systemctl` и `journalctl` для серверов с systemd; - инструменты конкретного firewall: `nft` или `iptables`. При отсутствии необязательной команды соответствующая функция должна показывать `SKIP` или понятное сообщение, а не завершать весь менеджер аварийно. ## 11. Тестирование Большая часть тестов не должна требовать реального интерфейса WireGuard или изменения `/etc/wireguard`. Необходимые сценарии: - разбор серверного конфига; - определение следующего свободного IP; - обнаружение конфликтующих `AllowedIPs`; - проверка имён клиентов; - построение peer-блока; - удаление только выбранного peer-блока; - обработка unmanaged peers; - успешное применение транзакции; - rollback при ошибке применения; - защита от параллельного запуска; - отсутствие секретов в логах; - работа CLI без `gum`; - корректная ошибка TUI без `gum`; - поиск локального и системного бинарника `gum`. Для тестов используются fixtures конфигураций и mock-команды `wg`, `wg-quick`, `systemctl`, `ip`, `nft` и `iptables`, подставляемые через контролируемый `PATH`. Дополнительные проверки качества: - `shellcheck`; - `bash -n`; - единый формат shell-кода; - тестирование на поддерживаемых версиях Bash. ## 12. Этапы реализации ### Этап 1. Каркас - создать `wg-manager.sh`; - реализовать загрузку конфигурации; - определить директорию проекта; - добавить обработку ошибок и временных файлов; - добавить проверку root для изменяющих операций; - реализовать CLI `help`, `status` и `list`. ### Этап 2. Модель клиентов - разобрать существующий `wg0.conf`; - связать имена, публичные ключи и адреса; - отображать managed и unmanaged peers; - добавить метаданные клиентов. ### Этап 3. Безопасные изменения - перенести и переработать логику `add-user.sh`; - добавить блокировку, backup, валидацию и rollback; - реализовать `add` и `remove`; - реализовать архивирование клиентских файлов. ### Этап 4. Диагностика и журнал - добавить диагностические проверки; - добавить статусы `OK/WARN/FAIL/SKIP`; - добавить audit log без секретов; - добавить просмотр резервных копий и восстановление. ### Этап 5. TUI на `gum` - реализовать главное меню; - таблицу и фильтрацию клиентов; - формы добавления; - карточку клиента; - подтверждение удаления и восстановления; - экраны диагностики, логов и резервных копий. ### Этап 6. Проверка MVP - добавить fixtures и mocks; - протестировать успешные и аварийные сценарии; - проверить поведение на реальном тестовом интерфейсе WireGuard; - подготовить README с примерами запуска и конфигурации. ## 13. Критерии готовности MVP MVP считается готовым, если администратор может: 1. Скопировать или переместить директорию проекта на Linux-сервер. 2. Настроить `wg-manager.conf` без редактирования основной логики. 3. Запустить TUI через `wg-manager.sh` с предоставленным `gum`. 4. Использовать основные функции через CLI без TUI. 5. Просмотреть WireGuard и список известных клиентов. 6. Безопасно добавить клиента и получить его конфиг или QR-код. 7. Безопасно удалить клиента. 8. Выполнить диагностику и увидеть конкретные предупреждения и ошибки. 9. Просмотреть журнал административных операций без утечки ключей. 10. Восстановить конфигурацию из backup после неудачного изменения. 11. Не повредить рабочий конфиг при ошибке команды или параллельном запуске. ## 14. За пределами MVP После завершения MVP можно добавить: - временное отключение и повторное включение клиента без удаления; - срок действия клиента; - ротацию ключей; - импорт существующих unmanaged peers; - поддержку нескольких WireGuard-интерфейсов; - шаблоны маршрутов и DNS для разных типов клиентов; - экспорт диагностического отчёта; - уведомления о проблемах; - JSON-вывод для интеграций; - локализацию интерфейса; - дополнительные варианты поставки `gum` для разных архитектур. Эти функции не должны задерживать выпуск первого работоспособного MVP.