RU Русский | EN English

# AmneziaWG 3.x Installer: Дополнительная информация и настройки Это дополнение к основному [README.md](README.md), содержащее более глубокие технические детали, пояснения и продвинутые опции для скриптов установки и управления AmneziaWG 3.x (3.1 по умолчанию) и 2.0. Пошаговый гайд по развёртыванию на VPS - в [INSTALL_VPS.ru.md](INSTALL_VPS.ru.md). ## Оглавление - [✨ Возможности (Подробно)](#features-detailed-adv) - [🔐 Параметры обфускации (3.1 и 2.0)](#awg2-params-adv) - [Presets](#presets-adv) - [🆕 Третья линия AmneziaWG для self-hosted](#awg3-adv) - [Что добавила 3.1](#awg3-31-adv) - [Какую линию модуля вы получите](#awg3-lines-adv) - [Что 3.0 меняет на проводе, а что нет](#awg3-wire-adv) - [Новые параметры 3.0](#awg3-params-adv) - [Что обязано совпадать, а что нет](#awg3-must-match-adv) - [Три вещи, на которых легко потерять вечер](#awg3-gotchas-adv) - [Профиль 3.1: что установщик включает и что нет](#awg3-not-yet-adv) - [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv) - [⚙️ Детали конфигурации клиента](#config-details-adv) - [AllowedIPs](#allowedips-adv) - [IPv6 устройства, `::/0` и локальная сеть](#client-ipv6-adv) - [Что видно сайту при делении трафика по адресу назначения](#split-detect-adv) - [Изоляция клиентов](#client-isolation-adv) - [IPv6 dual-stack в туннеле (v5.15.0+)](#ipv6-tunnel-adv) - [PersistentKeepalive](#persistentkeepalive-adv) - [DNS](#dns-adv) - [Свой DNS-сервер для клиентов](#own-dns-adv) - [Изменение настроек по умолчанию](#change-defaults-adv) - [🔒 Настройки безопасности сервера](#security-adv) - [Фаервол UFW](#ufw-adv) - [Параметры ядра (Sysctl)](#sysctl-adv) - [Модуль ядра и пространства имён пользователей](#userns-module-adv) - [Fail2Ban (Автоматическая установка)](#fail2ban-adv) - [Смена серверного ключа](#server-key-rotation-adv) - [🧹 Оптимизация сервера](#optimization-adv) - [📋 Примеры конфигурации](#config-examples-adv) - [🖥️ CLI Параметры запуска скриптов](#cli-params-adv) - [install_amneziawg.sh](#install-cli-adv) - [manage_amneziawg.sh](#manage-cli-adv) - [🧑‍💻 Полный список команд управления](#manage-commands-adv) - [🤖 JSON-интерфейс для автоматизации (--json)](#json-api-adv) - [🛠️ Технические детали](#tech-details-adv) - [Архитектура скриптов](#architecture-adv) - [DKMS](#dkms-adv) - [Генерация ключей и конфигов](#keygen-adv) - [🔄 Как обновить скрипты](#update-scripts-adv) - [❓ FAQ (Дополнительные вопросы)](#faq-advanced-adv) - [🩺 Диагностика и деинсталляция](#diag-uninstall-adv) - [Содержимое диагностического отчёта](#diagnostic-report-adv) - [🔧 Устранение неполадок (подробно)](#troubleshooting-adv) - [📊 Статистика трафика (stats)](#stats-adv) - [⏳ Временные клиенты (--expires)](#expires-adv) - [📱 vpn:// URI импорт](#vpnuri-adv) - [📱 MTU и мобильные клиенты](#mtu-mobile-adv) - [🚧 Хостинг недоступен из России (Hetzner): блокировка по AS](#as-blocking-adv) - [🛡️ Активное зондирование (active probing) и обфускация без прокси](#active-probing-adv) - [📋 Совместимость клиентов](#client-compat-adv) - [Какое поколение AmneziaWG понимает клиент](#client-gen-adv) - [🐧 Поддержка Debian](#debian-support-adv) - [🔧 Raspberry Pi и ARM64](#arm-support-adv) - [🐧 Подключение Linux-машины как клиента](#linux-client-adv) - [Раздельный список маршрутов и адрес сервера](#linux-client-loop-adv) - [📦 LXC / Docker через amneziawg-go (userspace)](#lxc-userspace-adv) - [🗄️ AmneziaWG на Synology NAS (DSM)](#synology-adv) - [⚠️ Известные ограничения](#limitations-adv) - [🤝 Внесение вклада (Contributing)](#contributing-adv) - [💖 Благодарности](#thanks-adv) --- > История изменений по версиям: [CHANGELOG.md](CHANGELOG.md) --- ## ✨ Возможности (Подробно) * **AmneziaWG 3.1 по умолчанию:** шифрование заголовков (`HeaderProtectionKey`, свой ключ на каждую установку) и добавочный паддинг (`ContentPaddingAddition`) поверх пакетов-пустышек, паддинга `S1`-`S4` и маскирующего пакета `I1`. AmneziaWG 2.0 ставится по флагу `--protocol=2.0` (для клиентов без 3.1) или автоматически там, где установщик 3.1 не выдаёт (ARM, ядро старее 6.7): [подробнее](#awg3-fallback-adv). * **Нативная генерация:** Ключи генерируются через `awg genkey/pubkey`, конфиги — через Bash-шаблоны, QR — через `qrencode`. Внешняя зависимость от Python/awgcfg.py полностью устранена. * **Автоматическая установка:** Устанавливает AmneziaWG, DKMS модуль, зависимости, настраивает сеть, фаервол, sysctl. * **Возобновляемость:** Использует файл состояния (`/root/awg/setup_state`) для продолжения после обязательных перезагрузок. * **Оптимизация сервера:** * Удаление ненужных пакетов (snapd, modemmanager, и др.) * Hardware-aware настройка swap и сетевых буферов * **Безопасность по умолчанию:** * `UFW`: Политика `deny incoming`, лимит SSH, разрешение VPN-порта. * `IPv6`: По умолчанию отключается через `sysctl` (в вопросе ответ по умолчанию «да», с `--yes` отключается без вопроса; оставить - флаг `--allow-ipv6`). * `Права доступа`: Строгие права (600/700) на все ключи и конфиги. * `Sysctl`: BBR congestion control, защита от спуфинга, оптимизация TCP. * `Fail2Ban`: Автоматическая установка и настройка для SSH. * **Резервное копирование:** Команда `backup` в скрипте управления (включая ключи клиентов). --- ## 🔐 Параметры обфускации (3.1 и 2.0) Эти параметры обфускации есть в обоих профилях, 3.1 и 2.0; различаются только нижние границы `S3`/`S4` и форма `H1`-`H4` (колонка «Профиль 3.1»). Параметры, которые есть только в 3.1 (`HeaderProtectionKey`, `ContentPaddingAddition`), - в разделе [Профиль 3.1](#awg3-not-yet-adv). Все значения генерируются при установке и выдаются клиентам такими же, как на сервере. Источник истины для команд `manage` и для переустановки - живой `/etc/amnezia/amneziawg/awg0.conf`; копия набора в `/root/awg/awgsetup_cfg.init` используется, только когда `awg0.conf` нет, то есть обычно при первой установке. Ключ `HeaderProtectionKey` в init не пишется: он хранится в `awg0.conf` и в `/root/awg/server_hpk.key`. | Параметр | Описание | Профиль 2.0 | Профиль 3.1 | Пример (2.0) | |----------|----------|----------|----------|--------| | `Jc` | Количество junk-пакетов | 3-6 | так же | `5` | | `Jmin` | Мин. размер junk (байт) | 40-89 | так же | `55` | | `Jmax` | Макс. размер junk (байт) | Jmin+50..Jmin+250 | так же | `200` | | `S1` | Padding init-сообщения (байт) | 15-150 | так же | `72` | | `S2` | Padding response-сообщения (байт) | 15-150, S1+56≠S2 | так же | `56` | | `S3` | Padding cookie-сообщения (байт) | 8-55 | 12-55 | `32` | | `S4` | Padding data-сообщения (байт) | 4-27 | 12-27 | `16` | | `H1` | Идентификатор init-сообщения | Диапазон uint32 | `1` | `134567-245678` | | `H2` | Идентификатор response-сообщения | Диапазон uint32 | `2` | `3456789-4567890` | | `H3` | Идентификатор cookie-сообщения | Диапазон uint32 | `3` | `56789012-67890123` | | `H4` | Идентификатор data-сообщения | Диапазон uint32 | `4` | `456789012-567890123` | | `I1` | CPS-пакет маскировки | Теги `` / `` / `` / `` / `` | так же | Пакет формы DNS-ответа, 70-128 байт | | `I2`-`I5` | Доп. CPS / special-junk пакеты, опциональны (переносятся в клиентов) | Теги `` / `` / `` / `` / `` | так же | `` | > Для `I1`-`I5` берите только теги ``, ``, ``, ``, ``: их понимают обе реализации, модуль ядра и amneziawg-go. Тег `` есть только в модуле ядра; на amneziawg-go (macOS, LXC и Docker без модуля, часть роутеров) конфиг с ним не поднимется. **Критические ограничения:** * В профиле 2.0 диапазоны H1-H4 **не должны пересекаться** (гарантируется алгоритмом генерации); генератор выбирает их случайно в пределах 5..2147483647. В профиле 3.1 `H1`-`H4` = 1-4: тип сообщения прячет шифрование заголовков, и случайные диапазоны ничего не добавляют. * `S1 + 56 ≠ S2` — предотвращает одинаковый размер init и response сообщений. * `S3 ≠ S2 + 28` - не даёт совпасть размерам response- и cookie-сообщений. * `S4` выбирается так, чтобы избежать вредных совпадений длины пакета данных с пакетами рукопожатия по модели транспорта 2.0: иначе в профиле 2.0 часть пакетов данных могла бы приниматься за рукопожатие и теряться. Безвредные совпадения генератор допускает. * Совпадать на сервере и клиентах **обязаны** `S1`-`S4` и `H1`-`H4` (в 3.1 ещё и `HeaderProtectionKey`): приёмник срезает этот паддинг и проверяет эти заголовки. В 2.0 `H1`-`H4` задаются диапазонами - диапазоны должны быть одинаковыми с обеих сторон. * А `Jc`/`Jmin`/`Jmax` и `I1`-`I5` совпадать **не обязаны**: это отдельные пакеты-обманки, их шлёт только инициатор рукопожатия, а вторая сторона отбрасывает. Каждый из `I1`-`I5` отправляется, если задан; установщик задаёт только `I1`, поэтому `--no-cps` убирает маскирующий пакет целиком. > `I1`-`I5` (CPS) маскируют рукопожатие под другой протокол - это основа защиты от активного зондирования (active probing). Подробно: [Активное зондирование и обфускация без прокси](#active-probing-adv). ### Presets Presets — это готовые наборы параметров обфускации, оптимизированные для конкретных условий сети. Выбираются при установке через флаг `--preset`. | Preset | Jc | Jmin | Jmax | Когда использовать | |--------|-----|------|------|-------------------| | `default` | 3-6 (случайно) | 40-89 | Jmin + 50..250 | Домашний и проводной интернет, стандартные VPS | | `mobile` | **3** (фиксированный) | 30-50 | Jmin + 20..80 | Мобильные операторы (Tele2, Yota, Мегафон, Таттелеком) | **Установка с preset:** ```bash # Стандартный пресет (по умолчанию) sudo bash install_amneziawg.sh --yes # Мобильный пресет - для SIM-карт, LTE/5G модемов, мобильных роутеров sudo bash install_amneziawg.sh --preset=mobile --yes ``` **Точечные переопределения (`--jc`, `--jmin`, `--jmax`):** Можно переопределить отдельные параметры поверх любого preset: ```bash # Mobile preset, но Jc=4 вместо 3 sudo bash install_amneziawg.sh --preset=mobile --jc=4 --yes # Полностью ручные параметры sudo bash install_amneziawg.sh --jc=2 --jmin=20 --jmax=60 --yes ``` | Флаг | Диапазон | Описание | |------|---------|----------| | `--jc=N` | 0-122 | Количество junk-пакетов; 0 выключает их | | `--jmin=N` | 0-1280 | Минимальный размер junk (байт) | | `--jmax=N` | 0-1280 | Максимальный размер junk (байт), должен быть ≥ Jmin | Потолок `Jc` - 122, а не 128: клиенты на amneziawg-go отправляют junk-пакеты, `I1`-`I5` и пакет рукопожатия одной пачкой, которая вмещает 128 пакетов, и при `Jc + число I + 1` больше 128 падают на первом рукопожатии (amneziawg-go#111). Модуль ядра этим не страдает. Если на работающем сервере `Jc + число I + 1` больше 128 (с одним `I1`, который ставит установщик, это `Jc` от 127), `check`, `diagnose`, `restore`, `add`/`regen` и шаг 6 установщика предупредят об этом: поставьте в `awg0.conf` значение до 122, перезапустите `awg-quick@awg0` и перевыпустите профили через `regen`. Остальные параметры при этом не меняются, а `--force --jc=N` сгенерировал бы их заново. > **Совет:** Если VPN работает на домашнем Wi-Fi, а через мобильную сеть не подключается, сначала проверьте `I1`: разбор и готовое решение в разделе Рукопожатие не собирается на мобильном интернете. На замеренном маршруте уменьшение junk-пакетов рукопожатию не помогло. Остальные случаи мобильных операторов - в FAQ. --- ## 🆕 Третья линия AmneziaWG для self-hosted **Термины.** У AmneziaWG есть поколения протокола, их ещё называют линиями: 1.x, 2.0 (вторая линия) и 3.x (третья; установщик выдаёт её выпуск 3.1). Установщик пишет в конфиги сервера и клиентов один из двух профилей: «профиль 3.1» (по умолчанию) или «профиль 2.0». Модуль ядра и утилиты `awg` тоже бывают второй или третьей линии, и для профиля 3.1 нужны модуль и утилиты третьей линии. **Что получает новая установка.** Профиль 3.1: к обфускации второй линии добавляются шифрование заголовков и добавочный паддинг, состав - в разделе [Профиль 3.1](#awg3-not-yet-adv). Проверить, какое поколение стоит на сервере: `sudo bash /root/awg/manage_amneziawg.sh check` печатает строку «Поколение протокола установки», а `check --json` отдаёт поле `protocol`. В конце июля 2026 команда Amnezia выпустила **AmneziaWG 3.0** и переключила на неё PPA, а 12 августа внутри той же линии вышла **3.1** (тег `v3.1.20260812`), и PPA раздаёт её с того же дня. С версии 6.0.0 установщик по умолчанию выдаёт новой установке **профиль 3.1**: из чего он состоит, разобрано в разделе [Профиль 3.1](#awg3-not-yet-adv), а где вместо него ставится 2.0 - в разделе [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv). Модуль третьей линии на x86 с ядром 6.7 или новее ставился и раньше, и конфиги второй линии на нём продолжают работать. Проверить, что стоит именно у вас: ```bash awg --version # amneziawg-tools v3.1.20260812 cat /sys/module/amneziawg/version # 3.1.20260812 - версия ЗАГРУЖЕННОГО модуля ``` ⚠️ Спрашивайте именно загруженный модуль, а не файл на диске. `modinfo amneziawg | grep ^version` читает метаданные того `.ko`, который выбран на диске, и если на хосте оказались два дерева с модулем одного имени (такое возможно на ARM: закреплённый 2.0 в `extra/` и DKMS-модуль третьей линии в `updates/dkms/`), он назовёт не тот, что работает в ядре. `modinfo` пригодится в одном случае - когда модуль не загружен и `/sys/module/amneziawg/` отсутствует; тогда он покажет, что лежит на диске. `manage check` и `manage diagnose` с v5.25.0 спрашивают загруженный модуль и переходят к `modinfo` только как ко второму пути. ⚠️ Версии пакетов apt на этот вопрос не отвечают. Там `amneziawg-dkms` значится как `1.0.0-0~202608140352+4680320~ubuntu24.04.1`, а `amneziawg-tools` как `1.0.20210914-0~...`: начало строки - это версия упаковки, а настоящее содержимое - в суффиксе с хешем коммита. Две команды выше отвечают прямо. ### Что добавила 3.1 Внутри третьей линии 12 августа 2026 года вышел выпуск `v3.1.20260812`, добавивший ровно два параметра устройства. Установщик их не задаёт, но знать про них стоит: один из них при ручном включении рвёт связь с каждым клиентом, у которого он не включён тоже, независимо от версии этого клиента. | Параметр | Класс | Что делает | |---|---|---| | `RandomTrailers` | 🔴 **двусторонний** | Дописывает случайный хвост к пакетам рукопожатия. Приёмник без этого флага удлинённый пакет **не опознаёт**, поэтому включение только на сервере обрывает связь со всеми клиентами, у которых его нет. | | `DisableCookies` | односторонний | Сервер перестаёт отправлять cookie-ответы, убирая характерный тип сообщения из наблюдаемого трафика. Совпадения сторон не требует. ⚠️ Но в WireGuard эти ответы существуют как защита от флуда рукопожатиями с подменённых адресов, так что вместе с сигнатурой убирается и она. | Совместимость на уровне интерфейса ядра при этом не сломана: `WG_GENL_VERSION` остался прежним, поэтому утилиты линии 3.0 работают с модулем 3.1. ### Какую линию модуля вы получите | Условие | Что ставится | Линия модуля | Профиль без `--protocol` | |---|---|---|---| | x86_64, ядро >= 6.7 | `amneziawg-dkms` из `ppa:amnezia/ppa` | **3.x** | **3.1** | | любая арх., ядро старее 6.7 (Debian 12 с 6.1) | закреплённый модуль из исходников | 2.0 | 2.0, автоматически | | ARM64 / armhf, есть готовый пакет под ваше ядро | наш предсобранный пакет | 2.0 | 2.0, автоматически | | ARM64 / armhf, готового пакета нет, ядро >= 6.7 | `amneziawg-dkms` из PPA | **3.x** | 2.0, автоматически: ARM под третью линию не мерена | Модуль третьей линии - необходимое, но не достаточное условие профиля 3.1: на шаге 3 установщик ещё проверяет утилиты и загруженный модуль, см. [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv). Последняя строка не теория: готовые ARM-пакеты собираются для Raspberry Pi 3/4/5, Ubuntu 24.04 ARM64 и Debian 12/13 ARM64. Ubuntu 26.04 ARM64 в этот список пока не входит, и на таком хосте установщик, не найдя совпадения, уходит на обычный путь DKMS и ставит модуль из PPA, то есть третью версию. На старых ядрах мы выбираем 2.0 **сознательно**, а не потому, что 3.0 там не собирается. Первые сутки после выхода она действительно не собиралась на ядре 6.1, upstream починил это 31 июля, и сейчас сборка проходит. Но именно на старых ядрах линия 3.0 обкатана меньше всего, а закреплённый 2.0 сверяется по неизменяемому коммиту. Порог снимем после отдельной проверки, а не по факту «сборка снова проходит». На ARM установщик сначала пробует предсобранный пакет, и если находит подходящий под ваше ядро, до PPA дело не доходит вовсе. Предсобранные пакеты закреплены на 2.0. Если совпадения нет, дальше решает то же правило, что и на x86: ядро старее 6.7 - закреплённый 2.0 из исходников, ядро новее - модуль из PPA. > ⚠️ **Закреплённая 2.0-линия не обновляется, и это осознанное решение, а не недоделка.** Модуль на закреплённом пути собирается из неизменяемого тега `v1.0.20260725`, а линия `1.0.x` у upstream заморожена - новых выпусков в ней не будет. То же относится к предсобранным ARM-пакетам. > > Что это значит на практике. На Debian 12 со штатным ядром 6.1 и на ARM с подходящим предсобранным пакетом вы получаете проверенный, но зафиксированный модуль. Пути «обновиться до третьей версии обычным `apt upgrade`» для таких хостов нет: установщик держит `amneziawg-dkms` в `apt-mark hold` именно для того, чтобы модуль из PPA не встал рядом вторым деревом с тем же именем. Ничего не ломается и работать не перестаёт - обновления просто не приходят. > > Если третья версия нужна именно на таком хосте, поддерживаемый путь один: получить ядро 6.7 или новее (на Debian 12 это ядро из backports) и переустановить. На x86 после этого начнётся обычный путь PPA, и новая установка получит профиль 3.1. ⚠️ На ARM учтите порядок: предсобранный пакет пробуется первым, поэтому если под новое ядро найдётся готовый пакет, вы снова получите закреплённую 2.0 - третья версия приедет только тогда, когда совпадения не найдётся. А профиль 3.1 на ARM пока не выдаётся вовсе, какой бы модуль ни встал. **Модуль из PPA обновляется вместе с системой, и отката у него нет.** На основном пути (x86_64, ядро 6.7 и новее) `amneziawg-dkms` приходит из PPA и меняется обычным `sudo apt upgrade`, а также при повторном запуске установщика: он обновляет систему на шаге 1. `unattended-upgrades` в штатной настройке пакеты из PPA не ставит (а если при установке прошла очистка пакетов, его на сервере уже нет; очистку отменяют `--keep-packages`, `--no-tweaks` и отказ в вопросе установщика; проверить: `dpkg -s unattended-upgrades`), так что сборка меняется тогда, когда систему обновляете вы. Загруженный модуль остаётся прежним до перезагрузки. PPA хранит только текущую сборку: вытесненная пропадает из архива примерно через сутки, поэтому вернуться на неё средствами apt нельзя. Чтобы самому решать, когда менять сборку, заморозьте пакет: `sudo apt-mark hold amneziawg-dkms` (снять - `sudo apt-mark unhold amneziawg-dkms`); цена в том, что вместе с новыми сборками перестанут приходить и исправления. Повторный запуск установщика (на работающем сервере для этого нужен `--force`) снимает это удержание на шаге 2, после перезагрузки, а сама сборка сменится при следующем `apt upgrade`, поэтому поставьте hold заново, когда установка завершится. Строка версии модуля разные сборки не различает, работающую показывает `cat /sys/module/amneziawg/srcversion`. ### Что 3.0 меняет на проводе, а что нет Ничего из того, что вы уже настроили. Проверено замером: на модуле 3.0 одновременно поднимаются и работают четыре интерфейса с конфигами разных поколений - без единого AWG-параметра, в стиле 1.x, в стиле 2.0 и с параметрами 3.0. Ключевое устройство: `H1`-`H4` внутри модуля стали диапазонами, но интерфейс, где они не заданы, получает диапазоны из одного значения - ровно типы сообщений WireGuard. Это видно и в проводе: | Интерфейс | Что уходит в провод | |---|---| | без AWG-параметров | на смещении 0 байты `01 00 00 00`, то есть обычный WireGuard | | `S1 = 100`, `H1 = 1234567` | на смещении 100 значение `H1`, перед ним junk-пакеты по `Jc` | Скалярное значение `H1 = 12345` из конфига 2.0 разбирается как диапазон из одного числа, и в провод уходит ровно оно. Поэтому апгрейд модуля сам по себе ничего вашим клиентам не ломает. ### Новые параметры 3.0 По сравнению с прошлой версией `amneziawg-tools` добавилось семь ключей конфигурации и **не удалено ни одного**: всё из 2.0 (`Jc`/`Jmin`/`Jmax`, `S1`-`S4`, `H1`-`H4`, `I1`-`I5`) принимается по-прежнему. | Параметр | Что делает | Обязан совпадать у сервера и клиента? | |---|---|---| | `HeaderProtectionKey` | шифрование заголовков ChaCha20 | **да, иначе рукопожатия не будет вовсе** | | `ContentPaddingAddition` | добавочный паддинг внутри шифрованной части | нет | | `RekeyAfterTime` | когда начинать перезаключение ключей | нет | | `RekeyTimeout` | пауза между попытками рукопожатия | нет | | `RejectAfterTime` | когда считать сессию просроченной | нет | | `KeepaliveTimeout` | пауза перед служебным пакетом | нет | | `MaxHandshakeAttempts` | сколько попыток рукопожатия делать | нет | Все семь принимаются и через `awg-quick`: он передаёт в `awg setconf` любые ключи, которые не разбирает сам, так что рукописные конфиги ничего особенного не требуют. 🔴 **Шесть из семи принимают ДИАПАЗОН, а не только одно число, и значение берётся из него случайно при каждом применении.** Это `ContentPaddingAddition`, `RekeyAfterTime`, `RekeyTimeout`, `RejectAfterTime`, `KeepaliveTimeout` и `MaxHandshakeAttempts`: формат `lo-hi`, одиночное число тоже допустимо и означает диапазон нулевой ширины. Проверено в обеих реализациях по исходникам, а не по документации: в модуле ядра они объявлены как `u16_range_t` (`src/device.h`), а выбор делает `u16_range_pick_one()` через `get_random_u32_inclusive()` (`src/type.h`); в `amneziawg-go` это тип `UintRange` с методами `FromString` и `PickOne` (`device/noise-types.go`), а разбор ключей идёт в `device/uapi.go`. Смысл именно в этом: постоянный интервал рукопожатий и keepalive сам по себе был приметой, а диапазон её убирает. Единственное исключение из семи - `HeaderProtectionKey`, это ключ, а не число. ⚠️ Отсюда практическое: если вы задаёте эти параметры руками, помните, что `KeepaliveTimeout = 20-30` это не опечатка и не интервал «от и до» в смысле таймаута, а именно случайный выбор на каждое применение. Установщик из семи задаёт два, `HeaderProtectionKey` и `ContentPaddingAddition` (профиль 3.1, см. [ниже](#awg3-not-yet-adv)), а тайминги не задаёт. Тайминги действуют только на той стороне, где заданы: сверять их с клиентом не нужно, и в профиль клиента скрипт их не переносит, даже если вы вписали их в `awg0.conf` сервера. ### Что обязано совпадать, а что нет Это место чаще всего понимают неправильно. README самого модуля ядра описывает только 1.x/2.0. README `amneziawg-go` описывает и третью линию (защиту заголовков, паддинг, тайминги) и делит параметры на server-side (обязаны совпадать) и client-side (не обязаны), но не говорит, что происходит при расхождении и как это увидеть. Ниже - то, что проверено замером. - **`S1`-`S4` обязаны совпадать.** Это не просто паддинг: приёмник читает тип сообщения **по смещению**, равному своему `S`. Разошлись значения - пакет не опознан. - **`H1`-`H4` должны быть совместимы.** Отправитель берёт значение из своего диапазона, приёмник проверяет, что оно попадает в его. Проще держать их одинаковыми. - **`HeaderProtectionKey` обязан быть одинаковым.** Проверено: ключ только на сервере, только на клиенте или разные ключи - рукопожатия нет вообще, 100% потерь. Это не постепенное ухудшение, а переключатель: как только сервер получил ключ, все пиры без него отваливаются. - **`Jc`/`Jmin`/`Jmax` и `I1`-`I5` совпадать не обязаны.** Пакеты-пустышки и маскировочные пакеты шлёт инициатор рукопожатия, вторая сторона их просто игнорирует. 🔴 **Не включайте `RandomTrailers`, пока не выйдет исправление.** Сам по себе флаг скорость не снижает: на голом конфиге (`Jc = 0`, `S1`-`S4 = 0`, `H1`-`H4 = 1..4`, `I1`-`I5` отсутствуют) измерено **11.94 МБ/с** и с ним, и без него. Падение возникает в сочетании с остальной обфускацией: при `Jc`, `S1`-`S4`, `H1`-`H4` и `I1` вместе с флагом пропускная способность составила **0.09-0.14 МБ/с**, то есть в 85-133 раза меньше. Что измерено по сочетаниям, все значения **при включённом флаге**: `S1`-`S3` вместе с `H1`-`H4` дали 5.60 МБ/с, добавление `S4` уронило до 0.11. Каждая из групп по отдельности - `S4`, `S1`-`S3`, `H1`-`H4`, `Jc`, `I1` - падения не дала: 11.7-11.9 МБ/с. То есть дело не в самих этих параметрах, а в их сочетании с флагом, и отключать обфускацию ради скорости не нужно. Падение воспроизводится и в локальной сети, без выхода в интернет: **44.22 МБ/с без флага против 0.09 с ним**. Значит маршрут ни при чём. Прежнее объяснение через потери пакетов в пути проверено и опровергнуто: потери оказались симптомом, а не причиной. Есть и вторая, отдельная причина держать флаг выключенным. Когда он включён, а диапазоны `H1`-`H3` широкие, приёмник может принимать часть пакетов данных за пакеты рукопожатия и отбрасывать их. Сколько именно, зависит от `S1`-`S4` и `H4`, при части раскладок потерь нет вовсе; на синтетическом наборе с `H3` шириной 3.5% от 2³² терялось 6.7-7.3% пакетов, одинаково на модуле ядра и на amneziawg-go. Падение скорости это не объясняет, это другой эффект. В профиле 3.1 этого установщика (`H1`-`H4` = 1-4 и ключ защиты заголовков) такая доля ничтожна. Разбор и замеры - в [amneziawg-linux-kernel-module#226](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/226). ### Три вещи, на которых легко потерять вечер **`HeaderProtectionKey` требует `S1`-`S4` не меньше 12.** Nonce для шифрования заголовка нигде не передаётся, а берётся из первых 12 байт S-паддинга, поэтому при меньшем значении конфиг отвергается. Ровно 12 подходит, хотя сообщение в ядре говорит «must be more then 12». `amneziawg-go` вдобавок называет параметр со сдвигом на единицу: ошибка про `S0` относится к `S1`, про `S2` - к `S3` ([amneziawg-go#201](https://github.com/amnezia-vpn/amneziawg-go/issues/201)). Сам ключ - 32 байта в base64, то есть строка из 44 символов, которая кончается на `=`; такую выдаёт `awg genkey`. Число или пароль вместо неё конфиг не примет. **Само сообщение по умолчанию не видно.** `awg` печатает только `Unable to modify interface: Invalid argument`, а объяснение уходит в отладочный лог ядра. Чтобы его увидеть: ```bash echo "module amneziawg +p" > /sys/kernel/debug/dynamic_debug/control # повторить неудачную команду, затем посмотреть: dmesg | tail echo "module amneziawg -p" > /sys/kernel/debug/dynamic_debug/control ``` **Параметр нельзя снять через `awg setconf` или `awg syncconf`.** Если убрать строку из конфига и применить его заново, значение останется прежним: для AWG-параметров эти команды работают на добавление. Вернуть интерфейс к чистому состоянию можно только пересозданием, то есть `systemctl restart awg-quick@awg0` (или `awg-quick down` и `up`). Начиная с v5.25.0 скрипты управления это отслеживают и **предупреждают**: они запоминают набор параметров интерфейса, применённый в прошлый раз, и если из `awg0.conf` какой-то параметр пропал, в журнале появляется предупреждение `Из секции [Interface] убрано: S1` вместе с командой, которая доводит снятие до живого интерфейса. Сам перезапуск скрипт **не делает**: он оборвал бы соединения всех клиентов, а решение такой цены принимает человек, а не автоматика. Предупреждение обычно показывается один раз: снимок набора обновляется после успешного применения, а также после `manage restart`, `manage restore` и установки, то есть после всего, что пересоздаёт интерфейс. Если же применение упало, снимок остаётся прежним и предупреждение повторится на следующем запуске - это сделано намеренно, иначе неудача молча погасила бы напоминание о том, что на живом интерфейсе параметр ещё стоит. Значения параметров по-прежнему применяются без перезапуска: `syncconf` меняет их корректно, проблема только в снятии. ### Профиль 3.1: что установщик включает и что нет С версии 6.0.0 новая установка без флага получает профиль 3.1. От профиля 2.0 он отличается так: | Параметр | Профиль 2.0 | Профиль 3.1 | |---|---|---| | `HeaderProtectionKey` | нет | случайный ключ на каждую установку, один на сервер и всех его клиентов | | `ContentPaddingAddition` | нет | `32-128` | | `H1`-`H4` | случайные непересекающиеся диапазоны | `1`, `2`, `3`, `4` | | `S3` / `S4` | от 8 / от 4 | от 12 / от 12 | | `Jc`/`Jmin`/`Jmax`, `S1`/`S2`, `I1` | как раньше | как раньше | - **`H1`-`H4` стоят на 1-4 намеренно.** Ключ шифрует заголовок, и тип сообщения в проводе больше не виден при любых `H`: случайные диапазоны ничего не добавляют. Уникальной каждую установку теперь делает ключ. - **`S3` и `S4` от 12**, потому что первые 12 байт S-паддинга служат nonce для шифрования заголовка (подробности - в разделе [Три вещи, на которых легко потерять вечер](#awg3-gotchas-adv)). - **Ключ** хранится в секции `[Interface]` серверного `awg0.conf` и копией в `/root/awg/server_hpk.key`. `manage` вписывает его в каждый клиентский профиль и в ссылку `vpn://`, `backup` и `restore` переносят его вместе с конфигом. Сменить ключ - значит перевыпустить профили всех клиентов: клиент со старым ключом не подключится, и ошибки при этом не увидит. - **`ContentPaddingAddition`** односторонний, совпадения сторон не требует. Дефект, из-за которого паддинг раньше не включали (простаивающий туннель переустанавливал соединение каждые 15 секунд вместо примерно 147, [issue #186](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/186)), исправлен upstream 5 августа 2026 ([PR #208](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/pull/208)) и проверен на стенде. Чего в профиле нет и почему: - **`RandomTrailers`** двусторонний, и вместе с остальной обфускацией роняет скорость в десятки раз (замер - в разделе [Что обязано совпадать](#awg3-must-match-adv)). Не включаем, пока не выйдет исправление. - **`DisableCookies`** вместе с сигнатурой cookie-ответов убирает и защиту от флуда рукопожатиями с подменённых адресов (см. [Что добавила 3.1](#awg3-31-adv)). - **Параметры таймингов** односторонние и безопасны, но без отдельного замера пользы от них мало, поэтому установщик их не задаёт. Строк `RandomTrailers` и `DisableCookies` в конфигах нет вовсе, даже со значением `off`. ### Где вместо 3.1 ставится 2.0 Установщик проверяет машину дважды. На шаге 0 - архитектуру и ядро: профиль 3.1 выдаётся только на x86_64 с ядром 6.7 или новее. На шаге 3, когда пакеты уже стоят и перезагрузки позади, - утилиты `awg` и загруженный модуль: модуль проверяется пробой, то есть профиль применяется к временному интерфейсу и читается обратно. | Ситуация | Что делает установщик | |---|---| | поколение не выбрано, машина не подходит | ставит 2.0 сам: причина выводится в лог отдельным блоком и повторяется в итоговом отчёте. На шаге 3 он сначала так же проверяет на временном интерфейсе набор 2.0 и, если модуль его не принял, останавливается, не трогая файл настроек | | утилиты `awg` второй линии при модуле третьей (`tools_old`) | набор 2.0 через такие утилиты тоже не применяется (они не задают диапазоны `H1`-`H4`), поэтому установка останавливается и называет команду обновления `amneziawg-tools`; файл настроек не тронут. При модуле второй линии набор 2.0 проходит пробу, и установщик ставит 2.0 | | `--protocol=3.1`, машина не подходит | останавливается и называет код причины | | `--protocol=2.0` | ставит 2.0, проверки третьей линии не нужны | | сервер уже выдал профили (дошёл до шага 6) | поколение не меняет. Если сервер 3.1 перестал проходить проверку, установщик называет причину и лечение (обновить утилиты или модуль, загрузиться в подходящее ядро); удаление он называет только последним вариантом | Коды причин: `kernel`, `arm`, `arch_unsupported`, `arch_unknown` (проверяются на шаге 0 и ещё раз на шаге 3); `tools_old`, `module_line2`, `module_probe_failed` (шаг 3). Поколение новой установки без `--protocol` по системам, на штатном ядре: | Система | Штатное ядро | x86_64 | ARM | |---|---|---|---| | Ubuntu 24.04 | 6.8 | 3.1 | 2.0, код `arm` | | Ubuntu 26.04 | 7.0 | 3.1 | 2.0, код `arm` | | Debian 13 | 6.12 | 3.1 | 2.0, код `arm` | | Debian 12 | 6.1 | 2.0, код `kernel` | 2.0, код `arm` | Установщик смотрит на работающее ядро, а не на штатное: система на x86_64, загруженная с ядром 6.7 или новее (например, из backports), получает 3.1; на ARM поколение 2.0 при любом ядре. Это проверка шага 0. На шаге 3 установщик может перейти на 2.0 и на подходящей системе, если утилиты `awg` или модуль не понимают третью линию или проверить модуль не удалось (коды `tools_old`, `module_line2`, `module_probe_failed`). Поколение и то, как оно выбрано, записываются в `/root/awg/awgsetup_cfg.init`: `AWG_PROTOCOL` (`2.0` или `3.1`), `AWG_PROTOCOL_SOURCE` (`default`, если поколение взято по умолчанию, `explicit`, если флагом) и `AWG_PROTOCOL_FALLBACK` (код причины, если установщик перешёл на 2.0 сам). У сервера, поставленного до версии 6.0.0, нет `AWG_PROTOCOL_SOURCE`, а маркер `AWG_PROTOCOL` равен `2.0` (с v5.32.0) или отсутствует (раньше); в обоих случаях сервер читается как 2.0. **Сменить поколение работающего сервера** можно только переустановкой: `--uninstall`, затем установка с нужным `--protocol`. Профили всех клиентов при этом выдаются заново, поэтому решать лучше до установки. Отдельный разбор ситуации на ядрах старше 6.7 - в разделе Поддержка Debian. --- ## ⚙️ Детали конфигурации клиента ### AllowedIPs Определяет, какой трафик **клиент** направляет в VPN-туннель. 1. **Режим 1: Весь трафик (`0.0.0.0/0`) - по умолчанию** * Весь IPv4 трафик клиента -> VPN, плюс `::/0`, чтобы IPv6 устройства не шёл мимо туннеля (без `--allow-ipv6-tunnel`; с ним правила другие, см. раздел про dual-stack ниже). * Ровно эту пару маршрутов приложение Amnezia считает полным туннелем: на ней работает его собственная страница раздельного туннелирования, а `awg-quick` на Linux включает policy-routing и не зацикливает маршруты. * Цена: локальная сеть уходит в туннель вместе со всем остальным. Останется ли она доступной, решает клиент, а не конфиг. 2. **Режим 2: Список Amnezia + DNS** * Список публичных IP-диапазонов + DNS `1.1.1.1`, `8.8.8.8`. Частные сети (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`) остаются вне туннеля. * **Цель:** оставить локальную сеть вне туннеля. По охвату ПУБЛИЧНОГО IPv4 это тот же полный туннель, отдельного выигрыша по обходу блокировок у него нет; вне списка остаются частные сети, служебный `0.0.0.0/8` и multicast. * Цена: приложение Amnezia видит список, не равный `0.0.0.0/0, ::/0`, считает раздельную маршрутизацию уже настроенной на сервере и выключает свою страницу; на Linux `awg-quick` такой конфиг может дать петлю маршрутизации. * IPv6: без `--allow-ipv6-tunnel` к этому списку дописывается `2000::/3` (весь глобальный IPv6), а в `Address` клиента служебный адрес вида `fddd:2c4:2c4:ffff::a09:905/128`. IPv6 устройства в интернет уходит в туннель и там гаснет, а локальная сеть остаётся вне туннеля целиком, и по IPv4, и по IPv6. Не `::/0` потому, что с ним клиент AmneziaWG для Windows включает блокировку всего трафика мимо туннеля, и локальная сеть пропадает. Нужен живой IPv6 устройства - смотрите [IPv6 устройства, `::/0` и локальная сеть](#client-ipv6-adv). 3. **Режим 3: Пользовательский (Split-Tunneling)** * Только трафик к указанным сетям -> VPN. * Пример: `192.168.1.0/24,10.50.0.0/16` * `::/0` не дописывается, пока список не покрывает весь публичный IPv4: IPv6 устройства идёт мимо туннеля напрямую. **Калькулятор AllowedIPs:** [WireGuard AllowedIPs Calculator](https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/). ### IPv6 устройства, `::/0` и локальная сеть `--disallow-ipv6` и ключ `DISABLE_IPV6` в `awgsetup_cfg.init` выключают IPv6 на самом сервере (sysctl хоста). IPv6 вашего устройства они не трогают и не решают, попадёт ли в клиентский `AllowedIPs` маршрут `::/0`. Это решает режим маршрутизации: - **полный туннель** без `--allow-ipv6-tunnel`: режим 1 получает `::/0`, режим 2 получает `2000::/3` и служебный IPv6-адрес. IPv6 устройства уходит в туннель, дальше не идёт, и устройство переходит на IPv4. Пока VPN включён, не открываются ресурсы, доступные только по IPv6; в режиме 1 недоступен и локальный IPv6 домашней сети, в режиме 2 он остаётся доступным; - **свой список сетей** (режим 3, `--route-custom`) `::/0` не получает, если не покрывает весь публичный IPv4. IPv6 устройства идёт мимо туннеля со своим адресом; - **с `--allow-ipv6-tunnel`** правила другие: полный туннель получает `::/0`, только если у сервера есть нативный IPv6, и тогда IPv6 устройства идёт через VPN. Без нативного IPv6 клиенту достаётся лишь туннельная подсеть, и глобальный IPv6 устройства снова идёт мимо туннеля. Подробно - [IPv6 dual-stack в туннеле](#ipv6-tunnel-adv). - **режим 2 с `--client-ipv6-direct`** (ключ `CLIENT_IPV6_DIRECT=1` в `awgsetup_cfg.init`): ни IPv6-маршрута, ни служебного адреса. IPv4 идёт через туннель, IPv6 устройства напрямую через провайдера, локальная сеть доступна. Цена: сайты, открытые по IPv6, видят настоящий адрес устройства, а ресурс, заблокированный у провайдера и доступный по IPv6, остаётся заблокированным. В режиме 1 ключ не допускается (без `::/0` iOS AmneziaVPN не поднимает туннель), вместе с `--allow-ipv6-tunnel` тоже, в режиме 3 он ничего не меняет. Выданным клиентам маршрут снимает обычный `manage regen`, ручные маршруты он не трогает; после него профили нужно импортировать заново. Выключить: строка `CLIENT_IPV6_DIRECT=0` в `awgsetup_cfg.init` и снова `regen`. `manage regen` дописывает IPv6-маршрут и в уже выданные профили полного туннеля, если в их `AllowedIPs` нет ни одного IPv6-маршрута, в том числе в списки, поправленные через `modify`, а профилям режима 2, выданным с `::/0`, заменяет его на `2000::/3`. Как это выглядит со стороны сайтов и как проверить с устройства - в разделе [Что видно сайту при делении трафика по адресу назначения](#split-detect-adv). ### Что видно сайту при делении трафика по адресу назначения Деление по адресу назначения выбирает выход для соединения по тому, куда оно направлено. Так устроены [каскад из двух серверов](CASCADE.md), [схема с WARP для российского сегмента](WARP-RU.md) и клиентский список `AllowedIPs`, из которого часть сетей исключена намеренно - например, чтобы российские сайты открывались мимо VPN (это режим 3 выше; режим 2 сюда не относится, он отправляет в туннель практически весь публичный IPv4). Адрес посетителя сайт узнаёт не только из соединения. На странице может работать скрипт, который спрашивает адрес у стороннего сервиса определения IP - а запрос к сервису идёт уже по другому адресу, значит может уйти и другим плечом, чем сам сайт. Тогда сервис ответит адресом того выхода, которым до него дошли, скрипт передаст ответ сайту, и у сайта окажется два разных адреса: source IP соединения и то, что сообщил скрипт. Расхождение возникает не всегда: всё решает то, по какую сторону деления попал сам сервис. Оказался на том же плече, что и сайт - адрес будет один. Загвоздка в том, что выбираете это не вы, а по цифрам ниже видно, что в проверенной выборке почти все такие сервисы лежали по «зарубежную» сторону. Следствия у трёх схем разные: - **клиентский список с исключениями.** Сайт видит домашний адрес, а запрос к сервису уходит через туннель, так что сайту достаются оба адреса - домашний и серверный; - **каскад.** Сайт видит адрес входного сервера, скрипт сообщит адрес зарубежного выхода. Домашний адрес при этом не раскрывается: оба адреса ваши серверные (при условии, что IPv6 устройства не идёт мимо туннеля - см. ниже); - **схема с WARP.** Сайт видит адрес Cloudflare, а скрипт - адрес самого сервера, то есть ровно тот адрес дата-центра, от которого схема и уводила. Дописать сервисы определения адреса в список исключений - путь ненадёжный. Проверка 7 августа 2026 против снимка российских сетей в репозитории (`cascade/ru.zone`, 8626 сетей): взял 24 домена популярных сервисов такого рода, разрешил каждый через два резолвера (`dig @8.8.8.8` и `@77.88.8.8`) и прогнал полученные адреса по снимку. - внутри снимка оказались два домена - `internet.yandex.ru` и `ipinfo.yandex.ru`, то есть один и тот же сервис под двумя именами, с общим адресом. Остальные 22 лежали вне российских сетей, значит запрос к ним уходит «зарубежным» плечом; - имя в зоне `.ru` о самом адресе не говорит ничего: `2ip.ru` и `myip.ru` отвечали адресами, которых в снимке нет; - адреса вообще непостоянны. `api.ipify.org` за одни сутки отдал три разных адреса, и разные резолверы отвечают по-разному: это anycast за Cloudflare. Прописать такое в список один раз нельзя. Проверку легко повторить: адреса из `dig` прогнать по `cascade/ru.zone` модулем `ipaddress` из стандартной библиотеки Python. ⚠️ Мерилось против того снимка, которым пользуется каскад. У схемы с WARP список свой - BGP-фид antifilter, и его содержимое я так не проверял: механика от этого не меняется, но конкретные числа к нему не относятся. Чего эти цифры НЕ доказывают. Насколько часто сайты действительно сравнивают адрес соединения с тем, что сообщил скрипт, я не измерял. И само расхождение доказательством VPN не является: у dual-stack посетителя без всякого VPN сайт может открыться по IPv6, а сервис определения адреса ответить по IPv4. Проверено здесь только то, что при делении трафика расхождение может возникнуть и что снаружи его видно. Если сайт должен видеть один и тот же адрес, деление по адресу назначения этого не гарантирует, где бы оно ни стояло. Убирает деление полный туннель (`--route-all`): тогда весь трафик уходит одним выходом. Оговорка: разные адреса IPv4 и IPv6 у одного и того же сервера при этом остаться могут, но это обычная картина для любого dual-stack подключения и признаком деления трафика не является. А если адрес нужен именно российский - значит и сервер нужен в России. **IPv6 - отдельный уровень, и его легко перепутать.** В гайдах фраза «IPv6 выключен, установщик так и ставит по умолчанию» означает IPv6 **на сервере** (sysctl хоста). IPv6 **на вашем устройстве** установщик не трогает вовсе, а деление трафика к нему не применяется: и список российских сетей у каскада, и BGP-фид у схемы с WARP содержат только IPv4 (в снимке `cascade/ru.zone` IPv6-записей нет ни одной). Пойдёт ли IPv6 устройства мимо туннеля, решает не схема, а то, попал ли в `AllowedIPs` IPv6-маршрут (`::/0` или `2000::/3`): - **полный туннель без `--allow-ipv6-tunnel`** - сюда попадают и дефолтный режим «Весь трафик» (`--route-all`), и режим «Amnezia»: клиент получает рядом с IPv4-маршрутами IPv6-маршрут (`::/0` в режиме «Весь трафик», `2000::/3` со служебным адресом в режиме «Amnezia»), и IPv6 устройства уходит в туннель. Сам туннель IPv6 не несёт, поэтому дальше такой трафик не идёт - но и мимо VPN не утекает. Обратная сторона: пока VPN включён, ресурсы, доступные ТОЛЬКО по IPv6, недоступны, а в режиме «Весь трафик» и локальный IPv6 домашней сети уходит в туннель (в режиме «Amnezia» локальная сеть остаётся доступной и по IPv4, и по IPv6); - **раздельная маршрутизация** (режим 3, свой список сетей через `--route-custom`): `::/0` не добавляется, пока список не покрывает весь публичный IPv4, иначе сломалось бы само деление. IPv6 устройства идёт мимо туннеля со своим настоящим адресом, и тогда сайту не нужны никакие скрипты - он видит этот адрес напрямую; - **включён `--allow-ipv6-tunnel`**: правила другие и зависят от того, есть ли у сервера нативный IPv6. Единственное их описание - [IPv6 dual-stack в туннеле](#ipv6-tunnel-adv); там же случай, когда клиенту достаётся только туннельная ULA, а глобальный IPv6 устройства снова идёт мимо. > **Профили, выданные до v5.31.0, остаются со старым списком.** Режим «Amnezia», бывший тогдашним дефолтом, получил `::/0` в v5.31.0; до неё `::/0` доставался только режиму «Весь трафик», и IPv6 устройства уходил мимо туннеля. Перевыпуск раздаёт исправление уже выданным клиентам: `sudo bash /root/awg/manage_amneziawg.sh regen`, затем переимпортировать профили на устройствах. Индивидуальные `AllowedIPs`, выставленные через `modify`, при этом сохраняются. Клиенту, выданному с `--allow-ipv6-tunnel`, обычный перевыпуск `::/0` не доставит - его IPv6-часть тоже считается индивидуальной настройкой; для такого клиента нужен `regen --reset-routes`, и установщик печатает эту подсказку сам. Профили режима «Amnezia», выданные с `::/0`, тот же `regen` переводит на `2000::/3` со служебным адресом: с `::/0` клиент AmneziaWG для Windows отрезал локальную сеть. Заменяется `::/0` у списка, IPv4-часть которого совпадает с текущим списком сервера (именно так его писал установщик), как бы этот список ни был задан. `::/0` при любом другом списке и у клиента с `--allow-ipv6-tunnel` остаётся как есть; если `::/0` остался у полного туннеля, `regen` предупреждает и подсказывает, как перейти на `2000::/3`: на сервере в режиме «Amnezia» через `regen --reset-routes <имя>`, в остальных режимах через `modify`. Проверка с подключённого устройства: `curl -6 ifconfig.co`. Смотреть надо не на факт ответа, а на сам адрес - при работающем IPv6 в туннеле ответ тоже придёт. Вернулся ваш домашний адрес - значит IPv6 идёт мимо туннеля. Нужна гарантия, что мимо не идёт ничего, - выключайте IPv6 на самом устройстве: серверный фильтр здесь не поможет, прямой IPv6-трафик до сервера просто не доходит. ### Изоляция клиентов По умолчанию клиенты VPN не видят друг друга: сервер добавляет в `PostUp`/`PostDown` конфига `awg0.conf` правило `iptables -I FORWARD -i awg0 -o awg0 -j DROP` (и симметричное `ip6tables`, если включён IPv6-туннель) - оно рвёт трафик между пирами до общего `ACCEPT`, независимо от режима маршрутизации. До этой настройки изоляция была случайным побочным эффектом режима: режим «Amnezia» и свой список сетей изолировали клиентов только потому, что в их `AllowedIPs` не было маршрута к соседям (подсеть туннеля в список не входит), `--route-all` не изолировал вовсе, а dual-stack клиенты в этих режимах всё равно оставались достижимы друг для друга по IPv6-подсети туннеля. **Отключение:** флаг `--isolation=off` при установке (или ответ `n` на интерактивный вопрос «Изолировать клиентов VPN друг от друга?» при первом запуске без `--yes`). DROP-правило не добавляется, а подсеть туннеля дописывается в `AllowedIPs` клиентов (режимы 2/3 - режим 1 с `0.0.0.0/0` уже покрывает её), так что устройства видят друг друга внутри VPN. **Как переключить на уже установленном сервере:** ```bash sudo bash ./install_amneziawg.sh --force --isolation=off # или --isolation=on ``` Настройка сохраняется в `awgsetup_cfg.init` (ключ `CLIENT_ISOLATION`). Как и смена режима маршрутизации, смена изоляции переустановкой не трогает уже выпущенные клиентские конфиги - им нужен явный перевыпуск: `sudo bash /root/awg/manage_amneziawg.sh regen --reset-routes` (инсталлятор печатает эту подсказку после переустановки со сменой режима). **Устаревшие конфиги.** Конфиг без ключа `CLIENT_ISOLATION` (созданный до появления этой настройки) трактуется как изолированный (`1`) - это и есть прежнее поведение режимов со списком сетей по умолчанию, никаких сюрпризов при переустановке без `--isolation`. ### IPv6 dual-stack в туннеле (v5.15.0+) По умолчанию туннель работает только по IPv4. Начиная с v5.15.0 можно дополнительно включить IPv6 внутри туннеля - клиенты получают IPv6-адрес рядом с IPv4 (dual-stack). > **IPv6 в IPv4-only режиме (по умолчанию).** Когда туннель работает только по IPv4, IPv6-трафик вашего устройства идёт напрямую, мимо VPN, - так и задумано: IPv4-only туннель по определению не несёт IPv6, и сервер на это не влияет (это свойство режима, а не утечка серверной стороны). Одна оговорка: сказанное верно для раздельной маршрутизации (режим 3, свой список сетей). В полном туннеле - а это и дефолтный `--route-all`, и режим «Amnezia» - клиент получает IPv6-маршрут рядом с IPv4-маршрутами, поэтому IPv6 устройства уходит в туннель и там глохнет, а не идёт напрямую - разбор в разделе [Что видно сайту при делении трафика по адресу назначения](#split-detect-adv). Нужен IPv6 в туннеле - включите `--allow-ipv6-tunnel` (ниже). Нужна, наоборот, гарантия, что ничего не идёт мимо VPN, - отключите IPv6 на самом устройстве: серверный фильтр тут не поможет, потому что прямой IPv6-трафик до сервера просто не доходит. **Когда включается:** только при явном флаге `--allow-ipv6-tunnel` у `install_amneziawg.sh`. Без флага поведение идентично предыдущим версиям. Это отдельная настройка от `--allow-ipv6` / `--disallow-ipv6`, которые управляют IPv6 на уровне хоста (sysctl) и не меняются. **Взаимодействие с `--disallow-ipv6`.** Туннельному IPv6 нужен форвардинг IPv6 на хосте, поэтому при сочетании `--allow-ipv6-tunnel` с `--disallow-ipv6` флаг туннеля побеждает: установщик пишет предупреждение в лог и оставляет форвардинг IPv6 на хосте включённым. Это не происходит молча. **Маршрутизация IPv6 повторяет выбранный режим IPv4 (intent-mirroring).** Когда включён `--allow-ipv6-tunnel`, набор `AllowedIPs` клиента для IPv6 зеркалит режим IPv4: - **Полный туннель** (дефолтный режим «Весь трафик» или «Amnezia» - оба покрывают маршрутами весь публичный IPv4): при нативном IPv6 на сервере к IPv4-маршрутам добавляется `::/0`, и весь IPv6-трафик идёт в интернет через VPN; без нативного IPv6 добавляется туннельная подсеть `fddd:2c4:2c4:2c4::/64` - IPv6 работает только между пирами внутри туннеля. - **Split-tunnel** (кастомный список через `--route-custom`): IPv4-список сохраняется без изменений, а к нему добавляется ТОЛЬКО туннельная ULA-подсеть `fddd:2c4:2c4:2c4::/64`. `::/0` не добавляется никогда - перехватывать весь IPv6 в split-режиме нельзя, это сломало бы раздельную маршрутизацию. IPv6 в split-туннеле доступен между пирами, но в IPv6-интернет не выходит. > Историческая заметка: в v5.15.0 dual-stack всегда подразумевал full-tunnel (split-tunnel с IPv6 вёл себя иначе). Начиная с v5.15.1 split-tunnel и IPv6 сочетаются корректно по правилам выше. Если клиент создавался на v5.15.0, пересоздайте его (`manage remove` + `add`), чтобы получить актуальный `AllowedIPs`. **Подсеть:** приватная ULA `fddd:2c4:2c4:2c4::/64`. Сервер занимает `::1`, клиенты получают `::2`, `::3` и т.д. зеркально нумерации IPv4. Подсеть можно переопределить до первого запуска через `IPV6_SUBNET=` в `/root/awg/awgsetup_cfg.init`. **Как определяется нативный IPv6 на сервере.** Скрипт считает, что у сервера есть маршрутизируемый в интернет IPv6, только если выполнены ОБА условия: 1. есть глобальный IPv6-адрес вне диапазона ULA (`fc00::/7`, то есть не `fddd:...`) - проверка `ip -6 addr show scope global`; 2. есть IPv6-маршрут по умолчанию - проверка `ip -6 route show default`. ULA-адрес сам по себе имеет scope global, но в интернет не маршрутизируется, поэтому одного адреса мало - нужен и дефолтный маршрут. Если хотя бы одно условие не выполнено, сервер считается без нативного IPv6: клиенту выдаётся туннельная ULA вместо `::/0` (по правилам маршрутизации выше), и в лог выводится предупреждение. Туннель при этом полностью работоспособен по IPv4. **Как добавить к существующей установке.** Запустите установщик повторно с `--force` и флагом туннеля: ```bash sudo bash ./install_amneziawg.sh --force --allow-ipv6-tunnel # для EN-версии: sudo bash ./install_amneziawg_en.sh --force --allow-ipv6-tunnel ``` `--force` обязателен: без него запуск на уже работающем сервере прерывается idempotency-гардом и флаг игнорируется. Именно `--force` заново рендерит серверный конфиг как dual-stack (`[Interface] Address`, sysctl, PostUp с ip6tables). Без него существующая установка остаётся без изменений, и сервер так и не получает IPv6. Одной только записи `ALLOW_IPV6_TUNNEL=1` в `/root/awg/awgsetup_cfg.init` недостаточно - она не перерендеривает серверный конфиг. Уже выданные IPv4-only клиенты при этом не меняются. Чтобы дать IPv6 такому клиенту, пересоздайте его - только при пересоздании серверу выделяется IPv6 для этого клиента: ```bash sudo bash /root/awg/manage_amneziawg.sh remove <имя> sudo bash /root/awg/manage_amneziawg.sh add <имя> ``` Затем заново импортируйте новый `.conf` на устройство. Обычный `regen` здесь не поможет: он зеркалит адреса из записи `[Peer]` на сервере, а у старого клиента IPv6 в ней ещё нет, так что конфиг останется IPv4-only. `manage list` корректно показывает смешанное состояние (dual-stack рядом с IPv4-only). **Устранение неполадок:** - **Конфликт ULA-подсети.** Если `fddd:2c4:2c4:2c4::/64` уже используется в вашей сети, задайте другую ULA-подсеть через `IPV6_SUBNET=` до установки. Кроме `fddd:2c4:2c4:ffff::/64`: этот префикс занят под сток IPv6 режима маршрутизации 2, и установщик с таким значением остановится. - **IPv6 не маршрутизируется в интернет.** Проверьте оба признака нативного IPv6: глобальный адрес вне ULA (`ip -6 addr show scope global`) И маршрут по умолчанию (`ip -6 route show default`). Если нет хотя бы одного - выход в IPv6-интернет невозможен, это ожидаемое поведение, туннель работает по IPv4. Если оба признака есть, проверьте правило ip6tables MASQUERADE и форвардинг (`sysctl net.ipv6.conf.all.forwarding`). - **Откат / очистка IPv6.** Выключение `ALLOW_IPV6_TUNNEL=0` не удаляет уже добавленные dual-stack записи `AllowedIPs` из `awg0.conf`. Для полной очистки: `awg-quick down awg0; sed -i 's|, fddd:[^/]*/[0-9]*||g' /etc/amnezia/amneziawg/awg0.conf; awg-quick up awg0`. ### PersistentKeepalive * **Значение по умолчанию:** `33` секунды. * Поддерживает UDP-сессию через NAT. * **Изменение:** `sudo bash /root/awg/manage_amneziawg.sh modify <имя> PersistentKeepalive 25` ### DNS * **Значение по умолчанию:** `1.1.1.1, 1.0.0.1` (Cloudflare, основной + резервный). * DNS-сервер для клиента внутри VPN. * **Изменение:** `sudo bash /root/awg/manage_amneziawg.sh modify <имя> DNS "8.8.8.8,1.0.0.1"` ### Свой DNS-сервер для клиентов (Pi-hole, AdGuard Home, Blocky) Блокировщик рекламы или свой резолвер можно поднять прямо на VPN-сервере и выдать клиентам в качестве DNS адрес сервера в туннеле. Установщик такой сервис не ставит, но и не мешает ему. Если что-то из списка ниже пропустить, схема не заработает, причём без единой ошибки: 1. **Сервис слушает адрес сервера в туннеле, взятый из конфигурации.** По умолчанию это `10.9.9.1`, но с `--subnet` адрес другой. Свой покажет `ip -4 addr show awg0` или строка `Address` в `/etc/amnezia/amneziawg/awg0.conf`. В командах ниже подставляйте его вместо `10.9.9.1`. 2. **Этот адрес выдан клиентам как DNS:** `sudo bash /root/awg/manage_amneziawg.sh modify <имя> DNS "10.9.9.1"` для каждого клиента. Чтобы новые клиенты сразу получали этот адрес, задайте `CLIENT_DNS` в `awgsetup_cfg.init`, см. [Изменение настроек по умолчанию](#change-defaults-adv). 3. **Адрес входит в `AllowedIPs` клиента.** Полный туннель (`0.0.0.0/0` в строке `AllowedIPs` клиентского конфига, режим по умолчанию с v5.34.0) его покрывает. Список режима 2 пускает частные сети мимо туннеля намеренно, а в своём списке режима 3 адреса нет, пока вы его не впишете. Это при включённой изоляции клиентов, она тоже по умолчанию. Тогда запрос идёт мимо туннеля и до сервера не доходит, а устройство может остаться без DNS или молча спросить DNS провайдера: блокировка выглядит настроенной, но не работает. Проще всего добавить адрес сервера в список клиента: ```bash # текущий список: всё после "AllowedIPs = ", вместе с IPv6-записями sudo sed -n 's/^AllowedIPs = //p' /root/awg/<имя>.conf sudo bash /root/awg/manage_amneziawg.sh modify <имя> AllowedIPs "<текущий список>, 10.9.9.1/32" ``` Новым клиентам адрес нужно добавлять так же. Обычный `regen` такой список сохраняет, `regen --reset-routes` его сбросит. 4. **Порт 53 открыт только на `awg0`.** Если UFW включён (`sudo ufw status verbose` покажет `Default: deny (incoming)`), входящие закрыты, и без правила запросы из туннеля отбрасываются: `sudo ufw allow in on awg0 to any port 53`. Правило без `in on awg0` откроет резолвер всему интернету. Если сервис работает в Docker, UFW его опубликованные порты не фильтрует, поэтому порт нужно публиковать только на адрес туннеля: `-p 10.9.9.1:53:53/udp -p 10.9.9.1:53:53/tcp`. 5. **Файлы, скопированные с Windows, очищены от `CRLF`:** `sed -i 's/\r$//' <файл>`. Возврат каретки в конце строки списка может стать частью доменного имени, и такая строка перестанет блокировать. После правки клиента его конфиг на устройстве нужно импортировать заново. Разбор этих граблей - от @Cueuler в [обсуждении #237](https://github.com/bivlked/amneziawg-installer/discussions/237). ### Изменение настроек по умолчанию **DNS новых клиентов** задаётся строкой `export CLIENT_DNS='...'` в `/root/awg/awgsetup_cfg.init`. Установщик пишет её туда пустой; впишите значение между кавычками, например `export CLIENT_DNS='10.9.9.1'`. На установках до этой версии строки нет, добавьте её в конец файла. Значение - IP-адреса через запятую. Его получают клиенты, созданные после правки (`manage add`), и клиент, чей конфиг `regen` восстанавливает с нуля. Уже выданные конфиги не меняются: `regen` сохраняет их DNS, поменять его можно командой `modify <имя> DNS ...`. Невалидное значение молча не подменяется: `add` и установщик откажут и напишут, что не так, а `regen` существующих клиентов работает как прежде. Пустое значение означает `1.1.1.1, 1.0.0.1`. Переустановка с `--force` строку сохраняет. **PersistentKeepalive** отдельной настройки не имеет: новые клиенты получают 33, у клиента значение меняется так: ```bash sudo bash /root/awg/manage_amneziawg.sh modify <имя> PersistentKeepalive 25 ``` **Параметры обфускации вручную** (`Jc`/`Jmin`/`Jmax`, `S1`-`S4`, `H1`-`H4`, `I1`-`I5`). Правьте их в `/etc/amnezia/amneziawg/awg0.conf`: оттуда их берут `add`, `regen` и переустановка с `--force`. Копия в `/root/awg/awgsetup_cfg.init` используется, только когда `awg0.conf` нет, то есть обычно при первой установке. Её можно поправить заодно, чтобы файлы не расходились, но правка только в ней не дойдёт ни до сервера, ни до клиентов (`manage` об этом предупредит). 1. Поменяйте значение в секции `[Interface]` файла `awg0.conf`. Имена ключей пишите ровно как в файле (`Jc`, `Jmin`, `Jmax`, `S1` и так далее; `I1`-`I5` только заглавными). По желанию впишите то же значение и в `awgsetup_cfg.init` (строка `export AWG_S1='...'` и так далее). 2. Перезапустите сервис: `sudo systemctl restart awg-quick@awg0`. Без перезапуска снятый параметр остаётся на живом интерфейсе, см. [Три вещи, на которых легко потерять вечер](#awg3-gotchas-adv). 3. Перевыпустите профили всех клиентов: `sudo bash /root/awg/manage_amneziawg.sh regen` - и импортируйте их заново на каждом устройстве. `S1`-`S4` и `H1`-`H4` обязаны совпадать, старые профили перестанут подключаться. Для одного `I1` перевыпуск не нужен: его можно поменять и в клиентском `.conf`. 4. На сервере 3.1 `H1`-`H4` не трогайте (там 1-4) и держите `S1`-`S4` не ниже 12. `HeaderProtectionKey` вручную не меняйте: новый ключ отрезает всех клиентов до перевыпуска, а штатно его даёт переустановка (`--uninstall` и новая установка). Если всё же меняете, одновременно меняйте и копию `/root/awg/server_hpk.key`, иначе `manage` откажется выпускать профили. Обычная переустановка с `--force` набор сохраняет (кроме `I1`, если установка шла с `--no-cps`: тогда `I1` снова убирается). Флаги `--preset`, `--mobile`, `--jc`, `--jmin` и `--jmax` при переустановке перегенерируют весь набор, включая `S`, `H` и `I1`, и после них нужен `regen` всех клиентов. Флаг `--i1` меняет только `I1` и закрепляет его: следующие переустановки значение сохраняют, а снимают закрепление `--no-cps` или те же `--preset`, `--mobile`, `--jc`, `--jmin` и `--jmax`. После `--i1` тоже нужен `regen`, иначе у клиентов останется прежний `I1`. Править саму библиотеку `awg_common.sh` бесполезно: установщик на шаге 5 и обновление скриптов перезаписывают её своей копией. --- ## 🔒 Настройки безопасности сервера ### Фаервол UFW * **Политики:** Deny incoming, Allow outgoing, Deny routed. * **Правила:** `limit 22/tcp` (SSH), `allow <порт_vpn>/udp`, `route allow in on awg0 out on ` (маршрутизация VPN-трафика, добавлено в v5.7.6). * **Проверка:** `sudo ufw status verbose` ### Параметры ядра (Sysctl) Файл: `/etc/sysctl.d/99-amneziawg-security.conf`. Включает: * IP forwarding * IPv6 disable (опц.) * BBR congestion control + FQ qdisc * TCP hardening (syncookies, rp_filter, RFC1337) * Отключение ICMP redirects и source routing * Адаптивные сетевые буферы (rmem/wmem по объёму RAM) * nf_conntrack_max = 65536 * kernel.sysrq = 0 ### Модуль ядра и пространства имён пользователей В модуле ядра AmneziaWG от вендора есть неисправленная ошибка: разборщик `I1`-`I5` принимает отрицательную длину в тегах ``, `` и ``, и в некоторых сочетаниях тегов это запись за границу буфера в ядре ([amneziawg-linux-kernel-module#233](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/233); на 12 октября 2026 исправления в PR #237 и #247 не приняты). Ошибка есть во всех сборках модуля, которые ставит скрипт: из PPA, из закреплённого исходника 2.0 и в готовых пакетах для ARM, собранных из него. От поколения протокола она не зависит. **Кого это касается.** Передать модулю параметры через собственный интерфейс может не только root. Команды модуля доступны любому процессу с правом `CAP_NET_ADMIN` в его собственном пространстве имён пользователей (user namespace) и в своём сетевом пространстве, а такое пространство на Debian 12 и 13 по умолчанию может создать любой пользователь (так решает патч ядра Debian, значение `kernel.unprivileged_userns_clone = 1`). Модулю не обязательно быть загруженным: установленный, он может подгрузиться сам по первому запросу, если загрузка модулей не запрещена. Мы проверили это на стенде с Ubuntu 24.04, не трогая саму ошибку: со снятым ограничением AppArmor обычный пользователь создал свой интерфейс AmneziaWG и задал ему `I1`. На Ubuntu 24.04 и новее по умолчанию действует ограничение AppArmor (`kernel.apparmor_restrict_unprivileged_userns = 1`), но это политика, а не запрет: простую попытку на нашем стенде оно отклонило, но обычного пользователя не остановило. Путь закрывает `kernel.unprivileged_userns_clone = 0`: с ним ядро отказывает непривилегированному процессу в создании пространства прямо в `unshare`/`clone`, ещё до AppArmor (так устроен патч ядра), а на стенде `unshare` с ним получил отказ. Если на сервере нет других пользователей и посторонних программ, риск мал. Он появляется, когда на машине есть чужие учётные записи или службы, через которые на неё может попасть посторонний. **Что делает скрипт.** Наши команды отрицательные длины, слишком длинные числа и сумму длин больше 65535 байт не пишут и отвергают при установке, `add`, `regen`, `modify` и `restore`. `manage check` и `manage diagnose` предупреждают, когда модуль есть в системе, а непривилегированные пространства имён пользователей разрешены без всяких ограничений, и называют команду, которая закрывает этот путь на вашей машине. При ограничении AppArmor (штатная Ubuntu) они молчат: так решено, чтобы предупреждение не стояло на каждом сервере с Ubuntu, хотя путь это ограничение не закрывает. Закрыть его и там можно той же командой, что ниже. Этот параметр скрипт сам не меняет: цена такой меры зависит от того, что ещё работает на сервере. **Как закрыть вручную.** На штатных ядрах Debian и Ubuntu (патч ядра с этим параметром есть в обоих; в Ubuntu проверено на 24.04): ```bash sudo sysctl -w kernel.unprivileged_userns_clone=0 echo 'kernel.unprivileged_userns_clone = 0' | sudo tee /etc/sysctl.d/99-userns.conf ``` Цена: перестанут работать rootless-контейнеры (Podman, Docker в режиме rootless), песочницы приложений и любые программы и службы, которые без права `CAP_SYS_ADMIN` на хосте (в том числе от root внутри обычного контейнера) сами создают такие пространства. Демон Docker в обычном режиме не затрагивается. Уже созданные пространства настройка не трогает: процесс, который успел войти в своё пространство раньше, сохраняет доступ, поэтому после записи файла надёжнее перезагрузиться. На ядрах без этого параметра (например, ядро Raspberry Pi OS или собранное вами; проверить: `sysctl kernel.unprivileged_userns_clone`) остаётся `user.max_user_namespaces`. Сначала запишите прежнее значение (`sysctl user.max_user_namespaces`), затем: ```bash sudo sysctl -w user.max_user_namespaces=0 echo 'user.max_user_namespaces = 0' | sudo tee /etc/sysctl.d/99-userns.conf ``` Эта мера дороже: user namespaces перестанут создаваться совсем, в том числе от root, и перестанут работать ещё и службы systemd с `PrivateUsers=` и Docker с `userns-remap`. Вернуть как было: `sudo rm /etc/sysctl.d/99-userns.conf`, затем, если ставили `kernel.unprivileged_userns_clone`, - `sudo sysctl -w kernel.unprivileged_userns_clone=1`, а если `user.max_user_namespaces` - `sudo sysctl -w user.max_user_namespaces=<записанное значение>`. **Если правите `I1`-`I5` руками.** Длины в ``, `` и `` - только неотрицательные целые числа, по документации вендора не больше 1000; наша проверка этот предел не навязывает, а отвергает отрицательные длины, слишком длинные числа и сумму больше 65535 байт. `manage restart`, перезапуск службы, старт при загрузке и другие пути, которые применяют уже лежащий `awg0.conf`, делают это без нашей проверки, поэтому ошибку в ручной правке они не остановят. ### Fail2Ban (Автоматическая установка) * Автоматически устанавливается и настраивается для защиты SSH. * **Настройки:** Бан через `ufw`, 5 попыток -> бан на 1 час. * **Backend:** `systemd` (journald) и на Ubuntu, и на Debian; на Debian установщик дополнительно ставит `python3-systemd`. * **Проверка:** `sudo fail2ban-client status sshd`. #### Безопасная загрузка конфигурации (v5.7.2) Начиная с v5.7.2, файл параметров `awgsetup_cfg.init` загружается через `safe_load_config()` — whitelist-парсер, который принимает только заранее определённые ключи (`AWG_*`, `OS_*`, `DISABLE_IPV6`, `ALLOWED_IPS_*`, `NO_TWEAKS` и др.). Прежний метод через `source` заменён полностью. Парсер корректно обрабатывает значения как в одинарных, так и в двойных кавычках (`'value'` или `"value"`). Это защищает от потенциальной инъекции кода: даже если файл конфигурации будет модифицирован, произвольные команды не выполнятся. ### Смена серверного ключа Понадобится, если приватный ключ сервера куда-то утёк: попал в скриншот, в сообщение на форуме или в чужие руки вместе с доступом. Отдельной команды для этого нет, но переустанавливать сервер не нужно. Сначала о том, чего бояться не стоит. **Записанный ранее трафик расшифровать не смогут** - за это отвечает forward secrecy рукопожатия, а из статического ключа сервера сессионные не выводятся. Реальный риск другой: владея ключом, можно **выдать себя за ваш сервер** перед клиентом, который ему доверяет. Поэтому смена ключа закрывает проблему не в момент замены на сервере, а тогда, когда **каждый клиент получит новый конфиг**. Ключ живёт в трёх местах, и менять надо все три сразу: | Файл | Что в нём | |---|---| | `/etc/amnezia/amneziawg/awg0.conf` | строка `PrivateKey` в секции `[Interface]` | | `/root/awg/server_private.key` | тот же приватный ключ отдельным файлом | | `/root/awg/server_public.key` | публичный ключ, из него собираются конфиги клиентов | Порядок такой: ```bash # 1. Резервная копия - на случай отката bash /root/awg/manage_amneziawg.sh backup # 2. Новая пара ключей umask 077 awg genkey > /root/awg/server_private.key awg pubkey < /root/awg/server_private.key > /root/awg/server_public.key chmod 600 /root/awg/server_private.key /root/awg/server_public.key # 3. Подставить приватный ключ в конфиг сервера. # В секции [Peer] строки PrivateKey нет, поэтому первая по файлу - нужная. # awk с -v безопасен для ключей: в base64 есть / и +, и экранировать их # не требуется, в отличие от sed. cd /etc/amnezia/amneziawg awk -v k="$(cat /root/awg/server_private.key)" \ '!d && /^[ \t]*PrivateKey[ \t]*=/ { print "PrivateKey = " k; d=1; next } { print }' \ awg0.conf > awg0.conf.new grep -q '^PrivateKey = ' awg0.conf.new && mv awg0.conf.new awg0.conf && chmod 600 awg0.conf # 4. Перезапустить сервис и перевыпустить конфиги всех клиентов systemctl restart awg-quick@awg0 bash /root/awg/manage_amneziawg.sh regen ``` `regen` перепишет конфиги всех клиентов с новым публичным ключом, заново создаст QR-коды и ссылки `vpn://`, а приватные ключи клиентов, их адреса и `AllowedIPs` оставит как были. После этого **раздайте новые конфиги заново** - до этого момента старые не работают, и именно они остаются уязвимыми. ⚠️ **Три места, где легко ошибиться:** - **Пропустить `server_private.key`.** Если поменять ключ только в `awg0.conf`, переустановка с `--force` вернёт старый: серверные ключи генерируются только при отсутствии этого файла, а конфиг собирается из него. - **Пропустить `regen`.** Файлы `.conf`, `.png`, `.vpnuri` и `.vpnuri.png` у существующих клиентов останутся со старым публичным ключом. Кто импортирует по QR или по ссылке, получит нерабочий конфиг. - **Восстановить старый бэкап позже.** Архивы в `/root/awg/backups/` содержат и `awg0.conf`, и оба файла ключей, поэтому восстановление отменит ротацию молча. Старые архивы после смены ключа лучше убрать. Откат: восстановить три файла из бэкапа, перезапустить сервис и **обязательно снова выполнить `regen`** - конфиги клиентов к этому моменту уже переписаны новым ключом. --- ## 🧹 Оптимизация сервера Скрипт установки автоматически оптимизирует сервер: **Удаляемые пакеты:** `snapd`, `modemmanager`, `networkd-dispatcher`, `unattended-upgrades`, `packagekit`, `lxd-agent-loader`, `udisks2`. Cloud-init удаляется **только** если не управляет сетевой конфигурацией. 🔴 **Снос `snapd` забирает с собой установленные снапы и их данные в `/var/snap`.** Пакет удаляется через `purge`, а следом установщик убирает каталоги `/snap`, `/var/snap` и `/var/lib/snapd`, поэтому снапы уезжают при любом раскладе. Отменить это нельзя: `rm -rf` не откатывается, и сам `snapd` вернётся через `apt install snapd`, а снапы придётся ставить заново, данные из `/var/snap` - только из бэкапа. Домашние каталоги очистка не трогает, так что данные из `~/snap` остаются на месте. Начиная с v5.27.0 установщик спрашивает согласие. На шаге 0, где задаются и остальные вопросы, он печатает пакеты, которые реально стоят в системе, отдельной строкой предупреждает про каталоги снапов и называет поимённо те снапы, которые поставили вы. Базовыми, то есть не несущими ваших данных, считаются только `snapd`, `bare` и `core*`; `lxd` в их число НЕ входит, потому что LXD из снапа держит контейнеры в `/var/snap/lxd`. Когда под удаление попадает и cloud-init, отдельной строкой говорится про `/etc/cloud` и `/var/lib/cloud`. Если терять есть что, удаление происходит **только по явному согласию**: ответом считается `y`, `yes` или `да`, всё остальное означает «сохранить». Любая неудачная проверка тоже трактуется в пользу сохранения - недоступный терминал, неопрошенный `dpkg`, нечитаемый каталог снапов. Ответ записывается в `awgsetup_cfg.init`, чтобы повторный или возобновлённый запуск не спрашивал заново и не считал молчание согласием: очистка выполняется только при явно записанном согласии. Способов отказаться два, и они не равнозначны: | Флаг | Что пропускает | Когда нужен | |---|---|---| | `--keep-packages` | только очистку системы | оставить фаервол, Fail2Ban и оптимизацию, но не трогать пакеты | | `--no-tweaks` | очистку, оптимизацию, sysctl-hardening, UFW и Fail2Ban | сервер уже настроен своими средствами | С `--yes` вопрос не задаётся и поведение остаётся прежним, то есть пакеты удаляются: список при этом всё равно печатается в журнал. Для неинтерактивной установки, где пакеты нужно сохранить, добавьте `--keep-packages`. **Hardware-aware настройки:** * **Swap:** 1 ГБ при RAM ≤ 2 ГБ, 512 МБ при RAM > 2 ГБ. `vm.swappiness = 10`. * **Сетевые буферы:** Автоматическая настройка `rmem_max`/`wmem_max` в зависимости от объёма RAM. --- ## 📋 Примеры конфигурации Новая установка получает профиль 3.1, поэтому его примеры идут первыми; примеры профиля 2.0 - ниже. Ключи и адреса замаскированы, значения параметров взяты для примера.
awgsetup_cfg.init, профиль 3.1 (параметры установки, сокращено) ```bash # Конфигурация установки AmneziaWG (Авто-генерация) export AWG_PORT=39743 export AWG_TUNNEL_SUBNET='10.9.9.1/24' export DISABLE_IPV6=1 export ALLOWED_IPS_MODE=1 export ALLOWED_IPS='0.0.0.0/0' export AWG_ENDPOINT='' export AWG_MTU=1280 export AWG_Jc=5 export AWG_Jmin=61 export AWG_Jmax=190 export AWG_S1=88 export AWG_S2=47 export AWG_S3=29 export AWG_S4=17 export AWG_H1='1' export AWG_H2='2' export AWG_H3='3' export AWG_H4='4' export AWG_I1='' export AWG_PRESET='default' export AWG_PROTOCOL_SOURCE='default' export AWG_PROTOCOL_FALLBACK='' export AWG_CPA='32-128' export AWG_PROTOCOL='3.1' ``` Здесь показаны строки, которые относятся к сети и протоколу; настоящий файл длиннее (ОС, изоляция клиентов, имя сервера, флаги установки). `HeaderProtectionKey` в init нет: он лежит в `awg0.conf` и в `/root/awg/server_hpk.key`.
awg0.conf, профиль 3.1 (серверный конфиг) ```ini [Interface] PrivateKey = [SERVER_PRIVATE_KEY] Address = 10.9.9.1/24 MTU = 1280 ListenPort = 39743 PostUp = iptables -I FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE Jc = 5 Jmin = 61 Jmax = 190 S1 = 88 S2 = 47 S3 = 29 S4 = 17 H1 = 1 H2 = 2 H3 = 3 H4 = 4 I1 = HeaderProtectionKey = [HEADER_PROTECTION_KEY] ContentPaddingAddition = 32-128 [Peer] #_Name = my_phone PublicKey = [CLIENT_PUBLIC_KEY] AllowedIPs = 10.9.9.2/32 ``` Строки `PostUp` и `PostDown` сокращены: в настоящем конфиге там ещё правила MSS-clamp и изоляции клиентов.
client.conf, профиль 3.1 (клиентский конфиг) ```ini [Interface] PrivateKey = [CLIENT_PRIVATE_KEY] Address = 10.9.9.2/32 DNS = 1.1.1.1, 1.0.0.1 MTU = 1280 Jc = 5 Jmin = 61 Jmax = 190 S1 = 88 S2 = 47 S3 = 29 S4 = 17 H1 = 1 H2 = 2 H3 = 3 H4 = 4 I1 = HeaderProtectionKey = [HEADER_PROTECTION_KEY] ContentPaddingAddition = 32-128 [Peer] PublicKey = [SERVER_PUBLIC_KEY] Endpoint = 203.0.113.1:39743 AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 33 ``` `HeaderProtectionKey` у клиента тот же, что на сервере: это один ключ на установку.
awgsetup_cfg.init, профиль 2.0 (параметры установки) ```bash # Конфигурация установки AmneziaWG (Авто-генерация) export AWG_PORT=39743 export AWG_TUNNEL_SUBNET='10.9.9.1/24' export DISABLE_IPV6=1 export ALLOWED_IPS_MODE=1 export ALLOWED_IPS='0.0.0.0/0' export AWG_ENDPOINT='' export AWG_Jc=6 export AWG_Jmin=55 export AWG_Jmax=205 export AWG_S1=72 export AWG_S2=56 export AWG_S3=32 export AWG_S4=16 export AWG_H1='234567-345678' export AWG_H2='3456789-4567890' export AWG_H3='56789012-67890123' export AWG_H4='456789012-567890123' export AWG_I1='' export AWG_PRESET='default' export AWG_PROTOCOL='2.0' ```
awg0.conf, профиль 2.0 (серверный конфиг, ключи замаскированы) ```ini [Interface] PrivateKey = [SERVER_PRIVATE_KEY] Address = 10.9.9.1/24 MTU = 1280 ListenPort = 39743 PostUp = iptables -I FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE Jc = 6 Jmin = 55 Jmax = 205 S1 = 72 S2 = 56 S3 = 32 S4 = 16 H1 = 234567-345678 H2 = 3456789-4567890 H3 = 56789012-67890123 H4 = 456789012-567890123 I1 = [Peer] #_Name = my_phone PublicKey = [CLIENT_PUBLIC_KEY] AllowedIPs = 10.9.9.2/32 ``` Строки `PostUp` и `PostDown` здесь сокращены: в настоящем конфиге там ещё правила MSS-clamp и изоляции клиентов.
Минимальный awg0.conf для AWG 2.0 (если настраивается вручную) Если разворачиваете сервер не моим инсталлятором (например, `amneziawg-go` в LXC), минимальный валидный `awg0.conf` для AWG 2.0 выглядит так — все 11 обфускационных параметров обязательны, `manage_amneziawg.sh add/regen` упадёт с ошибкой если хотя бы один отсутствует: ```ini [Interface] PrivateKey = [SERVER_PRIVATE_KEY] Address = 10.9.9.1/24 ListenPort = 51820 Jc = 4 Jmin = 40 Jmax = 90 S1 = 50 S2 = 40 S3 = 12 S4 = 8 H1 = 1234567 H2 = 2345678 H3 = 3456789 H4 = 4567890 ``` Нюансы для ручной установки: - **S3/S4** - параметры AWG 2.0, добавлены в протокол позже S1/S2. В конфигах от предыдущих версий (AWG 1.x) их может не быть - надо дописать руками, значения: `S3` в диапазоне 0-64, `S4` в диапазоне 0-32, главное что вообще есть. - **H1–H4** могут быть single-value (`H1 = 1234567`) или range (`H1 = 100000-200000`), диапазоны не должны пересекаться. Безопасный верхний предел — 2147483647 (`INT32_MAX`), иначе `amneziawg-windows-client` может подсвечивать значения как invalid. - **I1-I5** (CPS / special-junk пакеты) опциональны. Без `I1` (если `I2`-`I5` тоже не заданы) маскирующие пакеты не отправляются, остальная обфускация (`Jc`, `S`, `H`) работает как обычно; чтобы он был, добавьте `I1 = ` (random 128 байт) или `I1 = ` (binary). ⚠️ Пример `` показывает ФОРМАТ, а не рекомендуемое значение: по замеру сентября 2026 пакет из случайных байт на части мобильных сетей режется, и рукопожатие не собирается. Если туннель не поднимается на сотовой сети, см. [рукопожатие не собирается на мобильном интернете](#no-hs-mobile-adv). С версии 5.18.0 в клиентские конфиги переносятся все пять (`I1`-`I5`), а не только `I1`: пропишите `I2`-`I5` в секции `[Interface]` файла `awg0.conf`, перезапустите сервис (`sudo systemctl restart awg-quick@awg0`) и раздайте клиентам через `sudo bash /root/awg/manage_amneziawg.sh regen <имя>` - значения разойдутся в `.conf`, QR и `vpn://`. Готовые наборы берут, например, из списка VoidWaifu; переносимые форматы тегов: ``, ``, ``, ``, `` (тег `` есть только в модуле ядра, на amneziawg-go конфиг с ним не поднимется). Совпадать с сервером эти значения не обязаны: их шлёт только инициатор рукопожатия, а приёмник отбрасывает. Регистр важен - только верхний. Незаданные `I2`-`I5` просто не выводятся. - **MTU**, **PostUp/PostDown** — опциональны, зависят от сетапа (см. `amneziawg-go` секцию про iptables MASQUERADE в LXC). После создания такого `awg0.conf` для `manage_amneziawg.sh` нужен ещё минимальный `/root/awg/awgsetup_cfg.init` с `AWG_PORT`, `AWG_TUNNEL_SUBNET`, `AWG_ENDPOINT`. Файл `/root/awg/server_public.key` при отсутствии `manage` вычислит сам из `PrivateKey` в `awg0.conf`. **Профиль 3.1 вручную** требует больше: в `awg0.conf` строки `HeaderProtectionKey = <ключ из awg genkey>` и `ContentPaddingAddition = 32-128`, `S1`-`S4` не меньше 12, в init - `export AWG_PROTOCOL='3.1'` и `export AWG_CPA='32-128'`, а копия ключа - одной строкой в `/root/awg/server_hpk.key` (права 600). Без маркера `AWG_PROTOCOL='3.1'` сервер читается как 2.0, и `manage` откажется выпускать профили, увидев ключ в конфиге; если ключ в конфиге и в файле разойдутся, он тоже откажет.
client.conf, профиль 2.0 (клиентский конфиг, ключи замаскированы) ```ini [Interface] PrivateKey = [CLIENT_PRIVATE_KEY] Address = 10.9.9.2/32 DNS = 1.1.1.1, 1.0.0.1 MTU = 1280 Jc = 6 Jmin = 55 Jmax = 205 S1 = 72 S2 = 56 S3 = 32 S4 = 16 H1 = 234567-345678 H2 = 3456789-4567890 H3 = 56789012-67890123 H4 = 456789012-567890123 I1 = [Peer] PublicKey = [SERVER_PUBLIC_KEY] Endpoint = 203.0.113.1:39743 AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 33 ```
--- ## 🖥️ CLI Параметры запуска скриптов ### install_amneziawg.sh ``` Опции: -h, --help Показать справку --uninstall Удалить AmneziaWG --diagnostic Создать диагностический отчет --repair-module Починить модуль ядра на уже установленном сервере (ядро 7.0.0-38 и новее, недонастроенные пакеты после apt); сочетается только с --verbose и --no-color -v, --verbose Расширенный вывод (включая DEBUG) --no-color Отключить цветной вывод --port=НОМЕР Установить UDP порт (1-65535; на мобильных сетях с DPI часто выручает 443/udp) --ssh-port=ПОРТ SSH-порт для правила UFW (автодетект; список через запятую) --subnet=ПОДСЕТЬ Подсеть туннеля, CIDR /16-/30 (напр. 10.9.0.0/16) --allow-ipv6 Оставить IPv6 включенным --disallow-ipv6 Принудительно отключить IPv6 --allow-ipv6-tunnel Включить dual-stack IPv6 внутри туннеля (ULA, opt-in) --route-all Режим: Весь трафик (0.0.0.0/0) (умолч.) --route-amnezia Режим: Список Amnezia+DNS (частные сети мимо туннеля) --client-ipv6-direct С --route-amnezia: IPv6 устройств напрямую, мимо VPN --route-custom=СЕТИ Режим: Только указанные сети --isolation=on|off Изоляция клиентов друг от друга (умолч. on) --endpoint=АДРЕС Внешний endpoint сервера: FQDN, IPv4 или [IPv6] (для NAT) --server-name=ИМЯ Имя сервера в приложении Amnezia при импорте vpn:// (умолч. 'AWG Server') --mobile Мобильный сетап одним флагом: preset mobile + порт 443/udp (явный --port выигрывает) --protocol=2.0|3.1 Поколение протокола для новой установки или для начатой, но не дошедшей до шага 6 (по умолчанию 3.1). Без флага на машине, где установщик 3.1 не ставит (ядро старее 6.7, архитектура не x86_64, включая ARM, модуль ядра второй линии или непройденная проверка модуля), ставится 2.0 с объяснением; если модуль не примет и набор 2.0, установка останавливается. Если инструменты awg старее модуля третьей линии, установка останавливается и просит их обновить. --protocol=2.0 нужен, если клиенты - роутеры на стоковой прошивке, Hiddify или необновлённые приложения. Явный --protocol=3.1 на неподходящей машине прерывает установку и называет причину. На уже настроенном сервере флаг с ДРУГИМ поколением прерывает установку: поколение работающей установки меняется только переустановкой с перевыпуском всех клиентских профилей. Принимается и форма с пробелом: --protocol 2.0 --preset=ТИП Набор параметров обфускации: default, mobile mobile: Jc=3, узкий Jmax — для мобильных операторов (Tele2, Yota, Мегафон) --jc=N Задать Jc вручную (0-122, поверх preset; 0 выключает junk-пакеты) --jmin=N Задать Jmin вручную (0-1280, поверх preset) --jmax=N Задать Jmax вручную (0-1280, поверх preset, ≥ Jmin) --no-cps Отключить CPS (параметр I1) - для десктопных клиентов, которые его не поддерживают (например, macOS) --i1='' Задать I1 своим значением: теги , , , , (N от 1 до 1000, весь пакет не больше 1024 байт). Значение закрепляется, переустановка его сохраняет; снимают --no-cps, --preset, --mobile, --jc, --jmin и --jmax --no-prebuilt На ARM не ставить готовый пакет модуля из релиза arm-packages, а собрать модуль через DKMS -y, --yes Неинтерактивный режим (все подтверждения auto-yes) -f, --force Переустановка поверх работающего AWG (ENV: AWG_FORCE_REINSTALL=1) --no-tweaks Пропустить очистку системы, оптимизацию и hardening (UFW, Fail2Ban); минимальный forwarding-sysctl применяется всегда --keep-packages Не удалять системные пакеты (snapd и др.), но оставить фаервол, Fail2Ban и оптимизацию. Снос snapd уносит установленные снапы и их данные в /var/snap ``` ### manage_amneziawg.sh ``` Опции: -h, --help Показать справку -v, --verbose Расширенный вывод (для list) --no-color Отключить цветной вывод --conf-dir=ПУТЬ Указать директорию AWG (умолч: /root/awg) --server-conf=ПУТЬ Указать файл конфига сервера --json Машиночитаемый JSON-вывод (v5.21.0: большинство команд, см. раздел «JSON-интерфейс») --expires=ВРЕМЯ Срок действия при add (1h, 12h, 1d, 7d, 30d, 4w) --apply-mode=РЕЖИМ syncconf (умолч.) или restart (обход kernel panic) --psk (только для add) сгенерировать PresharedKey для клиента (v5.11.1+) --allowed-ips=СПИСОК (только для add) индивидуальные AllowedIPs клиента - CIDR через запятую; без флага - глобальный режим маршрутизации сервера --yes Не спрашивать подтверждение (ENV: AWG_YES=1) --carrier=NAME (только для diagnose) сравнить параметры с профилем оператора --reset-routes (только для regen) сбросить AllowedIPs клиентов на глобальный режим маршрутизации ``` > **`--psk`** - опциональный дополнительный слой поверх обфускации AmneziaWG. Генерирует 32-байт симметричный ключ через `awg genpsk`, пишет его в серверный `[Peer]` и в клиентский `[Peer]` (`PresharedKey = ...`). Совместим с любым WireGuard/AmneziaWG клиентом. В batch-режиме `add c1 c2 c3 --psk` каждому клиенту выдаётся свой PSK. Без флага клиенты создаются без `PresharedKey` (по умолчанию - обфускации AmneziaWG достаточно для большинства сценариев). Флаг влияет только на новых клиентов, создаваемых этим вызовом `add` - существующие клиенты без PSK остаются без изменений и продолжают подключаться как раньше. > **`--allowed-ips=СПИСОК`** - индивидуальные маршруты клиента сразу при создании, без последующего `modify` (Issue #253). Список CIDR IPv4/IPv6 через запятую: `add phone --allowed-ips="10.0.0.0/8, 192.168.0.0/16"`. Валидируется и нормализуется до создания первого клиента (невалидное или пустое значение рушит команду, ничего не создав), применяется ко всем именам batch-а - как `--expires`. Значение проходит те же правила, что и глобальный режим: полный туннель IPv4 получает рядом IPv6-маршрут (iOS-правило): `::/0` при `0.0.0.0/0`, `2000::/3` со служебным адресом у списка, а на dual-stack `::/0` при нативном IPv6 сервера и туннельную ULA без него; раздельный список `::/0` не получает никогда, а список с явными IPv6-токенами (например `0.0.0.0/0, ::/0`) записывается как есть - и если полный туннель расписан по IPv6 без `::/0`, `add` предупреждает об этом сразу, как это делает `regen`. Без флага - глобальный режим маршрутизации сервера, как раньше. Существующим клиентам маршруты по-прежнему меняет `modify`, а `regen` сохраняет такие индивидуальные списки. > > **Список замещает глобальный целиком.** В том числе подсеть туннеля, которую установщик дописывает в `AllowedIPs` при `--isolation=off`: клиент, созданный с `--allowed-ips="10.0.0.0/8"`, остальных пиров не увидит. Нужна видимость устройств внутри VPN - добавьте подсеть туннеля (по умолчанию `10.9.9.0/24`) в список вручную. **Переменные среды:** | Переменная | Описание | |------------|----------| | `AWG_SKIP_APPLY=1` | Пропустить apply_config. Для автоматизации: накопить N операций, применить одной командой | | `AWG_APPLY_MODE=restart` | Полный перезапуск вместо syncconf (можно сохранить в `awgsetup_cfg.init`) | | `AWG_YES=1` | Не спрашивать подтверждение (эквивалент флага `--yes`) | | `AWG_STRICT_CONFIRM=1` | Неинтерактивный запуск деструктивной команды без `--yes`/`AWG_YES=1` отказывает (rc 1) вместо тихого согласия. Для cron/CI/ботов (v5.21.0) | --- ## 🧑‍💻 Полный список команд управления Используйте `sudo bash /root/awg/manage_amneziawg.sh <команда>`: > **Как `manage` находит клиентов в серверном конфиге.** Каждый `[Peer]`, созданный моим инсталлятором/`manage add`, содержит комментарий-маркер `#_Name = <имя>` на первой строке блока. Именно по нему `list`, `remove`, `regen`, `modify` находят нужного клиента. Если вы переносите `awg0.conf` со старого сервера или добавляете peer руками — дописывайте `#_Name = <имя>` после `[Peer]`, иначе `manage` не увидит такого клиента. Пример: блок `[Peer]` в серверном конфиге выше (см. [Примеры конфигурации](#config-examples-adv)). * **`add <имя> [имя2 ...] [--expires=ВРЕМЯ] [--psk] [--allowed-ips=СПИСОК]`:** Добавить одного или нескольких клиентов. При batch-создании `awg syncconf` вызывается один раз для всех. С `--expires` - срок действия применяется ко всем. С `--psk` - для каждого генерируется отдельный PresharedKey (v5.11.1+). С `--allowed-ips` - каждый получает индивидуальные маршруты вместо глобального режима (Issue #253). * **`remove <имя> [имя2 ...]`:** Удалить одного или нескольких клиентов. При batch-удалении apply_config вызывается один раз. * **`list [-v] [--json]`:** Список клиентов (с деталями при `-v`; `--json` - машиночитаемый формат, включает поля `client_ipv6` и `expires_at`). * **`regen [имя ...] [--reset-routes]`:** Перегенерировать файлы `.conf`/`.png` для указанных клиентов или всех сразу. По умолчанию сохраняет индивидуальные `AllowedIPs`/`DNS`/`PersistentKeepalive` клиента (заданные через `modify`). С `--reset-routes` - сбрасывает `AllowedIPs` на текущий глобальный режим маршрутизации из `awgsetup_cfg.init`; используйте после смены режима переустановкой (`--force --route-all` / `--route-amnezia` / `--route-custom=`), чтобы новый режим дошёл до существующих клиентов (Issue #170). * **`modify <имя> <пар> <зн>`:** Изменить параметр клиента в `.conf` файле. Допустимые параметры: DNS, Endpoint, AllowedIPs, PersistentKeepalive. После изменения QR-код и vpn:// URI автоматически перегенерируются; прежние копии удаляются до правки, так что файл, который собрать не удалось, отсутствует, а не остаётся старым. * **`backup`:** Создать резервную копию (конфиги + ключи + данные истечения клиентов + cron). * **`restore [файл]`:** Восстановить из резервной копии (включая данные истечения и cron-задачу). * **`check` / `status`:** Проверить состояние сервера (сервис, порт, модуль, поколение протокола установки 3.1 или 2.0 и параметры обфускации). * **`show`:** Выполнить `awg show`. * **`restart`:** Перезапустить сервис AmneziaWG. * **`diagnose [--carrier=NAME]`:** Self-troubleshooting: проверка модуля ядра, sysctl, UFW; с `--carrier=ИМЯ` - сравнение AWG-параметров с профилем мобильного оператора. Имена: `beeline_msk`, `yota_msk`, `tele2_msk`, `tele2_krasnoyarsk`, `tattelecom`, `megafon_regions`, `tmobile_us` (последнее имя историческое: это российский Т-Мобайл, Москва и область). * **`repair-module`** (псевдоним `repair`): Восстановить/пересобрать модуль ядра amneziawg (DKMS) после обновления ядра сервера; про ядра 7.0.0-38 и новее - в разделе [Известные ограничения](#kernel-70-backport-adv). * **`help`:** Показать справку. * **`stats [--json]`:** Статистика трафика по клиентам. С `--json` — машиночитаемый формат для интеграции. ### Примеры использования ```bash # Изменить DNS клиента sudo bash /root/awg/manage_amneziawg.sh modify my_phone DNS "8.8.8.8,1.0.0.1" # Изменить PersistentKeepalive sudo bash /root/awg/manage_amneziawg.sh modify my_phone PersistentKeepalive 25 # Изменить AllowedIPs (split-tunneling) sudo bash /root/awg/manage_amneziawg.sh modify my_phone AllowedIPs "192.168.1.0/24,10.0.0.0/8" # Перегенерировать конфиг одного клиента sudo bash /root/awg/manage_amneziawg.sh regen my_phone # Создать бэкап sudo bash /root/awg/manage_amneziawg.sh backup # Восстановить из последнего бэкапа (интерактивный выбор) sudo bash /root/awg/manage_amneziawg.sh restore ``` --- ## 🤖 JSON-интерфейс для автоматизации (--json) С v5.21.0 флаг `--json` поддерживают не только `list`/`stats`, но и команды управления: `add`, `remove`, `regen`, `modify`, `backup`, `restore`, `check` (алиас `status`), `restart`, `repair-module` (алиас `repair`). Правила контракта: - **stdout = ровно один JSON-документ** одной строкой, при любом исходе, включая ошибки. Человеческие сообщения уходят в stderr. Читайте stdout целиком - потокового вывода нет, но у batch-команд `results[]` растёт линейно с числом имён. - **Exit-код - источник истины.** Поле `ok` дублирует его для ботов, читающих только stdout: `ok=false` при любом провале, в том числе частичном (`add a b`, где `b` уже существует). - **Совместимость аддитивная:** новые поля могут добавляться; существующие не переименовываются и не меняют тип. Наборы `status`-значений могут расширяться - неизвестное значение трактуйте как ошибку соответствующей записи. `list`/`stats` заморожены как есть в части ФОРМЫ ответа - это голые массивы без конверта; на набор полей заморозка не распространяется, он растёт по правилу выше. - **Поле `error` - человекочитаемый текст** (может быть локализован), не парсите его; машинные решения принимайте по `ok`, `rc` и `status`. - **Алиасы канонизируются:** в ответе всегда `"command":"check"` и `"command":"repair-module"`, как бы вы ни набрали команду. - `--json` **не подразумевает** `--yes`: деструктивные команды по-прежнему требуют подтверждения. - `help`, `show`, `diagnose` флаг не поддерживают - их вывод остаётся человеческим. Форма успеха (пример `add`): ```json {"command":"add","ok":true,"added":1,"failed":0,"applied":true,"results":[{"name":"phone","status":"created","conf":"/root/awg/phone.conf","qr":"/root/awg/phone.png","vpnuri":"/root/awg/phone.vpnuri","expires_at":null,"allowed_ips":"1.0.0.0/8, 2.0.0.0/7, 4.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4, 8.8.8.8/32, 1.1.1.1/32, 2000::/3"}]} ``` Форма любого аварийного выхода (die, неверная опция, отказ подтверждения, сигнал): ```json {"command":"remove","ok":false,"error":"confirmation denied","rc":1} ``` Статусы записей `results[]`: `add` - `created|exists|invalid_name|error`; `remove` - `removed|not_found|invalid_name|error`; `regen` - `regenerated|not_found|invalid_name|error`. Замечания по полям: - `applied` - применён ли конфиг к live-интерфейсу. У `regen` и `modify` поля нет: они не меняют серверное состояние (ключи и IP переиспользуются). При `AWG_SKIP_APPLY=1` всегда `false`. - `qr`/`vpnuri` - путь, если файл существовал на момент ответа. У `add` и `regen` QR и URI генерируются вне конфиг-блокировки: при параллельной операции файл может исчезнуть, гарантий свежести нет. У `modify` прежние копии удаляются до правки, а перевыпуск идёт под той же блокировкой: файл, который собрать не удалось, отсутствует, и поле равно `null`. Если параллельно с тем же клиентом ничего не делали, путь ведёт на копию из нового `.conf`. - `results[].allowed_ips` (у `add`, записи со статусом `created`) - применённые маршруты клиента, прочитанные из только что созданного `.conf`. Может отличаться от аргумента `--allowed-ips`: полный туннель IPv4 дополняется IPv6-маршрутом (`::/0`, `2000::/3` или туннельной ULA, iOS-правило). `null` означает, что прочитать значение не удалось - причина идёт в журнал ошибкой, как у `qr`/`vpnuri`. Внешнему потребителю (боту) поле снимает проверочный вызов после создания (Issue #253). - `restore` возвращает конверт и на провале (с полями `error` и `rolled_back` - боту важно знать, был ли откат). При `rolled_back: true` рядом стоит `rollback_complete`: `false` значит, что часть файлов откат вернуть не смог, причины и путь к снимку в stderr. `restored.clients` - число `[Peer]`-блоков в восстановленном серверном конфиге, не файлов в рабочей папке. - `repair-module.rc` - код внутренней проверки модуля (0 - модуль и сервис OK, 1 - модуль не поднялся, 2 - модуль OK, сервис нет), не exit-код процесса. - `check.module.loaded=false` сам по себе не ошибка: на userspace-инсталляциях (amneziawg-go, LXC) модуля нет и не будет. - `check.protocol` - поколение протокола установки строкой (`"2.0"` или `"3.1"`), прочитанное из маркера `AWG_PROTOCOL` в `awgsetup_cfg.init`, а не из версии модуля: модуль третьей линии штатно работает с конфигурацией второй. Установка без маркера - это `"2.0"`. `check.protocol_error` в норме `null`; значение `"unreadable"` означает, что маркер испорчен (недопустимое значение, пустое поле, две строки маркера, файл не читается): тогда `protocol` равен `null`, `ok=false` и код возврата 1. Оба поля присутствуют в каждом ответе самой проверки. Если файла `awgsetup_cfg.init` нет или это не обычный файл, `check` завершается раньше проверки общим конвертом ошибки (`command`, `ok`, `error`, `rc`), и этих полей в нём нет. - `list.expires_at` - unix-время числом у клиента со сроком либо `null` у бессрочного; каноническая десятичная запись не длиннее 15 знаков. `list.expires_at_error` - в норме `null`, значение `"unreadable"` означает, что метка срока на сервере есть, а значения из неё получить не удалось (пустой файл, повреждённое содержимое, каталог на месте файла, отказ чтения). Оба поля присутствуют в каждой записи всегда; подробности - в разделе [Временные клиенты](#expires-adv). - `check.port.number` - всегда целое, и `0` читайте как «порт не определён». Настройка отсутствует или пуста - это предупреждение, `ok` не меняется. Любое непустое значение, которое не является портом 1-65535, считается повреждённым конфигом: `ok=false` и код возврата 1. Значение нормализуется, поэтому `0080` в конфиге даст `80` в ответе, а пробелы по краям игнорируются. Судить о живом порте по одному этому полю нельзя - смотрите вместе с `port.listening`. ### Строгое подтверждение для пайплайнов (AWG_STRICT_CONFIRM) По умолчанию неинтерактивный запуск (cron, CI, бот) деструктивной команды молча продолжается, как будто вы ответили «да» - это историческое поведение, и оно сохранено. `AWG_STRICT_CONFIRM=1` включает строгий режим: без явного `--yes` (или `AWG_YES=1`) команда откажется с rc 1, а с `--json` вернёт `{"ok":false,"error":"AWG_STRICT_CONFIRM=1: non-interactive run requires --yes","rc":1}`. ```bash # Рецепт для ботов: строгий режим + явное согласие AWG_STRICT_CONFIRM=1 bash manage_amneziawg.sh remove phone --json --yes ``` Действует на один запуск, в конфиг не сохраняется. Активирует строго значение `1`. --- ## 🛠️ Технические детали ### Архитектура скриптов | Файл | Назначение | |------|-----------| | `install_amneziawg.sh` | Установщик: state machine из 8 шагов с поддержкой resume | | `manage_amneziawg.sh` | Управление: add/remove/list/regen/stats/backup/restore | | `awg_common.sh` | Общая библиотека: ключи, конфиги, QR, peer management | | `install_amneziawg_en.sh` | Установщик (English версия) | | `manage_amneziawg_en.sh` | Управление (English версия) | | `awg_common_en.sh` | Общая библиотека (English версия) | `awg_common.sh` подключается через `source` из обоих скриптов. Установщик скачивает его на шаге 5. ```mermaid graph TD A[install_amneziawg.sh] -->|"source (шаг 6)"| C[awg_common.sh] B[manage_amneziawg.sh] -->|"source"| C A -->|"wget (шаг 5)"| B A -->|"wget (шаг 5)"| C subgraph "State Machine (install)" S0[Шаг 0: Init + выбор поколения] --> S1[Шаг 1: Update] S1 -->|reboot| S2[Шаг 2: DKMS] S2 -->|reboot| S3[Шаг 3: Module + проба 3.1] S3 --> S4[Шаг 4: UFW] S4 --> S5[Шаг 5: Scripts] S5 --> S6[Шаг 6: Configs] S6 --> S7[Шаг 7: Service] S7 --> S99[Шаг 99: Done] end subgraph "Команды (manage)" M1[add / remove] M2[list / show / check] M3[modify / regen] M4[backup / restore] M5[restart] M6[stats / stats --json] end ``` ### DKMS Пересборка модуля ядра `amneziawg` при обновлении ядра. Проверка: `dkms status`. ### Генерация ключей и конфигов **Полностью нативная** генерация: * **Ключи:** `awg genkey` + `awg pubkey` (стандартные утилиты AmneziaWG). * **Конфиги:** Bash-шаблоны с параметрами обфускации; в профиль 3.1 дописываются `HeaderProtectionKey` и `ContentPaddingAddition`. * **QR-коды:** `qrencode -t png`. * **Python/awgcfg.py:** Убраны полностью. Workaround для бага удаления конфига больше не нужен. Ключи клиентов хранятся в `/root/awg/keys/` (права 600). Серверные ключи — в `/root/awg/server_private.key` и `server_public.key`. #### Привязка URL к версии (v5.7.2) Инсталлятор скачивает `awg_common.sh` и `manage_amneziawg.sh` с URL, привязанных к конкретному тегу версии: ``` https://raw.githubusercontent.com/bivlked/amneziawg-installer/v6.1.1/awg_common.sh ``` Это даёт **supply chain pinning**: скачиваемые скрипты соответствуют версии инсталлятора, даже если `main` уже обновлён. Для разработки можно переопределить ветку: ```bash sudo AWG_BRANCH=my-feature-branch bash ./install_amneziawg.sh ``` Переменную ставьте после `sudo`, иначе sudo сбросит окружение. С веткой, отличной от тега версии, проверка SHA256 скачанных скриптов пропускается (в журнале будет предупреждение), так что это режим только для разработки. --- ## 🔄 Как обновить скрипты Для обновления скриптов управления и общей библиотеки **без переустановки сервера** скачайте их во временную папку, проверьте подпись и только потом замените (нужен `minisign`: `sudo apt install minisign`): ```bash cd "$(mktemp -d)" KEY=RWQXfpABHIpZPttqrwYrQNHRTk/iLIz4cVh9KkRwAElHP+CoW/NPEysN M=manage_amneziawg.sh C=awg_common.sh # английская версия: M=manage_amneziawg_en.sh C=awg_common_en.sh ok=1 tag= for f in "$M" "$C"; do wget -q -O "$f" "https://github.com/bivlked/amneziawg-installer/releases/latest/download/$f" \ && wget -q -O "$f.minisig" "https://github.com/bivlked/amneziawg-installer/releases/latest/download/$f.minisig" \ && out=$(minisign -V -P "$KEY" -m "$f" -x "$f.minisig") \ && t=$(printf '%s\n' "$out" | sed -n "s/^Trusted comment: amneziawg-installer \(v[0-9.]*\) $f\$/\1/p") \ && [ -n "$t" ] && [ "${tag:-$t}" = "$t" ] || { echo "НЕ ПРОВЕРЕН: $f"; ok=0; break; } tag=$t done [ "$ok" = 1 ] && { old=$(sudo sed -n 's/^SCRIPT_VERSION="\(.*\)"/v\1/p' /root/awg/manage_amneziawg.sh) && [ -n "$old" ] \ || { echo "НЕ ПРОВЕРЕН: не удалось прочитать установленную версию из /root/awg/manage_amneziawg.sh"; ok=0; }; } [ "$ok" = 1 ] && [ "$(printf '%s\n' "$old" "$tag" | sort -V | tail -1)" != "$tag" ] \ && { echo "НЕ ПРОВЕРЕН: релиз $tag старше установленного $old"; ok=0; } [ "$ok" = 1 ] && { sudo install -m 700 "$M" /root/awg/manage_amneziawg.sh \ && sudo install -m 700 "$C" /root/awg/awg_common.sh && echo "Установлен проверенный релиз $tag" || echo "НЕ УСТАНОВЛЕН до конца: запустите блок ещё раз"; } ``` Если скрипт напечатал «НЕ ПРОВЕРЕН», рабочие файлы не тронуты; «НЕ УСТАНОВЛЕН до конца» значит, что заменены не оба файла, и блок нужно запустить ещё раз. Если установленный `manage` старше v5.7.0, строки версии в нём нет и блок откажет: такой сервер обновляйте новым установщиком с `--force`. Блок принимает только пару файлов из одного релиза и не старше уже установленного, поэтому подменённая ссылка на последний релиз не откатит скрипты на старые подписанные версии. Номер проверенного релиза он печатает: сверьте его со [страницей релизов](https://github.com/bivlked/amneziawg-installer/releases). Прямой `wget -O` поверх рабочего файла при сбое скачивания оставил бы пустой файл. Как устроена подпись: [Проверка подписи](README.md#proverka-podpisi). > **Примечание:** Переустановка скрипта `install_amneziawg.sh` **не требуется** для обновления управления. Сменить поколение протокола (3.1 или 2.0) обновлением скриптов или `--force` нельзя: только `--uninstall`, новая установка и новые профили для всех клиентов, см. [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv). --- ## ❓ FAQ (Дополнительные вопросы)
В: Почему мой конфиг подсвечен жёлтым в приложении Amnezia? О: Жёлтая метка означает поколение профиля, а не ошибку: так приложение Amnezia помечает конфигурации второй линии AmneziaWG. Сама по себе метка не говорит, что с соединением что-то не так, и переделывать из-за неё ничего не нужно. С версии 6.0.0 новая установка по умолчанию получает профиль 3.1. Профиль 2.0 - на серверах, поставленных раньше, поставленных с --protocol=2.0 или там, где установщик выбрал 2.0 сам (штатный Debian 12 с ядром 6.1, ARM), - метку получает ожидаемо. Чтобы убрать её, нужен сервер 3.1, то есть переустановка с перевыпуском всех профилей, и все ваши клиенты должны понимать 3.1.
В: Как получить на Android клиент, понимающий третью линию? О: Обновите приложение: лёгкий AmneziaWG в Google Play понимает третью линию с версии 3.1.4 (21 сентября 2026), APK со страницы релизов проекта - с v3.1.20260814, флагманское Amnezia VPN - с 5.0.1.5, WG Tunnel - с 5.6.0. Полная таблица - в разделе Какое поколение AmneziaWG понимает клиент.
В: Мой роутер умеет AmneziaWG третьей линии? О: В стабильных штатных прошивках третьей линии на 15 октября 2026 нет: у Keenetic она появилась в KeeneticOS 5.2 Alpha 11 (канал разработки), у GL.iNet штатно только вторая линия (с прошивки 4.9), а в официальных пакетах OpenWrt AmneziaWG нет вовсе. Поэтому для роутера, чья прошивка умеет только вторую линию (например, стабильный KeeneticOS 5.1), ставьте сервер с --protocol=2.0: профиль второй линии для него рабочий путь, а не временный компромисс. Третью линию на роутерах дают сторонние проекты: AWG Manager для Keenetic (v2.19.16 от 14 октября 2026; на KeeneticOS 5.2 Alpha 11 и новее штатным модулем, на других прошивках своим модулем ядра или встроенным sing-box), awg-openwrt для OpenWrt (третью линию дают только пакеты для OpenWrt 25.12.5 и 24.10.8, заменённые 22 сентября 2026 под прежними тегами; скачанные раньше и пакеты для более старых OpenWrt её не дают), для MikroTik и RouterOS - amneziawg-mikrotik-c (v1.4.3 от 8 октября 2026) и AmneziaWG-MikroTik. Таблица - в разделе Какое поколение AmneziaWG понимает клиент.
В: Можно ли переделать конфиг третьей линии обратно во вторую? О: Отредактировать клиентский конфиг третьей линии под вторую нельзя: поколение задаётся на стороне сервера, а часть параметров третьей линии двусторонние. По замеру от 30 августа 2026 ключ защиты заголовков, оставшийся только на одной стороне, даёт ноль рукопожатий и 100% потерь, причём молча, без сообщения об ошибке. Устройствам, оставшимся на второй линии, нужен сервер второго поколения: если такие устройства есть, ставьте сервер с --protocol=2.0.
В: Как сделать раздельный выход - российский трафик напрямую, остальное через заграницу? О: Это собирается каскадом из двух серверов: клиент подключается к серверу-входу (лучше в РФ), российский трафик уходит напрямую с него, остальное - через второй сервер за границей. Каскад не входит в установщик (другой масштаб), но есть отдельная пошаговая инструкция - CASCADE.md.
В: Российские сайты не открываются через VPN, потому что не пускают адреса зарубежных дата-центров. Что делать, если сервер один? О: Завернуть только российский сегмент во второй выход через Cloudflare WARP, а остальной трафик оставить прямым. Список российских сетей сервер получает автоматически по BGP, вести его руками не нужно. Российские сайты увидят адрес Cloudflare вместо адреса дата-центра. Пошаговая инструкция - WARP-RU.md. Если нужен именно российский IP, а не адрес Cloudflare, потребуется второй сервер в РФ и каскад (CASCADE.md).
В: AmneziaVPN пишет "данный сервер не поддерживает раздельное туннелирование". Как включить? О: Это ограничение самого клиента, а не сервера. Встроенное раздельное туннелирование по сайтам и приложениям в приложении AmneziaVPN включается только когда конфиг гонит в туннель весь трафик. Клиент смотрит на AllowedIPs: полный туннель разблокирует функцию, а частичный список подсетей клиент считает уже разделённым на уровне маршрутов и прячет свой переключатель с этой надписью. Надёжная форма полного туннеля, которую он распознаёт, - пара 0.0.0.0/0, ::/0, и именно её выдаёт установка по умолчанию. Надпись появляется, когда клиенту достался список подсетей вместо 0.0.0.0/0, ::/0: так выдаёт режим «Amnezia» (--route-amnezia), свой список сетей (--route-custom=) и индивидуальный AllowedIPs, заданный через modify. Решение, docker не нужен: переведите клиента на полный туннель - замените строку в его .conf на AllowedIPs = 0.0.0.0/0, ::/0 и переимпортируйте, либо перевыпустите клиента в режиме "Весь трафик" (--route-all). После этого страница раздельного туннелирования в приложении откроется, и сайты/приложения выбираются уже там. Если же нужно просто пустить в туннель часть трафика (сплит на уровне сети), это делает сам AllowedIPs - отдельная функция приложения для этого не требуется.
В: Десктопный AmneziaVPN на macOS виснет при подключении. Что делать? О: По issue #159 (июль 2026) десктопное приложение AmneziaVPN на macOS не справлялось с маскирующим пакетом I1 (CPS) и зависало на подключении; на текущих версиях приложения это не перепроверено. Мобильные (iOS/Android) и CLI-клиенты CPS понимают и подключаются нормально. Ставьте с флагом --no-cps: установщик уберёт I1 из серверного конфига и всех клиентов, и десктоп подключится. Теряется только слой CPS, остальная обфускация (Jc/S1-S4/H1-H4, а на сервере 3.1 и шифрование заголовков) остаётся. На уже установленном сервере то же самое через переустановку (поколение протокола она не меняет): sudo bash install_amneziawg.sh --force --no-cps, затем перевыпустите существующих клиентов sudo bash /root/awg/manage_amneziawg.sh regen (без этого в клиентском конфиге останется I1, а десктопное приложение спотыкается именно на нём). Чтобы позже вернуть CPS, переустановите с любым флагом перегенерации набора, например --preset=default - учтите, что это перегенерирует ВЕСЬ набор обфускации (H1-H4/S1-S4 тоже), поэтому после возврата снова нужен regen всех клиентов. Флаг убирает только I1: если вы вручную прописывали I2-I5, они останутся в конфигах. Issue #159.
В: Как изменить порт AmneziaWG после установки? О: 1. Измените ListenPort в /etc/amnezia/amneziawg/awg0.conf. 2. Измените AWG_PORT в /root/awg/awgsetup_cfg.init. 3. Обновите UFW (sudo ufw delete allow <старый_порт>/udp, sudo ufw allow <новый_порт>/udp). 4. Перезапустите сервис (sudo systemctl restart awg-quick@awg0). 5. Перегенерируйте конфиги ВСЕХ клиентов (sudo bash /root/awg/manage_amneziawg.sh regen) и передайте их клиентам.
В: Как изменить внутреннюю подсеть VPN? О: Проще всего выполнить деинсталляцию (sudo bash ./install_amneziawg.sh --uninstall) и установить заново, указав новую подсеть при первом запуске. Переустановка поверх живого сервера (--force) с другой подсетью прерывается, пока в конфиге есть клиенты - их адреса выданы в старой подсети.
В: Как изменить MTU? О: Начиная с v5.7.4 MTU = 1280 устанавливается автоматически. Для изменения остановите туннель (sudo systemctl stop awg-quick@awg0) и отредактируйте строку MTU = <значение> в секции [Interface] файла /etc/amnezia/amneziawg/awg0.conf и в .conf файлах клиентов. Там же, в строках PostUp и PostDown файла awg0.conf, поменяйте значения --set-mss: у правил iptables на 40 меньше MTU, у правил ip6tables (если они есть в PostUp) на 60 меньше. При MTU 1200 это 1160 и 1140. Без этого крупные пакеты перестанут пролезать в туннель, и часть сайтов будет открываться через раз. Затем запустите туннель: sudo systemctl start awg-quick@awg0. Останавливать его до правки нужно, чтобы старые правила MSS снялись по старым значениям. Подробнее - в разделе MTU и мобильные клиенты.
В: Где хранятся параметры обфускации? О: После установки - в секции [Interface] серверного конфига /etc/amnezia/amneziawg/awg0.conf. Он источник истины для manage: именно оттуда add и regen берут значения для клиентских конфигов. Оттуда же их берёт переустановка (--force), если не заданы флаги --preset/--mobile/--jc/--jmin/--jmax, которые перегенерируют набор. Копия параметров (AWG_Jc, AWG_S1..S4, AWG_H1..H4, AWG_I1..I5) лежит и в /root/awg/awgsetup_cfg.init, но используется, только когда awg0.conf нет, то есть обычно при первой установке: правка только в ней не дойдёт ни до сервера, ни до клиентов. manage предупреждает, если init изменён позже awg0.conf и значения в них расходятся. Порядок ручной правки - в следующем вопросе. На сервере 3.1 в [Interface] есть ещё HeaderProtectionKey и ContentPaddingAddition, а ключ дополнительно лежит копией в /root/awg/server_hpk.key.
В: Можно ли изменить параметры обфускации после установки? О: Да. Это полезно, если оператор начал опознавать ваш сервер по параметрам обфускации. Порядок действий:
  1. Отредактируйте параметры (Jc, S1-S4, H1-H4, I1-I5) в /etc/amnezia/amneziawg/awg0.conf в секции [Interface]; имена ключей пишите ровно как в файле.
  2. Перезапустите сервис: sudo systemctl restart awg-quick@awg0.
  3. Перегенерируйте конфиги всех клиентов: sudo bash /root/awg/manage_amneziawg.sh regen. regen читает актуальные значения прямо из awg0.conf.
  4. Раздайте новые .conf / QR-коды / vpn:// URI клиентам.
Сервер 3.1 (по умолчанию). H1-H4 стоят на 1-4 намеренно, и менять их бессмысленно: тип сообщения прячет ключ защиты заголовков, он же делает каждую установку уникальной. S1-S4 и I1 меняются тем же порядком, только S1-S4 не ниже 12. Новый ключ HeaderProtectionKey даёт переустановка (--uninstall + установка), и все профили тогда выдаются заново.

Сервер 2.0. Совпадать на сервере и всех клиентах обязаны S1-S4 и H1-H4, иначе handshake не пройдёт; Jc/Jmin/Jmax и I1-I5 совпадать не обязаны. Новый случайный набор H1-H4 и S1-S4 проще всего получить переустановкой с флагом перегенерации (--force --preset=default) и затем regen всех клиентов.

Подробный порядок - в разделе Изменение настроек по умолчанию.
В: Чем это отличается от официального приложения Amnezia? О: Под капотом тот же протокол AmneziaWG с той же обфускацией. Отличается то, как разворачивается и работает сервер. Официальное приложение Amnezia - графический клиент: указываешь сервер, и оно ставит серверную часть в Docker-контейнерах по SSH, не выполняя такой настройки и защиты самого сервера. Этот установщик создан, чтобы выжать из выделенного VPS максимум как из VPN-сервера, поэтому работает иначе:
  • AmneziaWG ставится модулем ядра (DKMS), без Docker - нет постоянного демона и его расхода RAM/CPU.
  • Весь сервер оптимизируется под железо: sysctl-буферы, swap, BBR, срез лишних пакетов.
  • Поверхность атаки минимальна: UFW deny-all, Fail2Ban, строгие права, sysctl-хардненинг, один сервис вместо стека.
  • Доступна тонкая настройка: пресет для мобильных сетей и прямой доступ к параметрам AmneziaWG.
  • Управление из CLI (manage add/remove/list/--expires), готовые сборки под ARM, headless-режим для автоматизации.
Подробное сравнение - на отдельной странице.
В: Сервер на Hetzner недоступен из России: рукопожатие проходит, потом трафик замирает. Что делать? О: Скорее всего сервер попал в автономную систему, которой нет в белом списке РКН (Hetzner - AS24940). Обычный junk не помогает; проходит пакет I1/CPS, замаскированный под QUIC с разрешённым SNI (для Hetzner - 7-zip.org). Метод работает не у всех операторов. Полевые результаты и инструкция - в разделе Хостинг недоступен из России.
В: Сервер за NAT — как указать внешний IP? О: Используйте флаг --endpoint=<внешний_IP> при установке: sudo bash ./install_amneziawg.sh --endpoint=1.2.3.4. На уже установленном сервере впишите адрес в /root/awg/awgsetup_cfg.init (строка export AWG_ENDPOINT='1.2.3.4') и перевыпустите клиентов: sudo bash /root/awg/manage_amneziawg.sh regen. Если AWG_ENDPOINT пуст, regen определяет внешний IP сам.
В: Как настроить проброс портов (NAT) для AmneziaWG? О: Если сервер находится за NAT (например, в облаке с приватным IP): 1. Пробросьте UDP-порт AmneziaWG (по умолчанию 39743) на внешний IP. 2. При установке укажите внешний IP: --endpoint=ВНЕШНИЙ_IP. 3. Убедитесь, что фаервол провайдера разрешает входящий UDP на этот порт.
В: Как изменить DNS для всех существующих клиентов? О: Используйте команду modify для каждого клиента: sudo bash /root/awg/manage_amneziawg.sh modify <имя> DNS "8.8.8.8,1.0.0.1". Затем перегенерируйте конфиги: sudo bash /root/awg/manage_amneziawg.sh regen. DNS для новых клиентов задаётся строкой CLIENT_DNS в awgsetup_cfg.init, см. Изменение настроек по умолчанию.
В: Как мониторить трафик VPN? О: 1. Текущие подключения: sudo awg show. 2. Статистика передачи: sudo awg show awg0 transfer. 3. Логи сервиса: sudo journalctl -u awg-quick@awg0 -f. 4. Общий статус: sudo bash /root/awg/manage_amneziawg.sh check.
В: Клиент пишет «неверный ключ» или «неизвестный ключ» при импорте конфига? О: Клиент не понимает поколение сервера. Если он спотыкается на s3, s4 или I1, он старее второй линии; если на HeaderProtectionKey или ContentPaddingAddition, он не понимает 3.1. Обновите клиент: amneziawg-windows-client 3.1.0+ для сервера 3.1 (2.0.0+ для сервера 2.0) или Amnezia VPN 5.0.1.5+ (4.8.12.7+ для 2.0). Остальные клиенты - в таблице Какое поколение AmneziaWG понимает клиент.
В: AWG 2.0-сервер не handshake-ится с моим старым AWG 1.0-клиентом — почему? О: Когда сервер генерирует S3>0 или S4>0 (cookie-/data-padding из AWG 2.0), AWG 1.0-клиент не сможет с ним handshake-нуться - это известная upstream-проблема: amnezia-vpn/amneziawg-linux-kernel-module#168. Мой инсталлятор всегда генерирует оба >0: в профиле 2.0 S3=8..55, S4=4..27, в профиле 3.1 от 12.

В типичном сценарии (Amnezia VPN client / WireGuard-Tools 2.0+ на клиентах + клиентские .conf, сгенерированные manage add) проблемы нет: manage всегда вписывает S3/S4 в клиентский .conf автоматически. Риск возникает только при:
  • ручной правке клиентских .conf со снятием S3/S4;
  • импорте серверного preset в WireGuard-клиент без AWG-расширений (обычный wg-quick на старом ядре, без amneziawg-модуля);
  • миграции с AWG 1.x setup, где клиенты намеренно использовали S3=0/S4=0.
Решение: использовать AWG 2.0-совместимый клиент (Amnezia VPN >= 4.8.12.7 или amneziawg-windows-client >= 2.0.0) и держать S3/S4 в client .conf идентичными серверным. Если очень нужен AWG 1.0 fallback — это отдельная задача за пределами штатного сценария установки, ждите фикса в upstream-issue #168.
В: Ошибка DKMS при обновлении ядра — что делать? О: 1. Проверьте статус: dkms status. 2. Попробуйте пересобрать: sudo dkms install amneziawg/$(dkms status | grep amneziawg | head -1 | awk -F'[,/ ]+' '{print $2}'). 3. Убедитесь, что установлены заголовки ядра: sudo apt install linux-headers-$(uname -r). 4. При неустранимой ошибке запустите диагностику: sudo bash ./install_amneziawg.sh --diagnostic.
В: Что меняется для меня после установки v5.12.0+ при обновлении ядра? О: До v5.12.0 после apt upgrade ядра DKMS не всегда успевал пересобрать модуль amneziawg к моменту следующего reboot. Симптом: awg-quick@awg0 падает с modprobe: FATAL: Module amneziawg not found, и VPN лежит до ручной правки.

В v5.12.0 я добавил три страховки, которые работают прозрачно:
  1. apt hook /etc/apt/apt.conf.d/99-amneziawg-post-kernel — после apt upgrade хелпер /usr/local/sbin/amneziawg-ensure-module --hook пересобирает DKMS под новое ядро. Лог: /var/log/amneziawg-ensure-module.log (weekly rotate, 4 копии).
  2. systemd unit amneziawg-ensure-module.service — на boot перед awg-quick@awg0 хелпер итерирует ядра с уже установленными headers, пересобирает DKMS под текущее ядро, делает modprobe amneziawg и проверяет загрузку через lsmod. Если headers ещё не установлены — пишет WARN и завершает успехом, не блокируя загрузку. Логи в journal: journalctl -u amneziawg-ensure-module.service.
  3. manage repair-module — явный fallback: sudo bash /root/awg/manage_amneziawg.sh repair-module доустановит kernel-headers (с AWG_ALLOW_APT_IN_ENSURE=1), пересоберёт DKMS, перезапустит awg-quick.
Ручное восстановление (если все три auto-пути не сработали или установка ещё на v5.11.x):
sudo apt install linux-headers-$(uname -r)
sudo dkms autoinstall
sudo modprobe amneziawg
sudo systemctl restart awg-quick@awg0
Ограничения:
  • ARM prebuilt (Raspberry Pi, Hetzner CAX, Oracle Ampere) использует готовый .deb, а не DKMS - auto-repair не задействован. После kernel upgrade запустите установщик повторно: он подберёт новый prebuilt или перейдёт на DKMS. manage repair-module недостающий готовый модуль не заменит.
  • Облачные ядра (Azure / AWS / GCP / Oracle / Debian-cloud) — installer определяет meta-package по суффиксу uname -r (например, linux-headers-azure). Если у вас custom kernel или нестандартный flavor — manage repair-module сделает то же самое в reactive-режиме.
В: Подробности миграции VPN на другой сервер? О: 1. На старом сервере: sudo bash /root/awg/manage_amneziawg.sh backup. 2. Скопируйте архив: scp root@старый_сервер:/root/awg/backups/awg_backup_*.tar.gz .. 3. На новом сервере установите AmneziaWG того же поколения, что на старом (для сервера 2.0 - с --protocol=2.0): restore возвращает сервер к поколению копии и предупреждает об этом. Бэкап сервера 3.1 переносит и ключ защиты заголовков, поэтому клиентам после переезда нужны новые конфиги только ради нового адреса. Хотите заодно перейти с 2.0 на 3.1 - не восстанавливайте копию, а выдайте клиентам новые профили. 4. Скопируйте бэкап: scp awg_backup_*.tar.gz root@новый_сервер:/root/awg/backups/. 5. Восстановите: sudo bash /root/awg/manage_amneziawg.sh restore (интерактивный выбор, или укажите полный путь к архиву). 6. Проверьте то, что приехало со старого сервера: в /etc/amnezia/amneziawg/awg0.conf строки PostUp/PostDown содержат имя сетевого интерфейса старой машины (-o eth0 и т.п.). Если у нового сервера он называется иначе (ip route get 1.1.1.1), замените имя и перезапустите сервис (sudo systemctl restart awg-quick@awg0). ListenPort должен совпадать с портом, открытым в UFW. Если в /root/awg/awgsetup_cfg.init задан AWG_ENDPOINT, впишите туда новый адрес или оставьте пустым для автоопределения. 7. Перегенерируйте конфиги с новым IP: sudo bash /root/awg/manage_amneziawg.sh regen. 8. Раздайте новые конфиги клиентам.
В: Не подключается смартфон через мобильную сеть / не работает на iPhone О: Проверьте строку MTU = 1280 в секции [Interface] серверного и клиентского конфигов: установщик ставит её сам с v5.7.4, в более старых конфигах её надо добавить (сотовые сети имеют MTU ниже стандартных 1420, а iOS строго обрабатывает PMTU, подробнее - в разделе MTU и мобильные клиенты). Если строка на месте, а рукопожатие на мобильной сети не собирается, дело обычно в I1 или порте: см. Рукопожатие не собирается на мобильном интернете, а при нестабильном подключении - следующий вопрос. Клиенту сервера 3.1 нужна поддержка 3.1, см. таблицу клиентов.
В: iPhone подключается, но через ~10 секунд трафик пропадает (туннель «висит») О: Исправлено в v5.16.1. Причина - тогдашний режим маршрутизации по умолчанию (mode 2, «Список Amnezia+DNS») начинался с диапазона 0.0.0.0/5, который включает служебный 0.0.0.0/8. Ядро iOS спотыкается на этом блоке и не доходит до остальных маршрутов, поэтому туннель поднимается и через ~10 секунд встаёт (симптом легко спутать с DPI). Разобрался и предложил фикс @LiaNdrY (Issue #42). В v5.16.1 первый диапазон списка разбит на 1.0.0.0/8, 2.0.0.0/7, 4.0.0.0/6 - это тот же охват без проблемного нулевого блока, частные сети по-прежнему остаются вне туннеля.

На уже установленном сервере (до v5.16.1) сохранённый список лежит в /root/awg/awgsetup_cfg.init и обычной переустановкой с --force не меняется (берётся из конфига). Поэтому: (1) быстрый разовый фикс - в конфиге iOS-клиента заменить строку AllowedIPs = ... на AllowedIPs = 0.0.0.0/0; (2) сохранить список режима «Amnezia» - отредактировать /root/awg/awgsetup_cfg.init, заменив начальный 0.0.0.0/5 на 1.0.0.0/8, 2.0.0.0/7, 4.0.0.0/6, затем пересоздать клиента (remove + add); (3) либо чистая установка заново (--uninstall, затем установка v5.16.1) - тогда список сгенерируется корректно.
В: Подключается через мобильную сеть только с третьего раза / нестабильно О: Если на мобильной сети рукопожатие не собирается вовсе, начните с разбора Рукопожатие не собирается на мобильном интернете: по замеру сентября 2026 на МТС Москва рукопожатие решает форма маскирующего пакета I1, а количество и размер junk-пакетов (Jc, Jmin, Jmax) на него не влияют. Если же подключение просто нестабильно, попробуйте флаг --preset=mobile (с v5.10.0): у него junk-пакетов меньше и они мельче (Jc=3). В Discussion #38 (@elvaleto) на Таттелеком (Летай) с Jc=4-8 подключалось раза с третьего, а после снижения Jc = 3 заработало сразу.

Новая установка (рекомендуется):
sudo bash install_amneziawg.sh --preset=mobile --yes
Существующая установка — ручная правка:
  1. Откройте /etc/amnezia/amneziawg/awg0.conf и замените Jc на 3. Если I1 вида <r N> с N больше 64, замените его на строку формы DNS (где её взять - в разборе) или на <r 64>. I1 формы DNS, который пишут установки v5.33.0 и новее, не трогайте.
  2. sudo systemctl restart awg-quick@awg0
  3. sudo bash /root/awg/manage_amneziawg.sh regen <имя_клиента> для каждого клиента.
  4. Раздайте обновлённые конфиги.
Если рукопожатие так и не собирается, снижать junk дальше бесполезно: на замеренном маршруте дело было в I1, см. разбор.

Отчёты по операторам (из issues/discussions):
ОператорПараметрыРекомендацияРезультат
Таттелеком (Летай)Jc=3, I1=<r 64>--preset=mobile✅
Yota (Москва)I1=<b 0xce...>, Jmax=261--preset=mobile✅
Yota/Tele2 (Москва)Jc=3, Jmin=40, Jmax=70--preset=mobile✅
Tele2 (Красноярск)ранее I1=отсутствует; май 2026: I1=<r 48>--preset=mobile; в майскую волну I1=<r 48>✅
МТС (Приморье)Jc=3, I1=<r 48> (май 2026)--preset=mobile + I1=<r 48>✅
МТС (Москва)случайный I1=<r 96> и длиннее не проходит, <r 64> и I1 формы DNS проходят; Jc/Jmin/Jmax не влияют (замер, сентябрь 2026)I1 формы DNS (на новых установках с v5.33.0 его пишет установщик) или <r 64>, см. разбор✅
Beelineдефолт--preset=default✅
Megafon (Москва)Jc=3, Jmin=80, Jmax=268--preset=mobile🔄 тестируется
Megafon (регионы)I1=отсутствует--preset=mobile + удалить I1✅
Т-Мобайл (Москва и область)узкий профиль (как в приложении Amnezia): Jc=6, Jmin=10, Jmax=50, DNS-мимик I1=<r 2><b 0x8580...> (полный вид в разделе про роутеры ниже); полный туннель 0.0.0.0/0, ::/0ручные параметры; профиль в diagnose --carrier=tmobile_us (имя историческое, профиль относится к этому оператору; сверяет Jc/Jmin/Jmax и что I1 бинарного вида); --preset=mobile здесь не подходит✅
Tele2 + Мегафон (Кемерово, 42)случайный I1 (<r N>) перестал держаться через 2+ дня; работает QUIC-мимикрия I1=<b 0xc3...> либо I1=отсутствует--preset=mobile + I1=<b 0xc3...> (QUIC) либо удалить I1✅

«I1=отсутствует» означает: в /etc/amnezia/amneziawg/awg0.conf и в клиентских .conf удалить строку I1 = ... целиком (не оставлять пустую). Это режим без маскирующего пакета: остальная обфускация остаётся, а CPS нет (если вы не задавали I2-I5), и handshake проходит DPI у некоторых региональных операторов, где CPS-пакеты сами триггерят блок (Issue #42, @alkorrnd). После правки на сервере: sudo systemctl restart awg-quick@awg0. На клиентах - sudo bash /root/awg/manage_amneziawg.sh regen <имя> для каждого, и раздать новые конфиги.
Обновление, май 2026: в майскую волну блокировок вариант I1=отсутствует на Tele2 (Красноярск) перестал срабатывать, а короткий I1 = <r 48> прошёл DPI. То же сработало на МТС (Приморье). Тогда это объяснили размером: меньшее значение <r 48> менее заметно для DPI. ⚠️ Замер сентября 2026 уточняет причину: решает не размер, а ФОРМА пакета. Пакет из случайных байт режется независимо от того, велик он или мал (мал - просто реже), а пакет той же длины, но похожий на настоящий протокол, проходит. Короткий <r 48> помогает потому, что на коротком мусоре фильтру не за что зацепиться, и это слабее, чем осмысленная форма. Подробности и таблица: рукопожатие не собирается на мобильном интернете. Если --preset=mobile или I1=отсутствует не помогают - попробуйте I1 = <r 48>. Профиль diagnose --carrier=tele2_krasnoyarsk пока отражает прежнее I1=отсутствует (Issue #42), так что для майской волны задайте I1 = <r 48> вручную (Discussion #38, @alkorrnd + @etotent).
QUIC-мимикрия I1 (экспериментально): вместо случайного <r N> можно задать I1 как блок, имитирующий начало QUIC-пакета: I1 = <b 0xc30000000108><r 8><b 0x08><r 8><b 0x0045dc><t><r 16>. Первые байты (0xC3 + версия) похожи на QUIC v1 long-header, и DPI, который классифицирует UDP/443 как QUIC, в этом отчёте поток пропустил. На Tele2/Мегафон (Кемерово) держится 2+ дня (Issue #42, @Fourdot-co). Это client-side параметр, меняется только в клиентских .conf, синхронизировать с сервером не нужно; учтите, что правка только одного экспортированного .conf потеряется при следующей перегенерации клиента (regen). Важно: не берите за основу TLS ClientHello (<b 0x160301...>) - это TCP-формат, в UDP DPI распознает TCP-структуру и дропнет пакет. Для UDP-мимикрии подходят QUIC long-header или DTLS (тот же тип handshake ClientHello, но с record header, где добавлены epoch и sequence number).
Как проверить, блокирует ли оператор ваш VPN-сервер (диагностика ТСПУ): если AmneziaWG не пробивается на конкретном операторе, сначала стоит понять, блокируется ли сам IP сервера и по какому признаку. Открытый сканер ByeByeVPN смотрит на адрес со стороны цензуры и помогает отличить проблему параметров обфускации (тогда подбирайте Jc/I1 по таблице выше) от блокировки по AS/IP (тогда см. раздел Хостинг недоступен из России). Для ориентира: стоковая установка получает у этого сканера 100/100 CLEAN (проверено на версии 2.8.3 в августе 2026). Его пробы AmneziaWG направлены в порты 51820 и 55555, а установщик по умолчанию слушает 39743; но и на 51820 сервер такие пробы оставляет без ответа, потому что рукопожатие, собранное без его публичного ключа, он молча отбрасывает. Читать это как «необнаружимо» нельзя: сканер задаёт серверу вопросы, а пассивный анализ трафика у оператора устроен иначе и в такой проверке не участвует.
В: Скрипт ломает VNC-консоль хостера / потеря сети на Hetzner О: До v5.8.2 скрипт устанавливал net.ipv4.conf.all.rp_filter = 1 (strict reverse-path filtering). На Hetzner и подобных облачных хостерах, где шлюз находится в другой подсети чем IP самой VPS, strict mode ломает routing — ответные пакеты не проходят проверку обратного пути. Симптомы: VPS периодически теряет сеть (раз в сутки), а VNC-консоль забивается строками [UFW BLOCK] от Fail2Ban и становится непригодной для работы. Discussion #41 (@z036). С v5.8.2 rp_filter установлен в 2 (loose mode), который проверяет source IP по любому маршруту в таблице (не только обратному через тот же интерфейс), и добавлен kernel.printk = 3 4 1 3 для подавления не-критических kernel messages на VNC-консоли. Если у тебя установка до v5.8.2 — исправь вручную:
  1. Открой /etc/sysctl.d/99-amneziawg-security.conf
  2. Замени rp_filter = 1 на rp_filter = 2 (обе строки: conf.all и conf.default)
  3. Добавь строку kernel.printk = 3 4 1 3
  4. sudo sysctl -p /etc/sysctl.d/99-amneziawg-security.conf
В: Не работает ping между сервером и клиентами внутри туннеля О: Скрипт устанавливает ufw default deny incoming — это блокирует всё входящее на всех интерфейсах, включая awg0. Forward-правило ufw route allow in on awg0 out on <public_iface> разрешает только туннель → интернет, а input на awg0 (пакеты от клиентов на сам сервер, в том числе ICMP echo-request) под него не попадает.

Дополнительно: если ты правил /etc/ufw/before.rules и заменил ACCEPT на DROP для ICMP без указания интерфейса, эти правила применяются ко всем интерфейсам — включая awg0.

Решение:
  1. Открой входящее на awg0 в UFW:
    sudo ufw allow in on awg0
    sudo ufw reload
    Это разрешает входящие на интерфейс туннеля целиком — узкая фильтрация ICMP делается через -i в before.rules (см. ниже).
  2. Если ты правил /etc/ufw/before.rules, добавь -i <public_iface> ко всем DROP-строкам ICMP:
    # вместо
    -A ufw-before-input -p icmp --icmp-type echo-request -j DROP
    # так (ens3 — твой публичный интерфейс)
    -A ufw-before-input -i ens3 -p icmp --icmp-type echo-request -j DROP
    То же самое для destination-unreachable, time-exceeded, parameter-problem. Имя публичного интерфейса: ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++) if($i=="dev") print $(i+1)}'. Применить: sudo ufw reload.
Не работает: ufw allow in on awg0 proto icmp — UFW не поддерживает icmp через флаг proto (только tcp/udp/esp/ah/gre/ipv6).

Проверка: с клиента ping <IP_сервера_в_туннеле>. С сервера на клиента (ping <IP_клиента>) может не отвечать сам клиент: на Windows и iOS встроенный фаервол часто режет echo-request — поэтому надёжнее проверять с клиента на сервер.

Если ты вручную правил AllowedIPs на клиенте под split tunneling (через VPN идут только нужные подсети - например, только Telegram/Discord, а остальной трафик мимо), убедись что в списке есть подсеть туннеля (10.9.9.0/24 или твоя кастомная). Без неё клиент не маршрутизирует в туннель даже пакеты к самому серверу - ufw status verbose и iptables -L ufw-before-input -v -n могут выглядеть правильно, а ping всё равно не идёт. Покрытие зависит от выбранного режима: дефолтный --route-all (полный туннель 0.0.0.0/0) включает подсеть туннеля автоматически; --route-amnezia (Amnezia List, исключает 10.0.0.0/8) и --route-custom= - нет, добавляй вручную.

Если нужен пинг между клиентами (телефон ↔ роутер через сервер): sudo ufw route allow in on awg0 out on awg0 && sudo ufw reload. AllowedIPs в клиентских .conf зависит от режима, выбранного при установке (см. абзац выше). Discussion #63.
В: Работает ли AmneziaWG в LXC-контейнере? О: Установщик - нет: он ставит модуль ядра через DKMS, а контейнер делит ядро с хостом и свой модуль загрузить не может, поэтому в контейнере установщик останавливается в самом начале с сообщением «Обнаружен контейнер». Варианты: полноценная VM (KVM/QEMU) или bare-metal для обычной установки, либо userspace-реализация amneziawg-go внутри LXC, настроенная вручную: LXC / Docker через amneziawg-go.
В: --endpoint отклоняется с ошибкой «Некорректный --endpoint» — что проверить? О: С v5.8.0 значение флага --endpoint проходит валидацию перед записью в конфиги. Разрешены три формата: FQDN (vpn.example.com), IPv4 (1.2.3.4), IPv6 в квадратных скобках ([2001:db8::1]). Запрещены перевод строки, CR, одинарные и двойные кавычки, обратный слеш, пробелы и табуляции — они могли бы инжектиться в awgsetup_cfg.init и клиентские .conf. Если нужно передать IPv6 — оберните в []. Если AWG_ENDPOINT в awgsetup_cfg.init не проходит валидацию при повторном запуске, инсталлятор выводит log_warn и использует автоопределение через get_server_public_ip.
В: «Другой экземпляр install_amneziawg.sh уже запущен» — что это? О: С v5.8.0 инсталлятор берёт process-wide flock на /root/awg/.install.lock в начале initialize_setup(). Это защищает от двух параллельных запусков которые иначе могли бы гонять apt-get одновременно и сломать package state. Если ты видишь эту ошибку но никакого второго инсталлятора нет (процесс висит / упал) — удали /root/awg/.install.lock и попробуй снова.
В: Почему --uninstall не отключил UFW? О: Это поведение с v5.8.0. Инсталлятор записывает маркер /root/awg/.ufw_enabled_by_installer только если активировал UFW сам (до этого UFW был в состоянии inactive). При --uninstall UFW отключается только при наличии маркера. Если до установки нашего скрипта UFW уже был активен (например, для защиты SSH или web-сервисов), --uninstall удалит наши правила (VPN-порт, awg0 routing; добавленное правило SSH rate-limit при этом остаётся), но оставит UFW активным. Это защита от destructive uninstall на чужой инфраструктуре. Если тебе нужно принудительно отключить UFW — ufw disable вручную.
В: regen говорит «отсутствуют обязательные AWG-параметры» — что делать? О: С v5.8.0 load_awg_params читает AWG-параметры напрямую из live /etc/amnezia/amneziawg/awg0.conf, а не из закешированного awgsetup_cfg.init. Если ты правил awg0.conf руками и удалил/повредил одно из обязательных полей (Jc, Jmin, Jmax, S1-S4, H1-H4), regen упадёт с этой ошибкой вместо того чтобы молча использовать устаревшие значения из init-файла. Это защита от split-brain между сервером и клиентами. Что делать: (1) проверь grep -E "^(Jc|Jmin|Jmax|S[1-4]|H[1-4]) = " /etc/amnezia/amneziawg/awg0.conf - все 11 полей должны быть; (2) если поле удалено, восстанови его из /root/awg/awgsetup_cfg.init или из awg0.conf.bak-* бэкапа; (3) перезапусти сервис и повтори regen. На сервере 3.1 regen после этой проверки сверяет ещё HeaderProtectionKey в awg0.conf с его копией /root/awg/server_hpk.key; если ошибка про ключ, не создавайте новый (он отрежет всех клиентов). В awg0.conf ключ, заданный серверу (живой интерфейс подхватит его правку только после перезапуска), а в файле - ключ, из которого выпускались профили. Если они разошлись, решите, какой у ваших клиентов: сравните с любым клиентским .conf. Если верен ключ из awg0.conf, уберите файл в сторону (mv /root/awg/server_hpk.key /root/awg/server_hpk.key.old) и запустите manage regen: пропавший файл manage восстанавливает из конфига сам. Если верен ключ из файла, впишите его в строку HeaderProtectionKey в awg0.conf и перезапустите awg-quick@awg0 (или верните конфиг из бэкапа командой manage restore, но бэкап может быть старше последних клиентов).
В: Клиент amneziawg-windows-client подчёркивает H2-H4 красным и не даёт редактировать конфиг О: Это upstream-баг в standalone Windows-клиенте amneziawg-windows-client (форк wireguard-windows с AWG-патчами). Его встроенный редактор конфигов в ui/syntax/highlighter.go ограничивает H1-H4 диапазоном [0, 2147483647] (это 2^31-1, INT32_MAX), хотя спецификация AmneziaWG допускает полный uint32 (0-4294967295). Значения выше 2^31-1 на сервере работают нормально, но клиент подчёркивает их красным и может блокировать сохранение правок. Upstream issue: amnezia-vpn/amneziawg-windows-client#85 (открыт с февраля 2026, не исправлен). Наш installer с v5.8.1 генерирует H1-H4 в безопасной половине диапазона [0, 2^31-1] — новые установки совместимы с Windows-клиентом из коробки. Если у тебя установка v5.8.0 с «плохими» H: (1) обнови через --uninstall + install_amneziawg.sh v5.8.1 — новые H будут в безопасном диапазоне; либо (2) поправь H2/H3/H4 в awg0.conf вручную на значения меньше 2147483647, перезапусти сервис и перегенерируй клиентские конфиги через manage regen <имя>; либо (3) используй кросс-платформенный Amnezia VPN клиент вместо amneziawg-windows-client — у него этого ограничения нет. Discussion: #40.
В: Какой клиент использовать для AmneziaWG? О: На Android - WG Tunnel (для 3.1 >= 5.6.0) или лёгкий AmneziaWG (для 3.1 >= 3.1.4 в Google Play). В нашей проверке 13 октября 2026 на профиле 3.1 оба импортировали <имя>.png своим сканером, переподключались меньше чем за секунду и не теряли туннель при переходе с Wi-Fi на мобильную сеть. На iPhone, Mac и Windows - лёгкий AmneziaWG для вашей платформы (для 3.1: iOS и macOS >= 3.1.4, Windows >= 3.1.0); iPhone и Mac в этой проверке не участвовали. Amnezia VPN (для 3.1 >= 5.0.1.5, для 2.0 >= 4.8.12.7) тоже поддерживается и принимает ссылку vpn://; на Android в той же проверке версия 5.0.3 подключалась около 2 секунд, а после выключения Wi-Fi туннель не восстановился, в том числе по кнопке подключения, помог только перезапуск приложения. На Linux - awg-quick из amneziawg-tools с модулем или amneziawg-go, понимающими поколение сервера (для сервера 3.1 - третьей линии; сборка третьей линии работает и с 2.0), см. Подключение Linux-машины как клиента. Стандартный WireGuard-клиент не подходит. Полная таблица совместимости - в разделе Совместимость клиентов.
В: Туннель включился, а первый запрос открывается с задержкой О: У клиентов на движке amneziawg-go (лёгкие AmneziaWG для Android, iOS, macOS и Windows, Amnezia VPN) известна гонка: самый первый пакет данных после включения туннеля может уйти с паддингом S4 по умолчанию (0), а не с заданным в конфиге, и сервер его отбросит (amneziawg-go#168; исправление предложено в #184 и на 13 октября 2026 не влито). Потеря первого пакета обычно означает повторную передачу TCP-пакета или повтор DNS-запроса, то есть задержку; если приложение запрос не повторяет, он может закончиться тайм-аутом. WG Tunnel собран на собственном форке этого движка; есть ли гонка в нём, мы не проверяли. Сама по себе эта гонка не говорит о проблеме в конфиге или на сервере.

В нашей проверке 13 октября 2026 на профиле 3.1 задержки, которую можно связать с этой гонкой, не было: AmneziaWG 3.1.4 на Android открывал страницу меньше чем за секунду в 10 переподключениях из 10, WG Tunnel 5.8.1 - так же быстро. На Windows AmneziaWG 3.1.0 открывал первую страницу примерно через 3 секунды, но так же вёл себя и профиль 2.0: это время Windows проверяет адрес туннельного адаптера (DAD), на сам протокол приходится около 0.2 секунды. Результат относится к этим устройствам и сетям, на других бывает иначе.
В: Как ограничить скорость для клиентов? О: AmneziaWG не имеет встроенного ограничения скорости. Для этого используйте tc (traffic control): sudo tc qdisc add dev awg0 root tbf rate 100mbit burst 32kbit latency 400ms. Это ограничит общую пропускную способность интерфейса. Для per-client лимитов потребуется более сложная настройка с tc и iptables (mark + class).
--- ## 🩺 Диагностика и деинсталляция * **Диагностика:** `sudo bash /путь/к/install_amneziawg.sh --diagnostic`. Отчет (параметры обфускации включены, `PrivateKey`, `PresharedKey` и `HeaderProtectionKey` заменены на `[HIDDEN]`) сохраняется в `/root/awg/diag_*.txt`. * **Деинсталляция:** `sudo bash /путь/к/install_amneziawg.sh --uninstall`. Запросит подтверждение и предложит создать бэкап. ### Содержимое диагностического отчёта Отчёт (`--diagnostic`) включает следующие секции: | Секция | Описание | |--------|----------| | OS | Версия ОС и ядра (`uname -a`) | | Hardware | RAM, CPU, Swap | | Configuration | Содержимое `awgsetup_cfg.init` (секреты скрыты) | | Server Config | `awg0.conf` (ключи скрыты) | | Service Status | `systemctl status awg-quick@awg0` | | AWG Status | Вывод `awg show` | | AWG Version | Вывод `awg --version` | | Network Interfaces | Вывод `ip a` | | Listening Ports | Вывод `ss -lunp` | | Firewall Status | `ufw status verbose` | | Routing Table | Вывод `ip route` | | Cascade / Split Routing | Юнит `awg-routing`, правило `ip rule` по метке, таблица 100, наборы `ipset`, правила `mangle` и `nat` каскада; «не настроен», если каскада нет | | Kernel Params | `net.ipv4.ip_forward`, `net.ipv6.conf.all.disable_ipv6` | | AWG Journal (last 50) | Последние 50 строк журнала `awg-quick@awg0` | | Client List | Имена клиентов | | DKMS Status | Вывод `dkms status` | | Module Info | Сведения о загруженном модуле `amneziawg` | --- ## 🔧 Устранение неполадок (подробно)
Сервер не отвечает после перезагрузки на первом шаге Установщик прошёл первый шаг, ушёл в перезагрузку, и машина больше не отвечает: ни SSH, ни ping. Панель хостера при этом показывает её включённой. Сначала убедитесь, что сервер недоступен отовсюду, а не только из России: попробуйте ping или SSH из сети за пределами РФ или сервисом проверки доступности с узлами в разных странах. Если снаружи РФ сервер отвечает, он жив, и вероятна блокировка адреса или подсети хостера: см. [Хостинг недоступен из России](#as-blocking-adv). Но прежде проверьте, не заблокирован ли ваш собственный адрес: Fail2Ban и ограничение частоты SSH на сервере банят по адресу источника, а успешный ping ещё не значит, что работает SSH. Если не отвечает нигде, по сети сюда уже не попасть, поэтому первым делом нужна **консоль хостера** (VNC, KVM или последовательная). Она показывает, дошло ли дело до загрузки вообще, а панель управления этого не говорит. Что вы там увидите: - **приглашение входа `login:`** - система загрузилась, сломана сеть. Смотрите `ip -br a`, `ip route`, `ss -lntp`; - **`You are in emergency mode`** - загрузка остановилась сама, разбор ниже; - **паника ядра или меню загрузчика** - до системы дело не дошло, сфотографируйте экран целиком. Первый шаг обновляет систему и может поставить новое ядро; если загрузка ломается именно на нём, перезагрузитесь и в меню GRUB (пункт «Advanced options for Ubuntu» или «Advanced options for Debian GNU/Linux»; если меню не показывается, держите Shift или Esc при загрузке) выберите предыдущее ядро. Загрузились - приложите к issue вывод `uname -r` и `journalctl -b -1 -p err` (прошлую загрузку журнал помнит, только если он постоянный; на Debian 12 по умолчанию это не так). **Аварийный режим** означает, что systemd не смог смонтировать что-то из `/etc/fstab` и намеренно остановился. Само это не пройдёт: пока причина на месте, каждая загрузка будет заканчиваться там же. Снимите в консоли три блока: ```bash journalctl -b --no-pager | grep -iE "Dependency failed|Timed out|emergency" | tail -20 cat -A /etc/fstab; findmnt --verify blkid; ls -l /dev/disk/by-label/ ``` Как их читать: - строка `Timed out waiting for device dev-disk-by\x2dlabel-...` означает, что systemd не дождался раздела, записанного в fstab меткой. Ждёт он по умолчанию 90 секунд на раздел, после чего уходит в аварийный режим; - `blkid` метку показывает, а `/dev/disk/by-label/` пуст или отсутствует - символические ссылки не создал udev. Проверьте, на месте ли он: `command -v udevadm || echo "пакета udev нет"`; - `findmnt --verify` даёт не `0 parse errors` - повреждён сам fstab, смотрите вывод `cat -A`: он дорисовывает `$` в конце каждой строки, поэтому склеенные строки видно сразу. **Пакета `udev` нет.** Восстановите его и пересоберите initramfs, перечислив имена одной командой: ```bash apt-get install udev systemd initramfs-tools reboot ``` `systemd` в списке не случайно: `udev` собран из того же исходника и не уживается с `systemd` старее себя, поэтому поодиночке apt их не поставит и ответит `udev : Breaks: systemd (< ...)`. Отсутствие `-y` тоже намеренное: если apt соберётся что-то удалять, прочитайте список перед подтверждением. Если apt пожалуется на ещё один пакет, которого в команде нет (вида `X : Breaks: Y` или `X : Depends: Y`), допишите Y туда же и повторите. В issue #223 таким пакетом оказался `systemd-resolved`: он держал `systemd` на старой версии зависимостью на точную версию. ⚠️ Дописывайте только то, что apt назвал сам. В частности, `systemd-resolved` НЕ следует ставить наугад: на Debian со статическим резолвером или с `resolvconf` его может не быть вовсе, а он объявляет `Conflicts: resolvconf` и `Replaces: resolvconf`, то есть его установка снесёт `resolvconf` и может оставить уже повреждённый сервер ещё и без DNS. **udev на месте, а ссылок нет.** Попробуйте создать их вручную и продолжить загрузку: ```bash udevadm trigger --action=add --subsystem-match=block; udevadm settle; ls /dev/disk/by-label/ systemctl default ``` **Ссылки так и не появились.** Снимите зависимость загрузки от этих разделов: параметр `nofail` говорит systemd не считать их отсутствие поводом остановиться. ```bash cp /etc/fstab /etc/fstab.bak sed -i 's/defaults/defaults,nofail/; s/umask=0077/umask=0077,nofail/' /etc/fstab cat /etc/fstab reboot ``` Посмотрите вывод `cat`: `nofail` должен появиться у строк `/boot` и `/boot/efi`, а строка корня остаться нетронутой. ⚠️ Пока стоит `nofail`, раздел `/boot` не смонтирован, а обновления ядра пишут именно туда. До восстановления udev не ставьте новые ядра и отложите `apt upgrade`. Начиная с **v5.28.0** установщик проверяет это сам и останавливается ДО перезагрузки, если обновление системы унесло пакеты, без которых сервер не поднимется. С **v5.28.1** обновление на первом шаге и вовсе не может удалить установленный пакет: вместо `apt full-upgrade` там `apt-get upgrade --with-new-pkgs`, у которой такого права нет. Разбор остановки - в следующем блоке.
Установщик остановился: «Отсутствуют критичные пакеты» (v5.28.0+) Первый шаг запоминает, какие критичные для загрузки пакеты стоят в системе - `udev`, `initramfs-tools`, `openssh-server` и сетевой стек - и сверяет список перед тем, как уводить машину в перезагрузку. Список лежит в `/root/awg/boot-critical.pkgs` и переживает перезапуски установщика, поэтому пакет, потерянный в прерванном прогоне, не забывается. Если чего-то не хватает и восстановить не удалось, установщик останавливается **пока сервер ещё доступен**. Это не отказ установщика, а отказ перезагружаться в систему, которая не вернётся: после перезагрузки чинить пришлось бы уже через консоль хостера. Что делать, в порядке частоты: 1. **Пакет действительно удалён.** Поставьте всё одной командой, перечислив имена сразу, и запустите установщик снова: ```bash apt-get install <имя> <имя> ... ``` Именно вместе, а не по очереди: связанные пакеты вроде `udev` и `systemd` поодиночке не встанут, потому что каждая отдельная команда обязана оставить остальное нетронутым. Если какого-то имени apt не знает вовсе, он отменит транзакцию целиком - тогда уберите это имя и повторите. Без `-y`: если apt соберётся что-то удалять, прочитайте список перед подтверждением. 2. **apt отказывается ставить из-за удержанных пакетов.** `apt-mark showhold` покажет удержания. Снимите нужное: `apt-mark unhold <имя>`. 3. **Пакета больше нет в репозиториях.** Имя могло смениться при переходе на новый выпуск дистрибутива. Уберите устаревшую строку из `/root/awg/boot-critical.pkgs`. Файл удаляется по завершении установки, поэтому от предыдущих установок он не остаётся и устареть не успевает.
Нет интернета после подключения к VPN 1. Проверьте IP forwarding: `sysctl net.ipv4.ip_forward` (должно быть 1) 2. Проверьте NAT правила: `iptables -t nat -L POSTROUTING -v` 3. Проверьте AllowedIPs клиента (режим маршрутизации) 4. Проверьте DNS: `nslookup google.com` из VPN 5. Проверьте MTU: `ping -s 1280 -M do ` - если не проходит, уменьшите MTU, а вместе с ним и MSS (см. вопрос «Как изменить MTU?» в FAQ)
Handshake есть, но трафик не идёт 1. Проверьте MTU: добавьте `MTU = 1280` в `[Interface]` серверного и клиентского конфигов 2. Проверьте iptables: `iptables -L FORWARD -v` — должно быть правило ACCEPT для awg0 3. Проверьте NIC: `ip route get 1.1.1.1` — убедитесь, что PostUp/PostDown используют правильный интерфейс
Handshake проходит, но потом трафик умирает (DPI/ТСПУ, Hetzner, бесконечные re-handshake) Этот симптом отличается от пункта выше: рукопожатие **завершается один раз** (в журнале клиента появляется `Received handshake response`), пару секунд трафик может идти, потом наступает тишина. Клиент циклически пишет `Handshake did not complete after 5 seconds` и `stopped hearing back`, а `awg show` на сервере показывает резкую асимметрию: клиент отправил десятки КиБ, сервер получил пару КиБ, а `latest handshake` не обновляется. Сервер тут ни при чём - конфиг исправен. Так выглядит DPI-фильтрация по IP/AS хостера: оборудование на канале (в РФ это ТСПУ) пропускает начальный handshake, а установленный поток душит почти в ноль. Характерный след в `awg show`: у клиента принято около 92 байт (ответ на handshake уровня WireGuard; на проводе пакет крупнее из-за обфускации) и больше ничего, хотя отправлены десятки КиБ. По моим замерам стабильно затронут Hetzner (AS24940); крупные датацентровые сети (OVH, AWS, Azure и подобные) тоже в зоне риска - проверять нужно по конкретному IP и маршруту, блокировка не тотальная. Быстрая проверка, что режет канал, а не конфиг: поднимите тот же конфиг **из другой сети** (мобильный интернет, другая страна). Если оттуда туннель держится - конфиг рабочий, режут путь до текущего хостера. Что делать: 1. Поднимите тестовый сервер у другого хостера или в другой стране. Если там handshake держится стабильно - проблема в AS текущей площадки. 2. Перенесите сервер на хостера с «чистыми» IP, не помеченными как датацентровые. Свою рекомендацию держу в разделе [Хостинг](README.md#recomend-hosting) (FreakHosting): сам тестировал его на РФ-маршрутах, на момент написания AmneziaWG через него работает стабильно, в отличие от Hetzner. Это не гарантия - DPI меняется, перед переездом проверьте небольшой VPS. 3. Либо поставьте впереди промежуточный узел (bridge/relay) в «чистой» сети: клиент -> relay -> exit. Вход клиент->relay не подпадает под фильтр назначения, а relay->exit идёт между дата-центрами.
AmneziaWG не подключается: handshake не проходит, хотя обычный WireGuard на том же сервере работает Симптом: клиент пытается подключиться, но сервер рукопожатие AmneziaWG не обрабатывает - `tcpdump` показывает, что пакеты доходят на нужный порт и сервер их принимает, но в `awg show awg0` поле `latest handshake` остаётся пустым. При этом обычный WireGuard на том же сервере поднимается без проблем. Встречается не только в РФ, где DPI вообще ни при чём. Раз ванильный WireGuard работает, сеть, порт и фаервол можно вычеркнуть. Разница между ним и AmneziaWG - слой обфускации: `Jc`/`Jmin`/`Jmax`, `S1`-`S4`, `H1`-`H4`, `I1`-`I5`, а в профиле 3.1 ещё шифрование заголовков `HeaderProtectionKey`. Разбор входящего пакета опирается на `S1`-`S4`, `H1`-`H4` и (в 3.1) на ключ: если хоть что-то из этого на сервере и клиенте не совпадает байт-в-байт, сервер не может разобрать handshake и молча отбрасывает его - снаружи это выглядит как «пакеты идут, но не обрабатываются». **Сначала узнайте поколение сервера:** `sudo bash /root/awg/manage_amneziawg.sh check` пишет строку «Поколение протокола установки: 3.1» (или 2.0). На сервере 3.1 клиент обязан понимать 3.1 (таблица [Какое поколение AmneziaWG понимает клиент](#client-gen-adv)) и нести тот же `HeaderProtectionKey`, что в `awg0.conf`. Клиент без поддержки 3.1 ошибку часто не показывает: рукопожатия просто нет. Про жёлтую метку профиля в приложении Amnezia - [отдельный вопрос](#faq-yellow-adv). Что проверить: 1. Сверьте параметры обфускации в секции `[Interface]` на сервере и у клиента. Совпадать обязаны `S1`-`S4` и `H1`-`H4`, а на сервере 3.1 и `HeaderProtectionKey`: приёмник срезает этот паддинг и проверяет эти заголовки, поэтому любое расхождение здесь означает, что пакет отброшен и рукопожатие не сойдётся. В 2.0 `H1`-`H4` задаются диапазонами - диапазоны должны быть одинаковыми с обеих сторон. А `Jc`/`Jmin`/`Jmax` и `I1`-`I5` совпадать не обязаны: это отдельные пакеты-обманки, их шлёт инициатор рукопожатия, а вторая сторона отбрасывает, и **несовпадению** тут взяться неоткуда. ⚠️ Но из этого не следует, что `I1` безразличен рукопожатию: совпадение сторон он не требует, а вот его форма может помешать пакету рукопожатия дойти, потому что тот летит в одном залпе с ним. Это отдельный случай, разобранный ниже: [рукопожатие не собирается на мобильном интернете](#no-hs-mobile-adv). Регистр у `I1`-`I5` при этом важен: только верхний. 2. Сверьте версии на обоих концах: `awg --version`. Клиент, собранный отдельно (например, `amneziawg-tools` из AUR на Arch), нередко оказывается старее поколения сервера - тогда сервер ждёт одну обёртку, а клиент шлёт другую. Список совместимых клиентов - в разделе [Совместимость клиентов](#client-compat-adv). Частный случай (сервер AWG 2.0 с `S3`/`S4` > 0 и старый клиент AWG 1.0) - известная upstream-проблема, разобрана в [FAQ](#faq-advanced-adv).
Рукопожатие не собирается на мобильном интернете, хотя на Wi-Fi тот же профиль работает **Симптом.** На сотовой сети клиент бесконечно висит в состоянии «Подключение», трафика нет. Тот же самый профиль, тот же сервер и тот же порт на Wi-Fi поднимаются и работают полностью. 🔴 **Со стороны сервера это выглядит как рабочая связь, и в этом главная ловушка.** В `awg show` пир **виден**: поле `endpoint` меняется на мобильный адрес клиента, счётчик принятых байт растёт. Не обновляется ровно одно поле - `latest handshake`. **Почему так.** Транспортный пакет летит по одному и проходит. Пакет рукопожатия летит не один: перед ним идёт залп пакетов-пустышек (`Jc` штук) и маскирующий пакет `I1`. Если сеть отбрасывает этот залп, вместе с ним теряется и рукопожатие. Отдельные транспортные пакеты от клиента при этом до сервера доходят, сервер обновляет по ним `endpoint` - отсюда обманчивая картина «клиент на связи». **Как отличить от соседних причин.** Все три дают «нет связи», но выглядят по-разному: | Что видно на сервере | Причина | |---|---| | пакетов от клиента нет вообще | не тот порт, фаервол, блокировка по адресу | | пакеты приходят, `latest handshake` пуст, `endpoint` НЕ меняется | не совпадают `S1`-`S4`, `H1`-`H4` или (сервер 3.1) `HeaderProtectionKey`; либо клиент не понимает 3.1 (см. предыдущий пункт) | | **пакеты приходят, `endpoint` меняется, счётчик растёт, `latest handshake` пуст** | **этот случай: залп режется в пути** | **Как убедиться.** На сервере посмотрите пира и запустите захват: ```bash awg show awg0 | grep -A5 '<публичный ключ клиента>' tcpdump -i any -n "udp port <порт вашего VPN> and host <адрес клиента>" ``` Если в захвате видно пакеты от клиента и ответы сервера, а `latest handshake` за минуту попыток так и не обновился - это он. **Причина и что делать.** Установки, сделанные до сентября 2026, несут маскирующий пакет вида `I1 = `, то есть N случайных байт, и часть мобильных сетей такой пакет отбрасывает. С сентября 2026 установщик пишет вместо него пакет формы DNS-ответа, и на замеренном маршруте свежая установка эту проблему уже не воспроизводит; чинить нужно то, что развёрнуто раньше. ⚠️ Это не обещание для всех сетей: у операторов, которым по таблице выше нужен `I1` отсутствующим вовсе, свежая установка проблему сохранит. Проверенные способы, в порядке предпочтения: 1. **Заменить `I1` на пакет осмысленной формы.** Строка вида `` изображает ответ DNS: два случайных байта - идентификатор транзакции, дальше заголовок и запись. Готовую строку под QUIC можно получить генератором из раздела [Блокировка по AS и обход через I1/CPS](#as-blocking-adv); он же годится и здесь, потому что решает не размер пакета, а его форма. Строку такого рода - но формы DNS, а не QUIC - выдаёт и сам установщик начиная с сентября 2026, так что её можно взять из свежей установки. `I1` совпадать у сторон не обязан, а маскирующие пакеты шлёт инициатор рукопожатия - значит одному клиенту достаточно правки в его собственном `.conf`, сервер трогать не нужно. Для всех клиентов сразу то же делает переустановка с флагом `--i1='<строка>'`, затем `regen` и переимпорт профилей на устройствах. 2. **Убрать `I1` вовсе** - переустановка с флагом `--no-cps`. Способ грубее: вместе с проблемой уходит и маскировка рукопожатия. 3. Уменьшать `Jc`, `Jmin`, `Jmax` **бесполезно** - см. замер ниже. **Замер (сентябрь 2026, МТС Москва, сервер в США).** Менялся ровно один параметр за раз, остальные во всех прогонах одинаковы: | `I1` | `Jc` | `Jmin`-`Jmax` | Рукопожатие | |---|---|---|---| | `` | 3 | 40-90 | **есть** | | `` | 6 | 40-90 | **есть** | | `` | 6 | 89-339 | **есть** | | `` | 6 | 89-339 | нет | | `` | 6 | 89-339 | нет | | `` | 6 | 89-339 | нет | | `` | 6 | 89-339 | нет | | **DNS-образный, 128 байт** | 6 | 89-339 | **есть** | Две последние строки - решающая пара: **один и тот же размер 128 байт, разное содержимое.** Случайный не проходит, DNS-образный проходит. Значит дело не в размере пакета и не в числе пакетов-пустышек: `Jc = 6` и пустышки до 339 байт проходят прекрасно. ⚠️ **Границы замера.** Один оператор (МТС, Москва), один маршрут (Россия -> США), одно устройство. Проверена одна альтернативная форма - DNS. Что именно решает, форма DNS или любая неслучайная структура, не различалось. У других операторов и на других маршрутах поведение может быть иным: на казахстанском направлении, по нашим прошлым замерам, проходит и полный залп.
Порт занят другим процессом 1. Определите процесс: `ss -lunp | grep :<порт>` 2. Измените порт AmneziaWG или остановите конфликтующий сервис 3. Для смены порта см. FAQ "Как изменить порт"
Установка обрывается на шаге 6: "Не удалось определить сетевой интерфейс" Шаг 6 определяет основной сетевой интерфейс (для NAT/MASQUERADE) по цепочке: `ip route get 1.1.1.1`, дефолтный IPv4-маршрут, первый глобальный IPv4-интерфейс, дефолтный IPv6-маршрут. Если все способы вернули пусто - провайдер блокирует или null-route'ит `1.1.1.1`, используется policy-routing или egress только по IPv6 (встречалось на Ubuntu 26.04 / Timeweb). Задайте интерфейс вручную и перезапустите установку: 1. Посмотрите имена интерфейсов: `ip -br link` (например `eth0`, `ens3`) 2. Перезапустите установку, передав интерфейс в той же команде: `sudo AWG_MAIN_NIC=ens3 bash install_amneziawg.sh` - значение подхватится на шаге 6. Раздельные `export AWG_MAIN_NIC=...` + `sudo bash ...` не сработают: sudo сбрасывает окружение (если вы уже под root, обычный `export` работает) Значение проверяется (существующий интерфейс без спецсимволов); при опечатке установщик предупредит в логе и вернётся к авто-определению.
--- ## 📊 Статистика трафика (stats) Команда `stats` показывает статистику трафика для каждого клиента. **Обычный вывод:** ```bash sudo bash /root/awg/manage_amneziawg.sh stats ``` ``` [2026-09-26 14:05:02] INFO: Статистика трафика клиентов: Имя | IP | Получено | Отправлено | Последний handshake | Статус ----------------------------------------------------------------------------------------------- my_phone | 10.9.9.2 | 1.24 GiB | 356.69 MiB | 2026-09-26 14:02:11 | Активен my_laptop | 10.9.9.3 | 892.30 MiB | 128.40 MiB | 2026-09-26 14:04:30 | Активен guest | 10.9.9.4 | 0 B | 0 B | никогда | Неактивен [2026-09-26 14:05:02] INFO: Итого: Получено 2.11 GiB, Отправлено 485.09 MiB ``` **JSON-вывод:** ```bash sudo bash /root/awg/manage_amneziawg.sh stats --json ``` ```json [ { "name": "my_phone", "ip": "10.9.9.2", "rx": 1332477952, "tx": 374083174, "last_handshake": 1710312180, "status": "Активен", "status_code": "active" } ] ``` > **Примечание:** поле `status` локализовано (RU `Активен` / `Недавно` / `Неактивен`, EN `Active` / `Recent` / `Inactive`) и предназначено для человека. Для автоматизации используйте машинно-стабильное поле `status_code` - оно не зависит от языка скрипта и принимает значения из фиксированного набора: `active` (handshake < 3 мин), `recent` (< 24 ч), `inactive` (stats: handshake не было или давно), `no_handshake` (list: handshake не было или давно), `key_error` (list: ключ клиента не найден в конфиге сервера), `no_data` (list: недостаточно данных). Поле `status_code` присутствует и в `list --json`, и в `stats --json`. --- ## ⏳ Временные клиенты (--expires) Создание клиентов с автоматическим удалением по истечении срока. **Создание:** ```bash sudo bash /root/awg/manage_amneziawg.sh add guest --expires=7d ``` **Форматы длительности:** | Формат | Описание | |--------|----------| | `1h` | 1 час | | `12h` | 12 часов | | `1d` | 1 день | | `7d` | 7 дней | | `30d` | 30 дней | | `4w` | 4 недели | **Механизм работы:** 1. При создании клиента с `--expires` сохраняется timestamp истечения в `/root/awg/expiry/<имя>`. 2. Cron-задача `/etc/cron.d/awg-expiry` проверяет каждые 5 минут. 3. Истёкшие клиенты автоматически удаляются (конфиг, ключи, запись в серверном конфиге). 4. При удалении последнего expiry-клиента cron-задача автоматически удаляется. **Проверка:** `list -v` показывает оставшееся время для каждого клиента с истечением. **Машиночитаемо:** `list --json` возвращает в каждой записи два поля. `expires_at` - unix-время числом либо `null` у бессрочного клиента; семантика та же, что у успешной записи `add --json` в `results[]`. `expires_at_error` - в норме `null`. Внешнему потребителю (GUI, бот, мониторинг) не нужно читать `/root/awg/expiry/` по SSH. ```bash sudo bash /root/awg/manage_amneziawg.sh list --json ``` ```json [ {"name":"guest","ip":"10.9.9.4","client_ipv6":"","status":"Активен","status_code":"active","expires_at":1788912000,"expires_at_error":null}, {"name":"pc","ip":"10.9.9.3","client_ipv6":"","status":"Недавно","status_code":"recent","expires_at":null,"expires_at_error":null} ] ``` > Значение `expires_at` - каноническая десятичная запись не длиннее 15 знаков. Ведущий ноль, > пустая метка, мусор и слишком длинное число значением не считаются: JSON запрещает числа с > ведущим нулём, а число за пределами int64 отвергнут разборщики на Go и .NET, то есть один > испорченный файл уронил бы разбор всего документа. > Когда метка на сервере ЕСТЬ, а значения из неё получить не удалось, `expires_at` остаётся > `null`, а `expires_at_error` принимает значение `"unreadable"`. Так выглядят пустой файл, > повреждённое содержимое, каталог на месте файла и отказ чтения. ⚠️ Отказ по ПРАВАМ сюда на > практике не попадает: скрипт работает от root, а root проверку прав обходит - замерено на > стенде, `chmod 000` на метке значение не скрыл. Остаются ошибка ввода-вывода, запрет модуля > безопасности и оборванное чтение. Один > только `expires_at: null` читался бы как «клиент бессрочный по замыслу», хотя срок ему > задавали. Причина уходит в журнал: потребителю JSON нужен один ответ - можно ли доверять > значению, - а с конкретным файлом разбирается администратор. Клиента с такой меткой проверка > истечения не удаляет. --- ## 📱 vpn:// URI импорт При создании клиента автоматически генерируется `.vpnuri` файл с `vpn://` URI и, начиная с v5.11.3, QR-код `<имя>.vpnuri.png` с тем же URI - для импорта в Amnezia VPN app (Android / iOS / Desktop). Надёжнее всего способ 2, вставка ссылки: встроенный сканер приложения справляется с этим кодом не всегда. **Расположение файлов:** - `/root/awg/<имя_клиента>.vpnuri` — текстовый `vpn://` URI - `/root/awg/<имя_клиента>.vpnuri.png` — QR-код этого URI (с v5.11.3) **Формат:** конфигурация сжимается через zlib (Perl `Compress::Zlib`) и кодируется в Base64, формируя URI вида `vpn://...`. > Perl с модулями `Compress::Zlib` и `MIME::Base64` должен быть на сервере. На Ubuntu и Debian они установлены по умолчанию. Если Perl отсутствует, `.vpnuri` / `.vpnuri.png` не создаются, но `.conf` работают штатно. `qrencode` (уже обязательный для `.conf` QR) нужен и для `.vpnuri.png`. **Способ 1 - QR-код:** 1. Скопируйте `/root/awg/<имя>.vpnuri.png` на компьютер (`scp`) или откройте локально. 2. В Amnezia VPN на телефоне: «Добавить VPN» → «Считать QR-код». 3. Наведите камеру на `.vpnuri.png`. Если сканер распознал код, импорт произойдёт автоматически; если нет, смотрите абзац ниже. Код плотный: в нашем профиле ссылка около 1100 символов. На Android встроенный сканер Amnezia VPN 5.0.3 его не распознал (проверено 13 октября 2026), а штатная камера тестового телефона (Samsung) прочитала сразу. В таком случае считайте код камерой телефона, скопируйте текст `vpn://...` и вставьте его в Amnezia VPN, как в способе 2. **Способ 2 - копипаст URI:** 1. Скопируйте содержимое `.vpnuri` файла. 2. Откройте Amnezia VPN → «Добавить VPN» → «Вставить из буфера». 3. Конфигурация импортируется автоматически. > Рядом лежит `<имя>.png` - QR из `.conf` для клиентов AmneziaWG, которые умеют импорт по QR-коду; AmneziaWG для Windows и `awg-quick` берут тот же `.conf` файлом, а обычный клиент WireGuard его не примет. Это разные форматы с разными получателями: приложение Amnezia VPN сканирует `.vpnuri.png`, клиенты AmneziaWG с импортом по QR - `<имя>.png`. Не путайте. > Для существующих клиентов, созданных до v5.11.3, `.vpnuri.png` появится после одного `manage regen <имя>`. Новые клиенты получают оба QR-кода сразу. **Права доступа:** `.vpnuri` и `.vpnuri.png` имеют права 600 (только root). --- ## 📱 MTU и мобильные клиенты Начиная с v5.7.4, `MTU = 1280` устанавливается автоматически в серверном и клиентских конфигах. **Зачем:** Сотовые сети (4G/LTE) часто имеют эффективный MTU ниже стандартных 1420 — пакеты фрагментируются или отбрасываются. iOS строго обрабатывает Path MTU Discovery и может не установить соединение. 1280 — минимальный MTU для IPv6 (RFC 8200), проходит через любую сеть. На скорость влияет незначительно. **С профилем 3.1 оставляйте 1280.** Профиль 3.1 добавляет к пакету данных паддинг `ContentPaddingAddition` (у нас до 128 байт), поэтому запас по размеру пакета нужен не меньше прежнего. Поднимать MTU (например, до 1420, как у WireGuard по умолчанию) стоит только после замера PMTU на пути каждого клиента, и MTU сервера не должен быть больше, чем у клиентов: в [#3089](https://github.com/amnezia-vpn/amnezia-client/issues/3089) сервер с 1420 слал пакеты крупнее, чем принимал интерфейс клиента с 1376, и они терялись, а в [#3274](https://github.com/amnezia-vpn/amnezia-client/issues/3274) (сервер 1420, клиент 1200) потери заметно уменьшило значение 1280 с обеих сторон. Это рекомендация, а не доказанный потолок. **Для установок до v5.7.4:** Добавьте `MTU = 1280` в секцию `[Interface]` серверного и клиентских конфигов вручную. Перезапустите сервис: ```bash sudo systemctl restart awg-quick@awg0 ``` > В ссылку vpn:// попадает MTU из клиентского `.conf`, по умолчанию 1280. ### Автоматический MSS-clamp (с v5.17.0) Начиная с v5.17.0 сервер дополнительно ограничивает TCP MSS под размер туннеля. Это правило `TCPMSS` в таблице `mangle` цепочки `FORWARD`, которое добавляется отдельными командами в `PostUp`/`PostDown` конфига `awg0.conf`. Значение берётся из `MTU` (по умолчанию 1280): MSS 1240 для IPv4 и 1220 для IPv6, в обе стороны. **Зачем:** даже при `MTU = 1280` крупные страницы и закачки иногда зависают на мобильных операторах, при двойном NAT и в каскаде из двух серверов. Причина - PMTUD-блэкхол: когда по пути фильтруется ICMP «Fragmentation needed» (для IPv6 - ICMPv6 «Packet Too Big»), крупные TCP-сегменты с флагом DF молча отбрасываются на туннеле, и соединение «висит» на больших объёмах данных (мелкие запросы при этом проходят). MSS-clamp заранее сообщает обеим сторонам туннель-безопасный размер сегмента, поэтому такие пакеты просто не появляются. Это дополняет `MTU = 1280`, а не заменяет его. Правило применяется автоматически при установке и переустановке (`--force`) на v5.17.0 и новее. Перегенерации клиентских конфигов оно не требует - живёт на сервере и действует для всех клиентов. Значение MSS вычисляется из `MTU` в момент генерации конфига; если вы меняете `MTU` вручную уже после установки, перезапустите установщик с `--force` без флагов `--preset`, `--jc`, `--jmin`, `--jmax` (с ними MTU берётся из `awgsetup_cfg.init`, и ручная правка откатится) или поправьте правила в `PostUp` и `PostDown`, как описано в FAQ «Как изменить MTU?». > MSS-clamp работает только для TCP. Видео и QUIC/HTTP3 (UDP) он не затрагивает: если тормозит именно такой трафик, причина в другом - смотрите параметры обфускации и операторские пресеты. ### Сотовый оператор режет порт (нет коннекта) Если на мобильном интернете туннель вообще не поднимается (handshake не проходит), хотя на Wi-Fi всё работает, у этого есть ДВЕ известные причины, и они различаются одним взглядом на сервер. **Причина первая - порт.** По умолчанию сервер слушает UDP 39743; часть операторов такой нестандартный UDP-порт глушит, но стабильно пропускает `443/udp` - он выглядит как QUIC/HTTP3. `--preset=mobile` тут не помогает: он меняет маскировку трафика, а не порт. Признак: на сервере **не видно вообще ничего** - `tcpdump` по вашему порту молчит, пира в `awg show` нет. **Причина вторая - форма маскирующего пакета `I1`.** Признак противоположный: пакеты от клиента на сервер **приходят**, `endpoint` у пира обновляется, счётчик принятых байт растёт, а `latest handshake` не обновляется никогда. Разбор и замер: [рукопожатие не собирается на мобильном интернете](#no-hs-mobile-adv). ⚠️ Не считайте порт причиной по умолчанию. В нашем замере сентября 2026 на МТС (Москва) нестандартный UDP-порт проходил свободно, и дело было целиком в `I1`. Сначала посмотрите на сервер, потом меняйте порт. При установке задайте порт сразу - `sudo bash install_amneziawg.sh --port=443 ...`. На уже работающем сервере смените порт без переустановки: ```bash sudo sed -i 's/^ListenPort = .*/ListenPort = 443/' /etc/amnezia/amneziawg/awg0.conf sudo sed -i 's/^export AWG_PORT=.*/export AWG_PORT=443/' /root/awg/awgsetup_cfg.init sudo ufw allow 443/udp sudo systemctl restart awg-quick@awg0 ``` Затем перевыпустите клиентские конфиги (`sudo bash /root/awg/manage_amneziawg.sh regen <имя>`) - в `Endpoint` подставится новый порт - и заново импортируйте их на устройства. Порт 443 проходит и на обычных сетях, поэтому на него можно перевести все устройства. > Если же туннель поднимается, но часть сайтов (например, YouTube) не открывается, хотя VPN подключён - причина обычно не в порте, а в IPv6 устройства, который идёт мимо туннеля. С v5.31.0 это относится к профилям, выданным раньше, и к своему списку сетей (`--route-custom`): полный туннель, включая дефолтный режим, IPv6 забирает, и такой причины у него не остаётся. Разбор и решение - в разделе про [IPv6 в IPv4-only режиме](#ipv6-tunnel-adv). --- ## 🚧 Хостинг недоступен из России (Hetzner и др.): блокировка по AS и обход через I1/CPS **Симптом.** VPN-сервер на Hetzner ведёт себя так: рукопожатие проходит, в клиенте появляется «Последнее рукопожатие», приходит несколько килобайт, после чего поток обрывается. Пинг внутри туннеля (адрес сервера `10.x.x.x`) уходит в 100% потерь, входящий трафик замирает, новые рукопожатия не завершаются. Со стороны выглядит как «сервер умер», хотя сам сервер жив и доступен по SSH. **Механизм.** Похоже, это не точечная блокировка конкретного IP, а попадание адреса сервера в автономную систему (AS), которой нет в белом списке. По исследованию DPI-аналитика 0ka ([Habr, статья 997088](https://habr.com/ru/articles/997088/)), фильтрация опирается на белый список примерно из 72 AS; в него не входят, например, Hetzner `AS24940`, а также диапазоны OVH, DigitalOcean, AWS и Cloudflare, и трафик к ним деградирует на уровне ТСПУ. Важный нюанс: обычные junk-параметры (`Jc`/`Jmin`/`Jmax`) тут не спасают, потому что меняют сигнатуру пакета, а не его «адресата» по AS. В наших тестах проходил только пакет `I1`/CPS, замаскированный под QUIC-рукопожатие к разрешённому SNI. ⚠️ **Уточнение по замеру сентября 2026: одной блокировкой по AS это не объясняется.** Тот же эффект воспроизвёлся на сервере в США, к Hetzner отношения не имеющем: маскирующий пакет `I1` из случайных байт не проходил, а пакет той же длины, но формы DNS, проходил. Значит фильтр реагирует и на **форму самого пакета**, а не только на адрес назначения, и подмена `I1` помогает не потому, что обходит список AS. Подробный замер - в разделе [рукопожатие не собирается на мобильном интернете](#no-hs-mobile-adv). SNI подбирается под конкретного хостера; для Hetzner рабочим оказался `7-zip.org`. **Полевая проверка (июнь 2026).** Рецепт проверен вживую на чистом сервере Hetzner (AS24940) с российского клиента через три московских оператора. Сравнивались тогдашняя конфигурация по умолчанию (generic `I1 = `) и QUIC-мимикрия (`I1`, сгенерированный под SNI `7-zip.org`). | Оператор | Дефолт (generic I1) | QUIC-I1 (SNI 7-zip.org) | |----------|---------------------|--------------------------| | Ростелеком | блок (рукопожатие, затем тишина) | **доступ восстановлен**: 0% потерь, реальный веб через туннель | | ecotelecom | блок | **доступ восстановлен**: 0% потерь | | Seven Sky | блок | **не помогло** (проверены два SNI: `7-zip.org` и `www.google.com`) | Контрольная проверка: туннель к серверу в другой AS (США) поднимался и держался на всех трёх операторах, значит в нашем тесте на Seven Sky оставался недоступен именно Hetzner, а не VPN вообще. На Seven Sky блок повторялся стабильно и вечером, и ночью, а QUIC-мимикрия с двумя разными SNI его не снимала. Вывод: метод 0ka действительно работает, но не универсально - результат зависит от оператора и региональной настройки ТСПУ. **Как применить вручную.** Инсталлятор не генерирует QUIC-мимикрию `I1` сам - это ручная настройка: 1. Сгенерируйте строку `I1` под нужного хостера в [Mini QUIC Generator](https://sageptr.github.io/mini_quic_generator/) (автор SagePtr): впишите SNI (`7-zip.org` для Hetzner) и скопируйте значение из поля «AmneziaWG 1.5+ (I1 = )». 2. Замените строку `I1 = ...` в секции `[Interface]` серверного конфига `/etc/amnezia/amneziawg/awg0.conf` (`I1`-`I5` регистрозависимы, только верхний регистр). 3. Перезапустите сервис и пересоберите клиентов - `regen` подставит новый `I1` в клиентские конфиги из `awg0.conf`, затем раздайте обновлённые `.conf`: ```bash sudo systemctl restart awg-quick@awg0 sudo bash /root/awg/manage_amneziawg.sh regen <имя> ``` 4. Если доступ не вернулся, попробуйте другой SNI или другого хостера: у части операторов (как Seven Sky в нашем тесте) мимикрия не прошла ни с одним из проверенных SNI. > Обсуждение метода и подбор SNI: тема [ntc.party #12845](https://ntc.party/t/12845). Если у вас Hetzner и сервер «замолкает» после рукопожатия, сначала проверьте, не в этом ли причина: поднимите для теста сервер у другого хостера (например, в США), и если туда туннель работает, дело в блокировке по AS назначения. --- ## 🛡️ Активное зондирование (active probing) и обфускация без прокси **Что это.** Глубокая инспекция трафика (DPI) не всегда работает пассивно. В режиме активного зондирования (active probing) она шлёт на UDP-порт сервера специально сформированные или повторно проигранные пакеты и трактует поведение порта как один из признаков: настоящий сервис ответит ожидаемым образом, а отсутствие ответа от прикрывающего сервиса может повысить подозрительность (хотя само по себе и не решает). К этому DPI добавляет пассивный анализ сигнатуры самих пакетов рукопожатия. **Что протокол делает сам (без отдельного демона).** AmneziaWG скрывает форму рукопожатия на уровне протокола и убирает WireGuard-признаки в ответах на валидный AWG-трафик, не поднимая дополнительных сервисов: - **Шифрование заголовков (профиль 3.1, по умолчанию).** Тип сообщения шифруется ключом `HeaderProtectionKey`, своим на каждую установку, поэтому в заголовке больше нет постоянной приметы WireGuard ни при каких `H1`-`H4`. Подробнее - в разделе [Профиль 3.1](#awg3-not-yet-adv). - **`I1`-`I5` (CPS concealment).** Concealment-пакеты делают рукопожатие похожим на разрешённый трафик - например на QUIC-подобный к разрешённому SNI, в зависимости от настройки, - так что и наблюдаемая сигнатура, и любой ответ на валидную AWG-инициацию выглядят не как обычный WireGuard. При этом протокол НЕ отвечает на произвольные QUIC/TLS/DNS-пробы как настоящий сервис. Это тот же механизм, что в рецепте обхода блокировки по AS; конкретный подбор SNI - в разделе [Блокировка по AS и обход через I1/CPS](#as-blocking-adv). - **Порт из «белого списка».** Запуск VPN на порту 443 или 53 (`--port=443`) кладёт трафик на порты, где сетевые сервисы ожидаемы: это может снизить простую блокировку по порту, но само по себе активное зондирование не побеждает. **Честная граница: где отдельный прокси идёт дальше.** В самых агрессивных сценариях active-probing отдельный отвечающий прокси (например `amneziawg-proxy` у проекта wiresock) объективно надёжнее: он реально отвечает на пробу как настоящий сервис - поднимает QUIC/TLS на 443, отвечает DNS на 53, обслуживает STUN и SIP. Это другой инженерный компромисс: постоянный процесс-демон, отдельный порт, сборка на Rust, а для полной двунаправленной маскировки - их собственный клиент. Здесь обфускация встроена в сам протокол и нацелена на типовой пассивный и мобильный DPI - без отдельного демона, дополнительного порта и платного клиента; более сильная защита от активного зондирования - это роль прокси. Что выбрать, зависит от того, насколько агрессивно зондирование в вашей сети. > Сравнение с официальным приложением Amnezia и с другими инструментами - на [странице сравнения](https://bivlked.github.io/amneziawg-installer/ru/compare/). --- ## 📋 Совместимость клиентов Клиент должен понимать поколение вашего сервера: новая установка по умолчанию даёт профиль 3.1, а с `--protocol=2.0`, на ядре старее 6.7 (штатный Debian 12) и на ARM - профиль 2.0. Какое поколение у сервера, установщик пишет в итоговом отчёте строкой «Поколение протокола», а позже его показывает `manage check`. Таблица ниже - короткий список с нашими пометками; полная таблица с версиями и источниками - в разделе [Какое поколение AmneziaWG понимает клиент](#client-gen-adv). | Клиент | Платформа | AWG 3.1 | AWG 2.0 | Примечание | |--------|-----------|---------|---------|------------| | [Amnezia VPN](https://github.com/amnezia-vpn/amnezia-client/releases) | Windows, macOS, Linux, Android, iOS | ✅ (>= 5.0.1.5) | ✅ (>= 4.8.12.7) | Поддерживает vpn:// URI. На Android после выключения Wi-Fi туннель не восстановился, в том числе по кнопке подключения; помог перезапуск приложения (5.0.3, проверка 13 окт 2026). В российском App Store нет | | [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-android) | Android | ✅ (Google Play >= 3.1.4, APK >= v3.1.20260814) | ✅ (>= 2.0.0) | Рекомендуемый для Android. Легковесный tunnel manager. Импорт через `.conf` и QR | | [AmneziaWG](https://apps.apple.com/app/amneziawg/id6478942365) | iOS, macOS | ✅ (>= 3.1.4) | ✅ | Легковесный клиент, есть в российском App Store | | [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-windows-client/releases) | Windows | ✅ (>= 3.1.0) | ✅ (>= 2.0.0) | Легковесный tunnel manager. Импорт через `.conf` | | [WG Tunnel](https://github.com/wgtunnel/android) | Android | ✅ (>= 5.6.0, лучше >= 5.7.5) | ✅ | Рекомендуемый для Android. FOSS-клиент с auto-tunneling и split tunneling; Google Play, IzzyOnDroid | | [WG Tunnel Desktop](https://github.com/wgtunnel/desktop) | Windows, Linux, macOS | ✅ (линия v2) | ✅ | Тот же движок, что у Android-версии | | `awg-quick` ([amneziawg-tools](https://github.com/amnezia-vpn/amneziawg-tools) + модуль или amneziawg-go) | Linux | ✅ (модуль и утилиты третьей линии) | ✅ | Для серверов и машин без графики, см. [Подключение Linux-машины как клиента](#linux-client-adv) | | [WireSock VPN Client](https://www.ntkernel.com) | Windows | не заявлено | ❌ (нет `S3`/`S4`) | Коммерческий, собственный движок. По документации вендора (wiresock.net, октябрь 2026) `I1`-`I5` молча отбрасываются, а `S3`/`S4` не поддерживаются; оба наших профиля задают `S3`/`S4`, поэтому подключения не ждите | | Hiddify | все | ❌ | - | Движок ниже третьей линии: для Hiddify ставьте сервер с `--protocol=2.0` | | Стандартный WireGuard | Все | ❌ | ❌ | Не поддерживает AWG-параметры | > Если при импорте клиент выдаёт ошибку про неизвестный параметр (`HeaderProtectionKey`, `ContentPaddingAddition`, S3, S4, I1 или H1 в формате диапазона), он не понимает поколение сервера: обновите его или возьмите клиент из первых строк таблицы. Клиент, не знающий 3.1, может и не показать ошибку - тогда рукопожатия просто нет. ### Какое поколение AmneziaWG понимает клиент Снято 15 октября 2026 со страниц релизов, магазинов и кода проектов, проверить можно там же. Клиенты двигаются раз в несколько дней, поэтому у строк стоят даты. «С какой версии» - по заметкам к выпускам, страницам и коду самих проектов, «Основание» - откуда известно поколение. Строки, проверенные позже, несут свою дату в столбце «Основание». | Клиент | 3.1 | Версия на 15 окт 2026 | С какой версии 3.1 | Где брать | Основание | |---|---|---|---|---|---| | Amnezia VPN (флагман, все платформы) | да | 5.0.3.0 (GitHub), 5.0.3.1 (Google Play) | 5.0.1.5 (21 авг 2026) | GitHub, магазины; в российском App Store нет; Windows - по прямой ссылке со страницы релизов | страницы проекта | | AmneziaWG для Android (лёгкий) | да | 3.1.4, Google Play (21 сен 2026) | 3.1.4 в Google Play, v3.1.20260814 в APK | Google Play, страница релизов | страницы проекта | | AmneziaWG для iOS и macOS (лёгкий) | да | 3.1.4 (24 авг 2026) | 3.1.4 | App Store, в том числе российский | страницы проекта | | DefaultVPN (iOS, от авторов Amnezia) | да | 2.0.2 (21 сен 2026) | 2.0.1 (24 авг 2026) | App Store, в том числе российский | страницы проекта, 21 окт 2026 | | AmneziaWG для Windows (лёгкий) | да | 3.1.0 (21 авг 2026) | 3.1.0 | страница релизов проекта | страницы проекта | | AmneziaWG для Windows 7 и 8 (сборка RomikB, сторонняя) | да | v3.1.1 (28 авг 2026) | v3.1.1 | страница релизов проекта, файлы с windows7 в имени | код проекта | | WG Tunnel (Android, сторонний) | да | 5.8.2 (19 окт 2026) | 5.6.0 | Google Play, IzzyOnDroid, APK | код проекта, 21 окт 2026 | | WG Tunnel Desktop (сторонний) | да | v2.4.1 (17 окт 2026) | 2.0.0 (13 сен 2026) | страница релизов проекта, choco, apt, AUR | код проекта, 21 окт 2026 | | mihomo (ядро для Clash Verge Rev и других) | да | v1.19.32 (30 сен 2026) | v1.19.30; 3.1 включается только строкой `version: 3` в `amnezia-wg-option` | страница релизов проекта | код проекта | | FlClash (Android, Windows, macOS, Linux, сторонний) | да | v0.9.1 (17 окт 2026) | v0.8.97 (10 сен 2026); ядро mihomo: нужна строка `version: 3` в `amnezia-wg-option` | страница релизов проекта | код проекта, 21 окт 2026 | | Throne (Windows, Linux, macOS, сторонний) | да | 1.3.2 (29 сен 2026) | 1.3.0 (17 сен 2026); в 1.3.x паддинг части пакетов урезается до свободного места в буфере; исправлено в пре-релизах 1.4.0-beta.1 - beta.3 | страница релизов проекта | код проекта, 21 окт 2026 | | L×Box (Android, сторонний) | да | v2.25.16 (19 окт 2026) | v2.23.0 (5 сен 2026) | страница релизов проекта | код проекта, 21 окт 2026 | | ZedSecure (Android, сторонний) | да | v3.1.6 (13 окт 2026) | - | страница релизов проекта | код проекта | | network-manager-amneziawg (Linux, сторонний) | да | v0.9.12 (13 окт 2026) | v0.9.12; своего движка нет: нужен модуль ядра третьей линии, а во внешнем режиме ещё и утилиты awg третьей линии | страница релизов проекта | страницы проекта | | gluetun (Docker, сторонний) | в ежедневном фиде, без тега | образ latest из master; в теге v3.41.3 AmneziaWG нет | master (26 сен 2026); движок 3.0: строк RandomTrailers и DisableCookies не читает, а профиль этого установщика их и не пишет | Docker Hub, тег latest | код проекта | | Hiddify | нет | 4.1.1 (5 мар 2026) | - | - | код проекта | | KeeneticOS (штатная прошивка) | только в канале разработки | 5.2 Beta 1 (19 окт 2026) | 5.2 Alpha 11 (25 сен 2026); в стабильной 5.1 нет | канал разработки Keenetic | страницы проекта, 21 окт 2026 | | AWG Manager (Keenetic, сторонний) | да | v2.19.19 (20 окт 2026) | штатным модулем на KeeneticOS 5.2 Alpha 11 и новее; на других прошивках - своим модулем ядра или встроенным sing-box (нужны Entware и компонент WireGuard) | страница релизов проекта | код проекта, 21 окт 2026 | | OpenWrt (официальные пакеты) | нет | пакета нет; PR openwrt/packages #30492 и #30493 открыты, одобрения мейнтейнеров нет | - | - | страницы проекта | | awg-openwrt (OpenWrt, сторонний) | да | v25.12.6, v24.10.8 | v25.12.5, v24.10.8 (22 сен 2026); пакеты этих релизов заменены под прежними тегами; скачанные раньше и пакеты для более старых OpenWrt - без 3.1 | страница релизов проекта, фид проекта | код проекта, 21 окт 2026 | | GL.iNet (штатная прошивка) | нет | AmneziaWG 2.0 с прошивки 4.9; сроков 3.x нет | - | - | страницы проекта | | amneziawg-mikrotik-c (MikroTik, сторонний) | да | v1.4.3 (8 окт 2026) | - | страница релизов проекта | страницы проекта | | AmneziaWG-MikroTik (сторонний) | да | Containers_3.1 (30 авг 2026) | Containers_3.1 | страница релизов проекта | страницы проекта | - **sing-box-extended** понимает 3.1 с v1.14.0-extended-2.7.0 (4 сентября 2026), но падает при `ContentPaddingAddition` больше 16 в конфиге самого устройства и трафике из TUN ([issue #158](https://github.com/shtorm-7/sing-box-extended/issues/158), на 15 октября 2026 открыт), а в нашем клиентском профиле 3.1 стоит `32-128`. Важен паддинг клиента, а не сервера: параметр односторонний, в профиле такого устройства строку можно уменьшить до 16 или убрать, сервер менять не нужно. На OpenWrt эта сборка работает с AmneziaWG в tachyon (преемник forkop) при выборе варианта extended; podkop берёт AmneziaWG из интерфейса системы и не затронут, а forkop туннели AmneziaWG сам не собирает. NyameBox перешёл на эту сборку только в ветке master, в выпусках её нет. Throne не падает: в 1.3.x паддинг урезается (см. таблицу), а в пре-релизах 1.4.0 под него резервируется место в буфере. - **amneziawg-mikrotik-c** (v1.4.3) принимает `ContentPaddingAddition`, но к исходящим пакетам его не применяет и пишет об этом в журнал. На связь это не влияет, добавочного паддинга просто нет. - **amneziawg-mikrotik-c** до v1.4.2 при `Jc = 0` не отправлял `I1`-`I5`, то есть профиль с `--jc=0` терял на нём маскирующий пакет. - **Karing** не рекомендуем: поддержки AmneziaWG в его заметках к выпускам нет. - **Windows 11 26H2:** по единичному отчёту ([amnezia-client#3277](https://github.com/amnezia-vpn/amnezia-client/issues/3277)) встроенный в Amnezia VPN 5.0.3.0 AmneziaWG там не передаёт пакеты (ошибка `WSAEFAULT`), а лёгкий AmneziaWG для Windows 3.1.0 работает. > ⚠️ Поколение у сторонних проектов указано по их коду и заметкам авторов, а у официальных - по > заметкам к выпускам и магазинам. Поведением на сгенерированном профиле 3.1 эта таблица не > проверялась. Отдельно 13 октября 2026 к серверу с профилем 3.1 от этого установщика подключались > AmneziaWG для Android 3.1.4, WG Tunnel 5.8.1 и Amnezia VPN 5.0.3 на Android и AmneziaWG 3.1.0 > на Windows; результаты - в вопросах о задержке первого запроса > и о выборе клиента в FAQ. ### Клиенты для роутеров | Проект | Платформа | Описание | |--------|-----------|----------| | [AWG Manager](https://github.com/hoaxisr/awg-manager) | Keenetic (Entware) | Веб-интерфейс для управления AWG-туннелями на роутерах Keenetic; третья линия - штатным модулем на KeeneticOS 5.2 Alpha 11 и новее, на других прошивках - своим модулем ядра или встроенным sing-box | | [awg-openwrt](https://github.com/Slava-Shchipunov/awg-openwrt) | OpenWrt | Пакеты kmod/tools/luci; третья линия - в пакетах для OpenWrt 25.12.5 и 24.10.8 (заменены 22 сентября 2026). В официальных пакетах OpenWrt AmneziaWG нет, а патч из репозитория `amnezia-vpn/amneziawg-openwrt` по нашему разбору даёт только уровень AWG 1.0 (без `S3`/`S4` и `I1`-`I5`), и с нашими профилями он не заработает | | [AmneziaWG for Merlin](https://github.com/r0otx/asuswrt-merlin-amneziawg) | ASUS (Asuswrt-Merlin) | Аддон AWG 2.0 с веб-интерфейсом, GeoIP/GeoSite маршрутизация; третья линия нами не проверялась | | [amneziawg-mikrotik-c](https://github.com/timbrs/amneziawg-mikrotik-c) | MikroTik (RouterOS Container) | Docker-контейнер, преобразует WireGuard-трафик MikroTik в AmneziaWG | > **Keenetic со штатной прошивкой.** Стабильная прошивка Keenetic (5.1 на октябрь 2026) понимает только вторую линию, поэтому для неё сервер ставится с `--protocol=2.0` (см. [Мой роутер умеет AmneziaWG третьей линии?](#faq-router-adv)). Встроенный клиент AmneziaWG есть и в более старых прошивках (4.x, 5.0), но диапазоны `H1`-`H4` понимают не все из них: например, 5.0.6 на Speedster их не разбирает, см. абзац ниже. Если туннель поднимается, но трафик не идёт - проблема в формате I1. Рабочие варианты: `I1 = ` или DNS-имитирующий паттерн `I1 = `. `I1` совпадать с сервером не обязан, поэтому достаточно поменять его в `.conf` роутера; если меняете в серверном конфиге, то дальше `sudo systemctl restart awg-quick@awg0` + `manage regen <клиент>`. [Discussion #45](https://github.com/bivlked/amneziawg-installer/discussions/45). > > 🔴 **Префикс `` в этом паттерне обязателен, копировать блок без него нельзя.** Два случайных байта - это идентификатор транзакции DNS, с которого начинается любой пакет протокола. Без них всё содержимое сдвигается на два байта, и как DNS пакет не разбирается вовсе: поле идентификатора получает `0x8580`, флаги становятся `0x0001`, то есть пакет объявляет себя запросом вместо ответа, счётчик дополнительных записей вырастает до 1641, а первая метка имени заявляет 99 байт при 29 оставшихся. И вторая причина: без случайного префикса все 42 байта постоянны, и пакет получается байт-в-байт одинаковым у всех, кто скопировал рецепт отсюда. ⚠️ Префикс делает разными только сами пакеты, а постоянный 42-байтовый блок внутри остаётся и по-прежнему годится как признак для поиска. > **Keenetic Speedster (прошивка 5.0.6), AmneziaWG не подключается:** старые прошивки ещё не парсят H1-H4 как диапазоны (`нижняя-верхняя`) и выдают ошибку `invalid H1`. Задайте H1-H4 конкретными числами - остальные слои обфускации (Jc/Jmin/Jmax, I1, S1-S4) при этом продолжают работать. Если handshake проходит, но трафика нет - снизьте junk (`Jc=3`, `Jmin=10`, `Jmax=50`), при необходимости уберите строку `I1` и обнулите `S3`/`S4`. Обойти часть прошивочных ограничений помогает сторонний [AWG Manager](https://github.com/hoaxisr/awg-manager) (веб-интерфейс для туннелей AmneziaWG на Keenetic, на модуле ядра); третью линию он даёт и на прошивках без её поддержки, своим модулем ядра или встроенным sing-box. [Discussion #81](https://github.com/bivlked/amneziawg-installer/discussions/81). --- ## 🐧 Поддержка Debian **Коротко.** Debian 13 (trixie) на x86_64 получает AmneziaWG 3.1, как Ubuntu (оговорка про ядра 7.0.0-38 - в [Известных ограничениях](#kernel-70-backport-adv)). На штатном Debian 12 (bookworm, ядро 6.1) установщик сам ставит 2.0: профиль 3.1 он выдаёт только на ядре 6.7 и новее. Чтобы получить 3.1, берите Debian 13 или Ubuntu 24.04/26.04 либо загрузите Debian 12 с ядром 6.7+ из backports (подробности ниже). Инсталлятор полностью поддерживает Debian 12 (bookworm) и Debian 13 (trixie). Это про поддержку СО СТОРОНЫ УСТАНОВЩИКА: у самого Debian 12 обычная поддержка закончилась 2026-07-11, дальше только Debian LTS до 2028-06-30, поэтому для нового сервера лучше Debian 13. **Различия Ubuntu vs Debian:** | Аспект | Ubuntu 24.04 | Debian 12 (bookworm) | Debian 13 (trixie) | |--------|-------------|---------------------|-------------------| | PPA codename | native | маппинг на `focal` | маппинг на `noble` | | APT формат | DEB822 `.sources` | `.list` | DEB822 `.sources` | | Headers | `linux-headers-$(uname -r)` | fallback на `linux-headers-amd64` | fallback на `linux-headers-amd64` | | snapd/lxd cleanup | Да | Пропускается | Пропускается | **Предварительная подготовка Debian:** На минимальных установках Debian отсутствует `curl`: ```bash apt-get update && apt-get install -y curl ``` **Ожидаемые предупреждения:** При установке на Debian вы можете увидеть предупреждение `sudo removal refused` — это нормально, так как Debian использует `sudo` как системный пакет и скрипт корректно пропускает его удаление. ### AmneziaWG 3.0 и ядра старше 6.7 (Debian 12) - v5.23.0 В конце июля 2026 команда Amnezia выпустила **AmneziaWG 3.0** и переключила на него PPA `ppa:amnezia/ppa`. Поначалу модуль 3.0 не собирался на ядрах старше 6.7: он вызывал функцию `nla_put_uint`, которой в Linux до версии 6.7 нет, и на **Debian 12 (bookworm) с ядром 6.1** установка обрывалась на `implicit declaration of function 'nla_put_uint'`. 31 июля разработчики это исправили ([issue #204](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/204)): в версии модуля `v3.0.20260731-04` сборка на ядре 6.1 проходит, проверено на Debian 12 с ядром 6.1.0-51. Инсталлятор при этом продолжает держать на таких ядрах **закреплённый последний модуль AmneziaWG 2.0** (тег `v1.0.20260725`, сверяется по commit-хэшу): начиная с **v5.23.0**, если версия ядра старше 6.7, модуль не берётся из PPA, а собирается из исходников через DKMS. Теперь это сознательный выбор, а не обход поломки: линия 3.0 в первые же дни успела сломать и починить сборку именно на старых ядрах, то есть там она обкатана меньше всего. Утилиты `amneziawg-tools` по-прежнему ставятся из PPA - версия 3.0 корректно работает с модулем 2.0, это проверено. Ставить что-либо вручную не нужно, всё происходит на шаге 2. На ядрах 6.7 и новее (Ubuntu 24.04/26.04, Debian 13 trixie) поведение прежнее - модуль ставится из PPA. Если хотите получить на Debian 12 именно третью линию AmneziaWG, проще всего развернуть сервер заново на Debian 13 / Ubuntu 24.04+. Второй путь - поставить ядро 6.7+ из `bookworm-backports` и **перезагрузиться в него**: инсталлятор смотрит на работающее ядро, а не на установленное, и после перезагрузки пойдёт обычным путём. На уже настроенном сервере не ставьте поверх: сделайте резервную копию (`sudo bash /root/awg/manage_amneziawg.sh backup`), снимите установку (`sudo bash install_amneziawg.sh --uninstall`) и поставьте заново - иначе закреплённый модуль 2.0 останется зарегистрированным в DKMS под тем же именем, что и пакет из PPA. С версии 6.0.0 новая установка на ядре 6.7 и новее получает профиль 3.1 сама, а на штатном ядре 6.1 установщик автоматически ставит 2.0, см. [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv). --- ## 🔧 Raspberry Pi и ARM64 Инсталлятор работает на ARM-системах, но протокол там - AmneziaWG 2.0: в v6.0.0 профиль 3.1 на ARM не выдаётся ни с каким модулем. Это осознанная осторожность до отдельного замера на ARM (см. [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv)). Клиентам такого сервера нужна поддержка 2.0. Явный `--protocol=3.1` на ARM прерывает установку. **Поддерживаемые платформы:** | Платформа | Архитектура | Пакет заголовков ядра | |-----------|-------------|----------------------| | Raspberry Pi 3, 4 (64-bit) | ARM64 (aarch64) | `linux-headers-rpi-v8` | | Raspberry Pi 5 | ARM64 (aarch64) | `linux-headers-rpi-2712` | | Raspberry Pi 3, 4 (32-bit) | ARMv7 (armhf) | `linux-headers-rpi-v7` или `linux-headers-rpi-v7l`, по суффиксу ядра в `uname -r` | | Ubuntu ARM64 (AWS Graviton, Oracle Ampere, Hetzner) | ARM64 | `linux-headers-generic` | | Debian ARM64 (облачные VPS) | ARM64 | `linux-headers-arm64` | **Как это работает:** 1. Инсталлятор определяет версию ядра и архитектуру автоматически. 2. Если в [arm-packages release](https://github.com/bivlked/amneziawg-installer/releases/tag/arm-packages) есть готовый пакет `amneziawg.ko` для вашего ядра, он скачивается и устанавливается через `dpkg`. Это занимает 2-3 минуты. 3. Если готовый пакет не подходит, инсталлятор переключается на DKMS-сборку из исходников. Работает с любым ядром, но занимает больше времени (10-30 мин в зависимости от оборудования). 4. Готовый пакет можно не брать вовсе: с флагом `--no-prebuilt` модуль сразу собирается через DKMS. Готовые пакеты собирает CI проекта, а установщик сверяет их только с файлом SHA256 из того же релиза; подписи у них нет. Учтите, что меняется и сам модуль: готовые пакеты собраны из закреплённого исходника AmneziaWG 2.0, а на ядрах 6.7 и новее DKMS ставит `amneziawg-dkms` из PPA, то есть тот же модуль третьей линии, что и на сервере x86. Клиентские профили в обоих случаях второго поколения. > **Покрытие готовыми ARM-пакетами:** prebuilt собираются для Raspberry Pi (3/4/5), Ubuntu 24.04 ARM64 и Debian 12/13 ARM64. Ubuntu 26.04 ARM64 пока без prebuilt - модуль ставится пакетом `amneziawg-dkms` из PPA и собирается через DKMS (дольше при первой установке, дальше работает штатно). **Определение ядра Raspberry Pi:** Ядра Raspberry Pi Foundation имеют суффикс `+rpt` в строке версии (например, `6.12.75+rpt-rpi-v8`). Инсталлятор маппит этот суффикс на правильный пакет заголовков. Стандартные ядра Debian/Ubuntu ARM64 используют свои обычные заголовки. **Решение проблем:**
В: Модуль не загружается на Raspberry Pi Проверьте, что заголовки ядра совпадают с работающим ядром: uname -r vs ls /lib/modules/. Если они различаются, обновите ядро: sudo apt update && sudo apt upgrade, перезагрузитесь и запустите инсталлятор повторно.
В: DKMS-сборка занимает очень много времени на Pi 3 Raspberry Pi 3 имеет 1 ГБ RAM и 4 ядра на 1.2 ГГц. Компиляция модуля ядра может занять 20-30 минут — это нормально. Убедитесь, что swap включен (инсталлятор настраивает его автоматически).
В: Как узнать, был ли использован готовый модуль? Ищите в логе установки (/root/awg/install_amneziawg.log) строку Предсобранный пакет установлен (английский установщик пишет Prebuilt installed). Если её нет, модуль собран через DKMS: при откате на сборку журнал пишет откат на DKMS.
--- ## 🐧 Подключение Linux-машины как клиента Мобильные и десктопные клиенты берут конфиг через приложение, QR или vpn:// URI. Чтобы подключить как клиента обычный Linux (домашний сервер, вторую машину, роутер на Linux), нужны модуль ядра или userspace-реализация AmneziaWG, понимающие поколение сервера: для сервера 3.1 (по умолчанию) - третьей линии (сборка третьей линии работает и с сервером 2.0). Штатный `wireguard` не подойдёт, он не знает про Jc/S/H/I и ключ защиты заголовков. Два пути. ### 1. Ядерный модуль + инструменты (Ubuntu / Debian) На СЕРВЕРЕ выпустите клиентский конфиг и заберите его: ```bash sudo bash /root/awg/manage_amneziawg.sh add my-linux-box # готовый конфиг: /root/awg/my-linux-box.conf ``` На КЛИЕНТЕ поставьте модуль и инструменты AmneziaWG. Это те же пакеты, что ставит установщик, но клиенту не нужны UFW / Fail2Ban / оптимизации сервера: ```bash # Ubuntu sudo add-apt-repository -y ppa:amnezia/ppa sudo apt update sudo apt install -y amneziawg-dkms amneziawg-tools linux-headers-$(uname -r) ``` Для Debian отдельных пакетов PPA нет. Установщик обходит это, ремапя suite на ближайшую Ubuntu (bookworm -> focal, trixie -> noble), но как ручной шаг на клиенте это ненадёжно - для Debian-клиента проще userspace `amneziawg-go` (путь 2) или сборка модуля из исходников. Положите конфиг под именем `awg0` и поднимите туннель: ```bash sudo mkdir -p /etc/amnezia/amneziawg sudo cp my-linux-box.conf /etc/amnezia/amneziawg/awg0.conf sudo chmod 600 /etc/amnezia/amneziawg/awg0.conf sudo awg-quick up awg0 sudo systemctl enable awg-quick@awg0 # автозапуск при загрузке ``` Проверка: `sudo awg show` покажет `latest handshake`, но одного его мало - проверьте и трафик (почему, см. [ниже](#linux-client-loop-adv)). При полном туннеле `curl ifconfig.me` вернёт IP сервера; при split-туннеле проверяйте по трафику к адресу, попадающему в `AllowedIPs`. Остановить туннель - `sudo awg-quick down awg0`. ### 2. amneziawg-go (userspace, без модуля ядра) Если модуль поставить нельзя (нет заголовков ядра, запрет DKMS, экзотическая архитектура), userspace [`amneziawg-go`](https://github.com/amnezia-vpn/amneziawg-go) работает поверх `/dev/net/tun` в любом Linux ценой ~30-50% CPU overhead. Клиенту нужны `amneziawg-go` плюс `amneziawg-tools`. `awg-quick up awg0` подхватит userspace-реализацию, если бинарь `amneziawg-go` лежит в `PATH` (или задайте `WG_QUICK_USERSPACE_IMPLEMENTATION=/путь/к/amneziawg-go`); нужен доступ к `/dev/net/tun` и `CAP_NET_ADMIN`. Сборка и запуск разобраны в разделе [LXC / Docker через amneziawg-go](#lxc-userspace-adv). ### Раздельный список маршрутов и адрес сервера Linux `awg-quick` сам разводит маршруты только для полного туннеля `0.0.0.0/0`: ставит метку и правило, по которым пакеты к серверу идут мимо туннеля. Со списком маршрутов (режим 2 `--route-amnezia`, режим 3, список через `modify`) такого правила нет. Если адрес сервера попадает в список, шифрованные пакеты к серверу заворачиваются в сам туннель. Приложения для Windows, Android и iOS ставят маршрут до сервера сами, поэтому у них этого отказа нет. Признак: `awg show` показывает свежий `latest handshake` (первый пакет уходит до маршрутов), но данные не идут. Принятое застывает около 92 байт, отправленное за секунды растёт до гигабайт, `ping` пишет `No buffer space available`. В этом отказе свежий `latest handshake` ничего не говорит о живом туннеле. С версии 6.0.0 установщик и `manage` сами делают в списке дыру у адреса сервера: маршрут, который его содержит, заменяется своим дополнением до этого адреса. Клиентам, выданным раньше, достаточно перевыпуска (`regen`). Цена одна: трафик к самому адресу сервера, например к сайту на том же сервере, идёт мимо туннеля. Дыра делается только для IPv4-адреса. Если в `Endpoint` стоит имя (его адрес может смениться) или IPv6, поставьте маршрут до сервера сами, до `awg-quick up`: ```bash sudo ip route add <адрес-сервера>/32 via <ваш-шлюз> # IPv4 sudo ip -6 route add <адрес-сервера>/128 via <ваш-шлюз-IPv6> # IPv6 ``` `modify <имя> AllowedIPs` записывает список как задан и предупреждает, если в нём адрес сервера. ### Осторожно на удалённой машине (риск потерять SSH) Если Linux-клиент - это удалённый сервер, которым вы управляете по SSH, полный туннель (`AllowedIPs = 0.0.0.0/0`) заворачивает в туннель весь трафик, включая ваш обратный SSH: машина начнёт отвечать через VPN, и текущая сессия почти наверняка отвалится. - Клиенту, которому в VPN нужна лишь часть трафика, дайте split-конфиг: `manage_amneziawg.sh modify my-linux-box AllowedIPs "нужные-подсети"`. SSH останется на прямом маршруте. - Если полный туннель всё же нужен, перед `awg-quick up` пропишите исключение для своего админского IP через исходный шлюз (policy-route), иначе доступ к машине пропадёт. - Проверяйте полный туннель на машине с локальной консолью или KVM/IPMI, а не вслепую по SSH. --- ## 📦 LXC / Docker через amneziawg-go (userspace) Если **кернел-модуль AmneziaWG нельзя установить на хост** — запрет провайдера, shared-kernel LXC без root-доступа к хосту, общий Proxmox с другими контейнерами, который не хочется перезагружать ради DKMS-сборки, — есть альтернатива: userspace-реализация [`amneziawg-go`](https://github.com/amnezia-vpn/amneziawg-go). Это TUN-backed вариант, модуль ядра не нужен. Производительность ниже kernel-native (~30–50% CPU overhead на 1 Gbps), зато работает в любом Linux с `/dev/net/tun`. Мой инсталлятор `install_amneziawg.sh` **этот путь не покрывает** — я специально ставлю kernel-native ради производительности и чтобы не тащить Go-компилятор на prod. Раздел описывает ручную настройку поверх готового Debian / Ubuntu в LXC. ### ⚠️ Security tradeoff Для работы `amneziawg-go` внутри LXC обычно требуется: - **Privileged контейнер** (root мапится на хост) или `unprivileged` с пробросом `/dev/net/tun` и `CAP_NET_ADMIN` — в обоих случаях контейнер получает широкий доступ к сетевому стеку хоста. - **Nesting** (`features: nesting=1` в Proxmox) — нужен для `iptables` внутри контейнера. На Proxmox 9 с Debian 13 LXC (systemd 257+) Proxmox сам предупреждает при создании: `WARN: Systemd 257 detected. You may need to enable nesting.` — без nesting контейнер тупит ещё и на уровне systemd. - **tun passthrough** через `lxc.cgroup2.devices.allow` и bind-mount `/dev/net`. Если изоляция контейнера критична (multi-tenant хост, privacy-sensitive workload) — берите KVM/QEMU-виртуалку с обычным инсталлятором вместо LXC. ### Требования к LXC host **Proxmox LXC config** (`/etc/pve/lxc/.conf`): ```conf features: nesting=1 lxc.cgroup2.devices.allow: c 10:200 rwm lxc.mount.entry: /dev/net dev/net none bind,create=dir ``` После правки config перезапустите контейнер: `pct stop && pct start `. **Forwarding внутри контейнера:** ```bash echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-awg-forwarding.conf sudo sysctl --system ``` ### Установка amneziawg-go и amneziawg-tools **Сборка из исходников.** Готовых бинарей у проекта нет: релизы на GitHub не публикуются, есть только теги (проверено 14 октября 2026). Для третьей линии берите тег `v3.1.*`, на эту дату последний - `v3.1.20260828`. Ему нужен Go 1.25 или новее, а системный `golang-go` в Debian 12/13 и Ubuntu 24.04 старее (ниже 1.25), поэтому Go ставьте с [go.dev/dl](https://go.dev/dl/): ```bash sudo apt install -y git make iptables curl # Go 1.25+ с https://go.dev/dl/ (системный golang-go для этого тега стар), например: curl -fsSL https://go.dev/dl/go1.25.0.linux-amd64.tar.gz | sudo tar -C /usr/local -xz && export PATH=/usr/local/go/bin:$PATH # для ARM - linux-arm64; актуальную версию сверьте на go.dev/dl git clone --branch v3.1.20260828 https://github.com/amnezia-vpn/amneziawg-go cd amneziawg-go && make && sudo make install cd .. ``` Номера тегов у двух репозиториев разные, это нормально: у каждого своя нумерация. **amneziawg-tools** дают `awg` и `awg-quick` CLI. Системный `awg-quick` из `wireguard-tools` не понимает обфускационные параметры (`Jc/Jmin/Jmax/S1-S4/H1-H4/I1-I5`), поэтому именно этот форк нужен, и тоже третьей линии: ```bash git clone --branch v3.1.20260812 https://github.com/amnezia-vpn/amneziawg-tools cd amneziawg-tools/src && make && sudo make install cd ../.. ``` ### Конфиг и запуск Создайте `/etc/amnezia/amneziawg/awg0.conf` - замените `YOUR_*` на свои значения. Ключи генерируются через `awg genkey | tee /etc/amnezia/amneziawg/server_private.key | awg pubkey`, ключ защиты заголовков - отдельным `awg genkey`. Пример ниже - профиль 3.1. Из параметров обфускации совпадать с клиентом обязаны `S1`-`S4`, `H1`-`H4` и `HeaderProtectionKey`; `Jc`/`Jmin`/`Jmax` и `I1` совпадать не обязаны: ```conf [Interface] Address = 10.9.9.1/24 ListenPort = 39743 PrivateKey = YOUR_SERVER_PRIVATE_KEY Jc = 4 Jmin = 50 Jmax = 150 S1 = 64 S2 = 37 S3 = 21 S4 = 15 H1 = 1 H2 = 2 H3 = 3 H4 = 4 HeaderProtectionKey = YOUR_HEADER_PROTECTION_KEY ContentPaddingAddition = 32-128 PostUp = iptables -I INPUT -p udp --dport 39743 -j ACCEPT PostUp = iptables -I FORWARD -i eth0 -o awg0 -j ACCEPT PostUp = iptables -I FORWARD -i awg0 -j ACCEPT PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D INPUT -p udp --dport 39743 -j ACCEPT PostDown = iptables -D FORWARD -i eth0 -o awg0 -j ACCEPT PostDown = iptables -D FORWARD -i awg0 -j ACCEPT PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] PublicKey = YOUR_CLIENT_PUBLIC_KEY PresharedKey = YOUR_PRESHARED_KEY AllowedIPs = 10.9.9.2/32 ``` `S1`-`S4` в профиле 3.1 не меньше 12: первые 12 байт паддинга служат nonce для шифрования заголовка. Для профиля 2.0 уберите строки `HeaderProtectionKey` и `ContentPaddingAddition` и задайте `H1`-`H4` непересекающимися диапазонами ниже 2147483647 (например `H1 = 134567-245678`); `S3` от 8 и `S4` от 4 там допустимы. Клиент должен получить те же `S1`-`S4`, `H1`-`H4` и ключ. Имя интерфейса (`awg0`) и внешний NIC (`eth0`) подставьте свои. Для IPv6 добавьте симметричные правила `ip6tables`. Порт `ListenPort` должен быть открыт на уровне хоста (UFW или iptables хоста) и на уровне облачного провайдера. Smoke-тест: ```bash sudo awg-quick up awg0 sudo awg # должен показать интерфейс и пиров sudo awg-quick down awg0 ``` Запуск как systemd-сервис: ```bash sudo systemctl enable awg-quick@awg0 sudo systemctl start awg-quick@awg0 sudo systemctl status awg-quick@awg0 ``` ### Работает ли `manage_amneziawg.sh` поверх? Мой `manage_amneziawg.sh` рассчитан на kernel-native setup (ждёт `/root/awg/awgsetup_cfg.init`, полагается на `awg-quick` + `awg` из `amneziawg-tools`). Теоретически он должен работать поверх ручной установки `amneziawg-go` + `amneziawg-tools`, если интерфейс назван `awg0` и директория `/etc/amnezia/amneziawg/` существует. Этот сценарий я **не тестирую и не поддерживаю** — если нужен полноценный менеджмент клиентов, ведите конфиги руками или возьмите отдельный инструмент под userspace. ### Источник Рабочий минимальный рецепт для Debian 13 в привилегированном LXC на Proxmox прислал [@Akh-commits](https://github.com/Akh-commits) в [issue #51](https://github.com/bivlked/amneziawg-installer/issues/51#issuecomment-4288953829) - этот раздел построен на нём с расширением по security-warning и профилю 3.1. Сам рецепт со сборкой третьей линии мы на стенде в LXC не прогоняли. --- ## 🗄️ AmneziaWG на Synology NAS (DSM) Мой установщик на DSM не работает, но сам AmneziaWG на Synology поднять можно - вручную, через userspace-реализацию. Всё, что ниже, проверял на DS918+ с DSM 7.4.1. ### Почему установщик не подходит | что смотрел | что на DSM 7.4.1 | |---|---| | версия ядра | 4.4.302+ | | минимум для модуля AmneziaWG | 5.15, ниже установщик предупреждает и просит подтверждение | | сборочное дерево `/usr/lib/modules/$(uname -r)/build` | нет | | компилятор `gcc` / `make` | нет | | DKMS | нет | Упирается всё в версию ядра. С процессором как раз порядок: DS918+ это обычный x86_64. А вот ядро 4.4 старше того, против чего собирается модуль, лет на десять. Собрать модуль на самой коробке нечем - ни заголовков, ни компилятора. Кросс-сборка тулчейном Synology в принципе возможна, но повторять её пришлось бы под каждое обновление DSM. ### Встроенный VPN-клиент DSM Умеет три протокола: L2TP, OpenVPN и PPTP. WireGuard среди них нет, модуля в ядре нет, утилиты `wg` в системе тоже нет. Так что штатными средствами DSM этот протокол не поднимается вообще, и скрипт тут ни при чём. ### Что работает: userspace [`amneziawg-go`](https://github.com/amnezia-vpn/amneziawg-go) - официальная реализация в пользовательском пространстве. Модуль ядра ей не нужен, нужен `/dev/net/tun`. На DSM он есть, и модуль `tun` уже загружен. Проверял живьём: с DS918+ поднялся туннель до сервера, установленного этим скриптом. Рукопожатие прошло, данные пошли в обе стороны, пинг внутри туннеля отвечает. Обфускация при этом была включена полностью - `Jc`/`Jmin`/`Jmax`, `S1`-`S4`, `H1`-`H4` и маскирующий пакет `I1`. Работает нормальный профиль AmneziaWG 2.0, а не выхолощенный WireGuard. С профилем 3.1 на DSM мы не проверяли. ### Чем за это платят - **Скоростью.** Шифрование считает процессор, никакой разгрузки нет. На Celeron уровня J3455 рассчитывайте на десятки мегабит. Точных чисел не назову, я их не мерил. - **Своим временем.** Всё делается руками из консоли: нужен SSH на NAS и root. `/dev/net/tun` принадлежит `root:root`, через веб-интерфейс до него не добраться. Бинарь придётся собрать на другой машине и перенести - ни Go, ни компилятора на DSM нет. - **Автозапуском.** systemd в DSM отсутствует, автостарт живёт в Планировщике задач от имени root. Пропустите этот шаг - и туннель исчезнет при первой перезагрузке NAS, а вспомнить, почему, будет уже трудно. ### Грабли - **`/tmp` смонтирован `noexec`.** Положенный туда бинарь не запустится, а `Permission denied` на настоящую причину даже не намекнёт. Кладите на том. - **Нет `nc`, `socat` и `perl`.** Зато есть `python3` и `curl` - управляющий сокет удобнее всего дёргать питоном. - **Адрес клиента обычно приходит с маской `/32`.** Маршрут до подсети сервера при ней сам не появится, и пакеты уйдут мимо туннеля. Придётся добавить его вручную: обычно это делает `awg-quick` по `AllowedIPs`, но на DSM его нет. - **Обновление DSM может снести то, что лежит в системных каталогах.** Где держать бинарь, чтобы этого не случилось, я не выяснял. ### Если нужен сервер на самом NAS На моделях с Virtual Machine Manager можно поднять обычную Ubuntu в виртуальной машине - внутри неё установщик отработает штатно, как на любом VPS. На DS918+ для этого есть всё: пакет VMM стоит, аппаратная виртуализация у процессора есть, том в btrfs. Оговорок две. Виртуалка съест заметную часть памяти NAS. И снаружи это всё равно сервер за домашним роутером: нужен проброс UDP-порта, а адрес за виртуалкой стоит закрепить, иначе после перезагрузки проброс будет смотреть в пустоту. Всю связку «DSM плюс VMM плюс Ubuntu плюс установщик» я не гонял - проверял только последнее звено, работу установщика в обычной Ubuntu. ### Чего я не проверял Заворачивание всего трафика NAS в туннель - проверял сам туннель, а маршрут по умолчанию не трогал. Ещё: как это переживает перезагрузку и обновление DSM, работает ли через Container Manager и какая получается скорость. DSM в поддерживаемые платформы не входит: установщик туда не ставится, и как площадку я её не тестирую. --- ## ⚠️ Известные ограничения * **Ядро 7.0.0-38 на Ubuntu 26.04 и HWE-ядро 7.0.0-38 на Ubuntu 24.04: модуль из PPA не собирается (с 1 октября 2026); с v5.37.1 установщик исправляет это сам.** В этих ядрах изменилась функция `setup_udp_tunnel_sock`, а модуль AmneziaWG из PPA (тег `v3.1.20260906`) об этом ещё не знает. Исправление предложено в репозитории модуля ([#218](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/pull/218), [#250](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/pull/250)), но пока не принято. Кого касается: Ubuntu 26.04 после обновления ядра до 7.0.0-38 и Ubuntu 24.04 с HWE-ядром 7.0.0-38 (`linux-generic-hwe-24.04`). В нашей проверке сборкой этой ошибки не было на Ubuntu 24.04 с обычным ядром 6.8.0-146, Ubuntu 26.04 на прежнем ядре 7.0.0-34, Debian 12 (6.1.0-53) и Debian 13 (6.12.107 и 6.12.111). Как это выглядит: `apt upgrade` заканчивается ошибкой DKMS, в логе сборки `passing argument 2 of 'setup_udp_tunnel_sock' from incompatible pointer type`. Пакеты нового ядра остаются недонастроенными, и следующие установки и обновления через `apt` снова упираются в ту же ошибку. Туннель на текущем ядре продолжает работать. На нашем стенде (24.04 с HWE) загрузчик не обновился, и после перезагрузки сервер остался на старом ядре, но рассчитывать на это нельзя: пока модуль не собран, в новое ядро не перезагружайтесь. С установщиком до v5.37.1 на Ubuntu 24.04 проще всего не попадать в эту ситуацию: оставайтесь на обычном ядре и не ставьте `linux-generic-hwe-24.04`. Какой метапакет стоит, видно в `dpkg -l 'linux-generic*' | grep ^ii`. Запрет метапакета через `apt-mark hold` уже установленное ядро не исправит. **Начиная с v5.37.1 это делает установщик**. Помощник `amneziawg-ensure-module`, который `apt` запускает после каждого обновления ядра, накладывает на исходник модуля правку из #218 - только если исходник совпадает с проверенным байт в байт - и собирает модуль для каждого ядра с заголовками. Свежая установка и следующие обновления ядра проходят без ручных шагов. На уже установленном сервере помощник старый, и обновить его нужно один раз: скачать установщик новой версии вместе с подписью, проверить подпись и запустить восстановление. Нужен `minisign` (`sudo apt install minisign`); блок проверяет подпись тем же ключом и тем же способом, что блок из раздела [«Как обновить скрипты»](#update-scripts-adv), и не запускает установщик, если подпись не сошлась или релиз выпущен раньше v5.37.1: ```bash cd "$(mktemp -d)" KEY=RWQXfpABHIpZPttqrwYrQNHRTk/iLIz4cVh9KkRwAElHP+CoW/NPEysN f=install_amneziawg.sh # английская версия: f=install_amneziawg_en.sh tag= wget -q -O "$f" "https://github.com/bivlked/amneziawg-installer/releases/latest/download/$f" \ && wget -q -O "$f.minisig" "https://github.com/bivlked/amneziawg-installer/releases/latest/download/$f.minisig" \ && out=$(minisign -V -P "$KEY" -m "$f" -x "$f.minisig") \ && tag=$(printf '%s\n' "$out" | sed -n "s/^Trusted comment: amneziawg-installer \(v[0-9.]*\) $f\$/\1/p") if [ -z "$tag" ]; then echo "НЕ ПРОВЕРЕН: $f, не запускаю" elif [ "$(printf '%s\n' v5.37.1 "$tag" | sort -V | head -1)" != v5.37.1 ]; then echo "Релиз $tag раньше v5.37.1: в нём этой команды нет, используйте ручной путь ниже" else echo "Проверен релиз $tag"; sudo bash "$f" --repair-module fi ``` `--repair-module` обычную установку не запускает. Он разворачивает новый помощник, правит исходник (только проверенный), собирает модуль для ядер с заголовками и донастраивает пакеты (`dpkg --configure -a`), только если ни одно недонастроенное ядро не останется без модуля. В конце он называет ядра, у которых модуля нет, и печатает время проверки. Сервер он не перезагружает, и загрузку модуля в новом ядре не проверяет. Пока он работает, не запускайте `apt`. Скрипты управления он не обновляет: чтобы `manage repair-module` тоже работал через новый помощник, а `manage diagnose` показывал модуль по каждому ядру, обновите их блоком из раздела [«Как обновить скрипты»](#update-scripts-adv). Перед перезагрузкой в новое ядро проверьте то же, что в шагах 5 и 6 ручного пути ниже. Если правка помощника мешает (для поддержки): `sudo amneziawg-ensure-module --revert` возвращает исходник к виду из пакета и больше его не трогает, `sudo amneziawg-ensure-module --enable` разрешает правку снова. Что проверено: сборка с правкой на всех ядрах из списка выше и на обоих проблемных; другие компиляторы, Secure Boot и ARM мы не проверяли. **Ручной путь** (v5.37.0 и более ранние, или если `--repair-module` отказал): помогает та же правка из #218, она проверяет саму сигнатуру функции. Команды ниже выполняются от root: откройте root-shell командой `sudo -i`. Блок из шага 2 можно вставить целиком: он остановится на первой ошибке. Если какая-то команда завершилась ошибкой или проверка хеша написала `FAILED`, дальше не идите. 1. Дождитесь, пока текущая команда `apt` закончится. Работающее ядро и туннель не трогайте. 2. Наложите правку на исходник модуля, сверяя хеш до и после: ```bash ( set -e cd /usr/src/amneziawg-1.0.0 echo 'b14346040ce0188c47e2db2baad1a4f21aa784510f6c95bbb4aa58d5bbe691c9 compat/compat.h' | sha256sum -c - curl -fsSL -o /root/pr218.diff https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/commit/62189503fa51bc049d826e226fdb49ee683f53f2.diff cp -p compat/compat.h /root/compat.h.orig patch -p2 --forward < /root/pr218.diff echo '8d47a358b4df0b2187788ce6f88ad63128218de1be22c78b263ef3e5d770c26b compat/compat.h' | sha256sum -c - ) ``` Если `FAILED` написала уже первая проверка, сверьте второй хеш: `cd /usr/src/amneziawg-1.0.0 && echo '8d47a358b4df0b2187788ce6f88ad63128218de1be22c78b263ef3e5d770c26b compat/compat.h' | sha256sum -c -`. Если он совпал, правка уже наложена, переходите к шагу 3. Если нет, у вас другой исходник, и эта правка не для него. 3. Соберите модуль под новое ядро. Его полное имя есть в сообщении об ошибке DKMS и в `ls /lib/modules`, например `7.0.0-38-generic`. Не подставляйте `uname -r`, это текущее ядро: ```bash dkms install -m amneziawg -v 1.0.0 -k 7.0.0-38-generic ``` 4. Донастройте пакеты: `dpkg --configure -a`. Если остались ошибки зависимостей, выполните `apt-get -f install` и снова `dpkg --configure -a`. Если `apt` предложит что-то удалить, сначала прочитайте список: работающее ядро удалять нельзя. 5. Перед перезагрузкой проверьте: `dpkg --configure -a` закончился без ошибок (именно он обновляет initramfs и загрузчик), `dpkg --audit` ничего не выводит, `dkms status amneziawg` показывает `installed` для нового ядра. Для контроля: файл `/boot/initrd.img-7.0.0-38-generic` есть, а в `/boot/grub/grub.cfg` есть пункт с этим ядром (`grep -c 7.0.0-38-generic /boot/grub/grub.cfg` больше нуля). Если включён Secure Boot (`mokutil --sb-state`), модуль должен быть подписан ключом, которому доверяет система; под Secure Boot мы это не проверяли, и отключать его ради этого не надо. Если что-то не так, не перезагружайтесь и старое ядро не удаляйте. 6. Перезагружайтесь в новое ядро, когда под рукой есть консоль хостера. `installed` в DKMS ещё не значит, что модуль загрузится: после перезагрузки проверьте `lsmod | grep amneziawg` и `systemctl status awg-quick@awg0`. На ARM эту правку мы не проверяли. Правка живёт в `/usr/src/amneziawg-1.0.0` до следующего обновления пакета `amneziawg-dkms`. Если новая версия из PPA уже содержит исправление, повторять ничего не нужно; если нет, сборка под следующее ядро снова упадёт, и шаги придётся повторить. Если у вас та же ошибка, но хеш в шаге 2 не совпал, напишите в [Issues](https://github.com/bivlked/amneziawg-installer/issues) с выводом `dkms status` и `uname -r`. * **LXC-контейнеры не поддерживаются моим инсталлятором.** AmneziaWG использует ядерный модуль (DKMS). LXC разделяет ядро с хостом — загрузить свой модуль из контейнера нельзя. Варианты: полноценная VM (KVM/QEMU) или bare-metal сервер для kernel-native установки, либо userspace-реализация `amneziawg-go` внутри LXC (см. [LXC / Docker через amneziawg-go](#lxc-userspace-adv)). * **Предполагается выделенный сервер.** Скрипт настраивает UFW, Fail2Ban, sysctl и оптимизирует систему под VPN. На сервере с другими сервисами используйте `--no-tweaks`, чтобы пропустить hardening, либо `--keep-packages`, если мешает только удаление системных пакетов, а фаервол и оптимизация нужны. * **Не ставьте на хост с сервером из приложения Amnezia.** Официальное приложение разворачивает AmneziaWG в Docker-контейнере на userspace `amneziawg-go`. Как только на хосте появляется наш модуль ядра, `awg-quick` внутри контейнера переключается на него и перестаёт откатываться в userspace, и контейнер AmneziaWG перестаёт принимать подключения ([issue #209](https://github.com/bivlked/amneziawg-installer/issues/209)). Выберите что-то одно: отдельный сервер под установщик или сначала уберите контейнер через приложение. Если уже поставили поверх, `--uninstall` и перезагрузка должны вернуть контейнер на userspace. Фаервол UFW здесь ни при чём: опубликованные порты Docker идут через FORWARD, а не через INPUT. * **Одно поколение протокола на сервер.** Все клиенты получают профиль одного поколения: или все 3.1, или все 2.0. Если хоть одно устройство не понимает 3.1, сервер ставится с `--protocol=2.0`; смена поколения - `--uninstall`, новая установка и новые профили для всех клиентов, см. [Где вместо 3.1 ставится 2.0](#awg3-fallback-adv). Клиенты AWG 1.x не поддерживаются ни одним из профилей. * **Ubuntu вне `noble`, `jammy` и `focal`:** установщик запрашивает у PPA файл `dists/<кодовое имя>/Release`, и если ответа нет (404 или PPA недоступен), переключает codename PPA на `noble`. Ubuntu 26.04 обычно получает свой набор `resolute` (PPA публикует его с 14 сентября 2026), а если проверка не прошла, тоже переключается на `noble`. Debian отображается на ближайший выпуск Ubuntu всегда: 12 -> `focal`, 13 -> `noble`. Модуль при этом ставится DKMS-пакетом из PPA и собирается под ваше ядро, кроме ARM-систем с готовым модулем. * **IPv6 Dual-Stack Tunnel - откат `ALLOW_IPV6_TUNNEL=0`:** Установка `ALLOW_IPV6_TUNNEL=0` в `awgsetup_cfg.init` (или повторный запуск без `--allow-ipv6-tunnel`) **не удаляет** dual-stack `AllowedIPs = ..., fddd::.../128` из уже существующих записей `[Peer]` в `awg0.conf`. Записи остаются, ядро продолжает держать IPv6-маршруты для этих клиентов. `manage_amneziawg.sh regen <имя>` (или полный путь `/root/awg/manage_amneziawg.sh regen <имя>`) после отключения флага пересобирает только клиентский `.conf` - он станет IPv4-only, так как `regenerate_client` читает `ALLOW_IPV6_TUNNEL`. Но `regen` **не** убирает IPv6 `AllowedIPs` из блока `[Peer]` на сервере. Чтобы очистить и серверную сторону, используйте sed-очистку всех пиров: `awg-quick down awg0; sed -i 's|, fddd:[^/]*/[0-9]*||g' /etc/amnezia/amneziawg/awg0.conf; awg-quick up awg0`, либо `manage_amneziawg.sh remove <имя>` + `add <имя>`. --- ## 🤝 Внесение вклада (Contributing) Предложения и исправления приветствуются! Создавайте Issue или Pull Request в [репозитории](https://github.com/bivlked/amneziawg-installer). --- ## 💖 Благодарности * Команде [Amnezia VPN](https://github.com/amnezia-vpn). ---

↑ К началу