Files
wireguard-scripts/README.md
T

12 KiB
Raw Blame History

wireguard-scripts

M1 runtime foundation

The current entry point provides dependency-free help and version commands. The planned operational commands are recognized but remain unavailable until later milestones.

Runtime locations default to the project directory and can be redirected for an isolated run with absolute paths using these environment variables:

WG_MANAGER_CONFIG, WG_MANAGER_BACKUP_DIR, WG_MANAGER_LOG_DIR, WG_MANAGER_METADATA_DIR, WG_MANAGER_ARCHIVE_DIR, and WG_MANAGER_LOCK_FILE.

WG_MANAGER_GUM selects an executable gum explicitly; otherwise the bundled bin/gum and then PATH are checked in that order. Configuration is parsed as restricted KEY=VALUE data and is never executed as shell code. Blank lines and full-line # comments are ignored; spaces around the key, =, and value are trimmed. Values are either one unquoted token or a double-quoted value without escapes, and only documented keys are accepted.

For deterministic read-only tests, WG_MANAGER_NOW may override the current epoch when set to decimal seconds; invalid values are rejected.

M2 adds read-only status and list. They parse the configured WireGuard file and, when available, wg show <interface> dump; a stopped or unavailable runtime is reported as unavailable and disk-only peers remain visible. list uses stable tab-separated output with English machine fields state and origin (managed, legacy, or unmanaged) and never prints private or preshared keys.

The explicit peer comment marker is # wg-manager-client: NAME; it is only a display candidate. A peer is considered managed only when its exact public key and configured addresses match a valid metadata record with MANAGED=1.

M3 transaction foundation

The internal run_transaction OPERATION TARGET BUILDER [METADATA_FILE...] primitive acquires WG_MANAGER_LOCK_FILE, then reloads and validates the live configuration before calling its builder. It creates a restrictive, timestamped backup, validates a same-filesystem staged configuration with wg-quick strip, replaces the live file atomically, applies it with wg syncconf, and verifies the active peer set. Apply or verification failures restore both disk and runtime; a failed restoration is reported as a critical rollback error. No M3 mutation command is exposed yet.

M3 tests use only isolated overrides and deny-by-default command mocks; they do not inspect or modify host WireGuard state.

M4 client creation

add NAME creates a client transactionally. The optional forms are --mode full-tunnel|split-tunnel and --endpoint HOST; unknown or extra arguments are rejected. Names are restricted to ASCII letters, digits, ., _, and - (without a leading -). Root is required for production use; tests enable only an isolated WG_MANAGER_TEST_MODE under TEST_ROOT.

Private/public/PSK files, client configuration, and metadata use restrictive permissions and are removed if the server transaction or rollback fails. Generated key material is supplied to wg through stdin or stdout and is not placed in command arguments or diagnostic output.

M5 inspection and export

show NAME displays only non-secret peer details and a config path after identity, ownership, mode, and path validation. config NAME prints only that validated path. Full client content requires the explicit noninteractive config NAME --show form; it never reads separate .key or .psk files.

qr NAME feeds the validated config to qrencode -t ansiutf8 through stdin. If the optional qrencode dependency is unavailable, it prints the safe config path and returns status 69; QR failures return the operation status. Routine show/export/path/error output is secret-free.

The inspection commands do not require gum or qrencode for show and config. qrencode is the only optional QR dependency; when it is absent, qr NAME writes the validated configuration path to stdout and an actionable warning to stderr, then returns status 69. A nonzero qrencode result returns status 70 without printing configuration content in the diagnostic.

Common command statuses are 64 for usage errors, 65 for invalid or unsafe client identity/path data, 69 for a missing optional dependency, and 70 for an operational read/export/QR failure. config NAME --show is the only inspection form that writes the complete client configuration to stdout; ordinary show, config, and qr output remains secret-safe.

M9 TUI

Запуск без аргументов или командой tui открывает read-only интерфейс gum в терминале. gum разрешается в порядке WG_MANAGER_GUM, локального bin/gum, затем PATH; необходимые подкоманды проверяются до вывода интерфейса. Нужны одновременно интерактивные stdin и stdout. Escape и отмена возвращают на предыдущий экран или завершают меню без изменений. Доступны status, clients/show, diagnose, log и backups; add/remove в M9 являются placeholder-действиями и не выполняют мутаций. CLI работает независимо от gum; отсутствие или неполная возможность gum даёт код 69 только для TUI, а неинтерактивный запуск TUI — код 64.

M6 удаление клиента

remove NAME [--yes] удаляет только подтверждённый managed-peer после повторной проверки точного публичного ключа, адресов и блока под lock. В интерактивном терминале без --yes показываются имя, адреса и только последние 8 символов публичного ключа; ответ, отличный от y, отменяет операцию без изменений. В неинтерактивном режиме --yes обязателен.

Изменение серверной конфигурации выполняется внутри транзакции: сначала конфигурация заменяется и проверяется в WireGuard, а затем финализатор архивирует связанные .conf, .meta, .key, .pub и .psk (если существуют) в уникальный каталог ARCHIVE_DIR с режимами 0700/0600. Ошибка архивирования после применения приводит к откату и оставляет исходные файлы доступными для восстановления; архивы не удаляются автоматически и служат восстановительным материалом. Журнал содержит operation, target, UTC timestamp, outcome и короткий суффикс публичного ключа; ключи и содержимое конфигураций в него не записываются.

remove возвращает 64 для ошибки аргументов, 65 для неподтверждённой или небезопасной identity/path, 69 для отсутствующей обязательной зависимости и 70 для ошибки операции или архивации. Ошибка аудита после успешной мутации явно сообщается и возвращает операционный статус; отмена остаётся успешной без изменения состояния. diagnose [--quiet] выполняет только read-only проверки конфигурации и прав, наличия интерфейса, wg dump, forwarding, адресов/маршрутов IPv4 и IPv6, UDP-порта, firewall, systemd, runtime-vs-disk peer set и журнала. Отдельные записи config-parse, duplicate-keys, allowedips-overlap и key-permissions не скрывают независимые причины сбоя. Каждая запись имеет один из статусов OK, WARN, FAIL или SKIP; --quiet выводит только стабильные строки id=STATUS. Обязательны wg, wg-quick и ip; systemctl, journalctl, nft, iptables и ss являются optional и при отсутствии дают собственный SKIP. На хосте без активного systemd проверки systemd и журнала пропускаются. firewall=OK означает только видимое ожидаемое NAT-свидетельство, а не полную проверку политики firewall. Ненулевой код (70) возвращается при любом FAIL, 64 — при неверных аргументах. Команда не изменяет конфигурацию, runtime, маршруты, firewall или sysctl; handshake и журнал имеют ограниченную историческую видимость. Тесты используют только изолированные fixtures/mocks и не доказывают состояние реального сервера.

M8 резервные копии, восстановление и аудит

backup создаёт ручную резервную копию текущей серверной конфигурации под lock; backups показывает только проверенные прямые дочерние каталоги, в порядке от новых к старым. Повреждённые или неполные записи не исполняются и не читаются как shell-код. restore BACKUP [--yes] восстанавливает только серверную конфигурацию: перед заменой текущая версия также резервируется, а ошибки применения проверяют и откатывают disk/runtime. Восстановление другой WireGuard-интерфейсной конфигурации отклоняется. Без --yes требуется подтверждение в терминале; в неинтерактивном режиме команда возвращает ошибку использования. Клиентские metadata/key-файлы восстановлением не изменяются.

log [LIMIT] выводит только корректные структурированные audit-события в newest-first порядке; LIMIT находится в диапазоне 1..1000. При отсутствии журнала выводится безопасное сообщение. Записи содержат UTC timestamp, actor UID, operation, target, outcome и короткую категорию ошибки; секреты, команды и полные конфигурации не записываются. Ошибки аудита после успешной мутации сообщаются как частичный операционный результат. Основные коды: 64 — аргументы, 65 — небезопасная/невалидная backup identity, 70 — ошибка операции; критический неудачный rollback сохраняет отдельный rollback status.