awg_profiler
Инструмент на Go для развёртывания и управления сервером AmneziaWG (форк WireGuard с обфускацией трафика): установка зависимостей, инициализация сервера, управление клиентами (CLI и веб-UI) и сбор статистики трафика, переживающей перезапуски.
Проект самодостаточен: единственный бинарник awg_profiler, встроенный
веб-интерфейс (без внешних зависимостей в браузере) и Docker-образы для
запуска без установки чего-либо на хост.
Quick Start
Ниже — два независимых пути развёртывания «с нуля» (Green Field): в контейнере (рекомендуется, не требует ничего кроме Docker) или напрямую на хосте.
Вариант A — в контейнере (рекомендуется)
Требования: Docker + Docker Compose, ядро Linux с включённым модулем tun
(есть на любом современном дистрибутиве).
Контейнер запускает встроенный веб-интерфейс на :8080 (WEB UI) и слушает
VPN-трафик на UDP :51820. AmneziaWG-стек (awg, awg-quick,
amneziawg-go) собирается внутри образа — на хосте ничего ставить не нужно.
git clone <repo-url> awg_profiler && cd awg_profiler
# Сборка и запуск (образ на базе Alpine)
docker compose up -d --build
# Логи / статус
docker compose logs -f
По умолчанию порт 8080 публикуется только на 127.0.0.1 хоста (см.
docker-compose.yml) — веб-UI недоступен по сети, пока вы явно не расширите
доступ. На самой машине откройте http://127.0.0.1:8080, либо для доступа с
другого компьютера прокиньте порт по SSH: ssh -L 8080:127.0.0.1:8080 user@server и откройте http://127.0.0.1:8080 локально.
Веб-UI покажет мастер настройки:
- install-deps — пропускается автоматически (зависимости уже в образе).
- init-server — заполните форму (сеть, порт, DNS, MTU — можно оставить значения по умолчанию) и отправьте. Сервер сгенерирует ключи, параметры обфускации и запустится.
- Создавайте клиентов на вкладке Clients, скачивайте
.conf/ QR-код.
Чтобы открыть UI на всех интерфейсах (LAN/интернет), сначала включите Basic-аутентификацию, иначе панель управления сервером останется без пароля:
# в docker-compose.yml:
# 1. раскомментировать блок environment: и задать
AWG_WEB_USER=admin
AWG_WEB_PASS=длинный-пароль
# 2. заменить порт "127.0.0.1:8080:8080" на "8080:8080"
docker compose up -d --build
Все изменяемые данные (конфиг, реестр клиентов, профили, статистика) живут в
именованных томах awg-data и awg-etc — переживают docker compose down
без -v.
Альтернативный образ (Linux Mint база, вендорские пакеты AmneziaWG вместо собранных из исходников):
docker compose -f docker-compose.mint.yml up -d --build
Вариант B — на хосте (без контейнера)
Требования: Linux (Ubuntu, Debian, Linux Mint или Alpine), Go ≥ 1.26,
root/sudo. install-deps сам ставит AmneziaWG: на apt-based дистрибутивах —
пакеты amneziawg/amneziawg-tools из ppa:amnezia/ppa; на Alpine, где
готового пакета amneziawg-tools нет, — собирает awg/awg-quick из
исходников (нужен интернет для git clone на этапе install-deps). На Alpine
kernel-модуль amneziawg при этом не ставится — его нужно предоставить
отдельно (DKMS/akmods или готовый модуль под ваше ядро), install-deps
только предупредит об этом.
git clone <repo-url> awg_profiler && cd awg_profiler
# 1. Сборка бинарника
export PATH=$PATH:/usr/local/go/bin
go build -o awg_profiler .
# 2. Установка зависимостей (AmneziaWG, qrencode, nftables, jq) — один раз
sudo ./awg_profiler install-deps
# 3. Интерактивная инициализация сервера (ключи, обфускация, конфиг, служба)
sudo ./awg_profiler init-server
# 4. Первый клиент
sudo ./awg_profiler create phone
# 5. (опционально) веб-UI поверх той же установки
sudo ./awg_profiler web --addr 0.0.0.0:8080
install-deps и init-server — обязательно раздельные шаги и в этом
порядке: init-server проверяет флаг, оставленный install-deps, и
отказывается работать, если пакеты ещё не установлены.
На вопрос «VPN network CIDR» принимается только /24 (например
10.0.0.0/24 или 192.168.5.0/24) — весь остальной код (адрес сервера,
адреса клиентов, запись в конфиг) жёстко расчитан на /24, другой префикс
init-server отклонит с ошибкой.
Дальше — управление через CLI (server-status, create, list, …) или
запущенный web; см. полный список команд в CLI-командах.
Detailed Info
Расположение файлов
Пути привязаны к каталогу исполняемого файла (<dir>, переопределяется
переменной AWG_PROFILER_DIR — так собран Docker-образ, где <dir>=/data):
| Назначение | Путь |
|---|---|
| Конфиг профилировщика | <dir>/awg_config (формат shell KEY="value") |
| Реестр клиентов | <dir>/data/awg_clients.json |
| Накопленная статистика трафика | <dir>/data/awg_stats.json |
| Профили клиентов | <dir>/awg_clients/<name>.conf + .png (QR) |
| Флаг «зависимости установлены» | <dir>/awg_state.json |
| Interface conf / nft-правила | /etc/amnezia/amneziawg/<iface>.conf, <iface>-rules.nft |
CLI-команды
SERVER SETUP
install-deps Установить AmneziaWG, jq, qrencode для текущей ОС
и записать флаг deps_installed (выполнить ПЕРВЫМ)
init-server Интерактивная настройка сервера: проверяет флаг
зависимостей, затем генерирует ключи + параметры
обфускации, пишет конфиги, включает IP-forwarding
и запускает службу (пакеты НЕ ставит)
SERVER MANAGEMENT
server-status Статус интерфейса и список пиров
server-start Запустить службу AmneziaWG
server-stop Остановить службу AmneziaWG
server-restart Перезапустить службу AmneziaWG
show-config Показать текущий конфиг (приватные ключи скрыты)
sync-config Пересобрать <conf-dir>/<iface>.conf из реестра
клиентов и (по подтверждению) перезапустить службу
CLIENT MANAGEMENT
create <name> Создать клиента: ключи, .conf, QR-код
delete <id> Удалить клиента (файлы + запись в реестре)
disable <id> Перевести клиента в статус DISABLED
enable <id> Перевести клиента в статус ACTIVE
list Список всех зарегистрированных клиентов
WEB UI
web [--addr host:port] Запустить веб-UI (по умолчанию 127.0.0.1:8080)
[--theme classic|glass]
[--ui-mode dark|light|auto]
Поддерживаемые ОС: Ubuntu, Debian, Linux Mint, Alpine Linux
(автоопределение по /etc/os-release; на apt-based используется systemd, на
Alpine — OpenRC; если систем systemd не является PID 1 — например, в
контейнере — используется прямое управление через awg-quick).
Разделение install-deps и init-server
Установка пакетов полностью отделена от настройки сервера:
install-depsставит AmneziaWG и тулинг под текущую ОС и пишет флагdeps_installed=trueвawg_state.json(с временем и версией ОС).init-serverпакеты не ставит. Сначала проверяет флаг: еслиinstall-depsне запускался, завершается ошибкойDependencies not installed — run 'install-deps' first. При установленном флаге переходит к генерации ключей, параметров обфускации, конфигов, включению IP-forwarding и запуску службы.
В контейнерных образах этот флаг сеется автоматически при старте
(entrypoint.sh / entrypoint.mint.sh), так как AmneziaWG-стек уже
запечён в образ на этапе сборки — шаг install-deps в UI/CLI внутри
контейнера не требуется.
Web-UI
Команда web поднимает встроенный веб-интерфейс управления. Он использует ту
же логику, что и CLI (общий Go-пакет), поэтому реестр/конфиг/служба остаются
совместимыми. Статические ассеты (webui/, webui_glass/) вшиты в бинарник
через go:embed — дополнительных файлов при развёртывании не нужно.
sudo ./awg_profiler web # 127.0.0.1:8080 (по умолчанию)
sudo ./awg_profiler web --addr 0.0.0.0:8080 # на всех интерфейсах
sudo ./awg_profiler web --theme glass # альтернативный дизайн (glassmorphism)
sudo ./awg_profiler web --ui-mode auto # следовать светлой/тёмной теме ОС
Дизайн выбирается флагом --theme classic|glass (env AWG_WEB_THEME, по
умолчанию classic), цвет-режим — --ui-mode dark|light|auto (env
AWG_WEB_MODE, по умолчанию dark — тёмная форсируется). glass —
dark-only, --ui-mode для неё игнорируется.
Возможности UI:
- Дашборд — статус интерфейса (UP/DOWN), эндпоинт, сеть, публичный ключ,
счётчики «всего / активных / онлайн», кнопки
start/stop/restartиsync. - Клиенты — список с индикатором онлайна и накопленным трафиком; создание,
включение/выключение, удаление, скачивание
.confи просмотр QR-кода. - Статистика по пользователю — по каждому клиенту показываются накопленные
байты (↓ rx / ↑ tx), отметка «Stats since», последний handshake, эндпоинт и
признак «онлайн» (handshake ≤ 150 c), а также кнопка Reset stats для
быстрой очистки. Живые данные берутся из
awg show <iface> dumpи сопоставляются с реестром по публичному ключу. - Мастер настройки — если сервер ещё не инициализирован, UI показывает
форму
install-deps→init-server(неинтерактивные аналоги CLI-команд).
UI построен как одностраничное приложение на «ванильном» JS/CSS (без внешних
зависимостей — работает офлайн), mobile-first, с обновлением статистики каждые
10 c. По умолчанию всегда тёмная тема (см. --ui-mode выше).
Накопление статистики (переживает перезапуск)
awg show <iface> dump отдаёт счётчики rx/tx, которые обнуляются при каждом
перезапуске интерфейса — а в контейнере userspace-data-plane amneziawg-go
рестартует вместе с приложением, поэтому «сырое» чтение после рестарта
показывает ноль. Чтобы этого не происходило, трафик накапливается инкрементально
и отдельно по каждому клиенту в data/awg_stats.json:
- Значения складываются как дельты между замерами. Если счётчик «ушёл назад» (rx стал меньше предыдущего) — это трактуется как сброс, и всё текущее значение засчитывается как новый трафик. Дельты всегда неотрицательны, поэтому итог может только расти.
- В каждой записи хранится базовая точка (
last_rx/last_tx) — она тоже пишется на диск. После рестарта итог берётся с диска, а маленькое пост-рестарт чтение корректно распознаётся как сброс. Перезапуск программы не может уменьшить или обнулить уже накопленную статистику. - У каждого клиента есть отметка
since— момент, с которого идёт накопление (при первом появлении пира или после очистки). Трафик, накопленный интерфейсом до начала отслеживания, задним числом не засчитывается. - Замер выполняется фоном (раз в 20 c) и попутно при опросе API, под отдельным
мьютексом; запись — атомарно (temp + rename). Битый файл сохраняется как
awg_stats.json.bad, чтобы ошибка парсинга не затёрла данные. POST /api/clients/{id}/stats/reset(кнопка Reset stats) обнуляет накопленное для клиента и заново выставляетsince. Удаление клиента удаляет и его запись статистики.
Безопасность
- Приватные и preshared-ключи не передаются в браузер в JSON-списках —
секреты покидают сервер только в файле
.confпри явном скачивании. - По умолчанию сервер слушает
127.0.0.1. Для доступа извне включите HTTP Basic-аутентификацию, задав переменные окружения:
export AWG_WEB_USER=admin
export AWG_WEB_PASS='длинный-пароль'
sudo -E ./awg_profiler web --addr 0.0.0.0:8080
(за TLS/публичный доступ отвечает обратный прокси, например nginx/caddy).
- Каждая операция сериализуется мьютексом; в веб-режиме внутренние ошибки перехватываются и возвращаются как HTTP-ответ, а не роняют сервер.
Docker-образы
Проект поставляет два независимых образа — оба запускают тот же бинарник и веб-UI, различается только то, откуда берётся сам AmneziaWG-стек:
Dockerfile (по умолчанию) |
Dockerfile.mint (альтернатива) |
|
|---|---|---|
| Базовый образ | alpine:3.20 (рантайм) |
Linux Mint 22 (linuxmintd/mint22-amd64) |
awg / awg-quick |
собираются из исходников (amneziawg-tools) |
пакет из официального ppa:amnezia/ppa |
amneziawg-go (userspace data-plane) |
собирается из исходников | собирается из исходников |
| compose-файл | docker-compose.yml |
docker-compose.mint.yml |
Оба варианта:
- используют userspace data-plane
amneziawg-goвместо kernel-модуля — контейнер не может загрузить модуль ядра,awg-quickавтоматически переключается на userspace через/dev/net/tun, когда/sys/module/amneziawgотсутствует; - требуют
cap_add: NET_ADMINи проброс/dev/net/tun(уже прописано в compose-файлах); - сохраняют состояние в volume'ах:
/data(конфиг, реестр, профили, статистика) и/etc/amnezia/amneziawg(interface.conf+ nft-правила); - внутри контейнера слушают
51820/udp(VPN) и8080/tcp(веб-UI), команда по умолчанию —web --addr 0.0.0.0:8080(переопределяется черезcommand:в compose или аргументомdocker run); наружу же порт8080по умолчанию публикуется только на127.0.0.1хоста (см. compose-файлы) — расширяйте его на все интерфейсы только вместе сAWG_WEB_USER/AWG_WEB_PASS.
Технические особенности реализации
- Работа с JSON-реестром клиентов и статистикой — нативно (
encoding/json), без внешнегоjq.jqвсё ещё ставитсяinstall-deps(используется в ручной отладке конфигов), но в рантайме профилировщика не требуется. awg(genkey/pubkey/genpsk/set/show) иqrencodeвызываются как внешние бинарники.- Случайные значения (ключи, параметры обфускации) берутся из
crypto/rand. - Определение публичного IP — нативный HTTP-клиент (IPv4-only), аналог
curl -sf4.
Тесты
go test ./...