Конфиг AmneziaWG выглядит как конфиг WireGuard, в который дописали два
десятка строк вида Jc, S4, H2, I1.
Что делает каждая, толком не написано нигде: официальная документация описывает версию
1.5, статьи пересказывают друг друга, а генераторы выдают числа без объяснений. Ниже —
разбор всех полей, какие из них обязаны совпасть с сервером до числа, а какие можно
менять только у себя (это мы проверили замером, и первое наше прочтение оказалось
неверным), и почему чужой конфиг иногда встречает ответом
Line unrecognized. Полный список полей снят 31 августа 2026 года с живой
ноды — из бинаря awg версии amneziawg-tools v3.1.20260812,
а не переписан из чужих статей.
Короткий ответ
AmneziaWG — это форк WireGuard. Всё, что вы знаете про конфиг WireGuard, работает
без изменений: [Interface] с ключом и адресом, [Peer] с
Endpoint и AllowedIPs. Разница ровно одна: добавлены поля,
которые задают форму пакетов — сколько байт добивки, какими числами
помечены типы пакетов, что уходит в сеть первым.
Главное, что стоит понять до всех таблиц: эти поля не «настраиваются правильно» — они совпадают. Часть из них — общий алфавит клиента и сервера: разошлись на единицу, и рукопожатия не будет вовсе. Другая часть касается только клиента, и сервер про неё вообще ничего не знает. Граница между этими двумя половинами и есть самое полезное, что здесь написано, и её мы измерили сами.
Если вы пользуетесь готовым сервисом (нашим или чужим), настраивать эти поля вам не нужно: конфиг приходит целиком, вместе с уже согласованными значениями. Эта статья — для тех, кто поднимает свой сервер, переносит конфиг между устройствами или разбирается, почему туннель не поднимается.
Все поля конфига 3.1
Ниже — поля, которых нет в обычном WireGuard. Все они живут в секции
[Interface], кроме последнего. Стандартные строки
(PrivateKey, Address, DNS, MTU,
PublicKey, Endpoint, AllowedIPs,
PersistentKeepalive) остались прежними и здесь не повторяются.
| Поле | Что задаёт | Формат |
|---|---|---|
Jc |
Сколько отдельных датаграмм со случайным содержимым уходит перед рукопожатием. | целое, 0 — не слать |
Jmin / Jmax |
Границы длины такой датаграммы: длина каждой выбирается случайно из этого промежутка. | байты, Jmin < Jmax |
S1 |
Сколько байт добивки ставится перед телом пакета Initiation — первого пакета рукопожатия. | целое до 65535 |
S2 |
То же для пакета Response — ответа второй стороны. | целое до 65535 |
S3 |
То же для пакета Cookie. Появился в версии 2.0. | целое до 65535 |
S4 |
То же для каждого пакета с данными. Появился в 2.0 — и именно он тихо съедает ваш MTU, см. отдельный раздел. | целое до 65535 |
H1–H4 |
Какими числами помечены четыре типа пакетов (Initiation, Response, Cookie, данные) вместо стандартных 1, 2, 3, 4. | число или min-max; диапазоны не должны пересекаться |
I1–I5 |
Содержимое до пяти самостоятельных датаграмм, которые уходят в сеть самыми первыми, ещё до мусорных пакетов. | строка тегов, см. ниже |
HeaderProtectionKey |
Ключ, которым шифруется заголовок пакета. Появился в 3.x; в утилитах 1.5 и 2.0 этой строки не было. | hex-ключ |
ContentPaddingAddition |
Добавочная добивка содержимого. Поле есть в 3.x; что именно оно меняет, мы не измеряли и выдумывать не будем. | диапазон |
RandomTrailersDisableCookies |
Переключатели, появившиеся в 3.x. По названиям — случайный «хвост» у пакетов и отключение механизма cookie. Замером не проверяли. | on / off |
RekeyAfterTimeRekeyTimeoutRejectAfterTimeKeepaliveTimeoutMaxHandshakeAttempts |
Внутренние таймеры WireGuard, вынесенные в настройки в 3.x: когда пересогласовывать ключи, сколько ждать ответа, когда считать сессию мёртвой. Раньше это были константы в коде. | диапазон |
AdvancedSecurity |
Единственное поле из списка, которое стоит в секции [Peer], а не [Interface]. Наследие версии 1.5. |
on / off |
🔴 Честная граница этой таблицы. Про Jc, S1–S4,
H1–H4 и I1–I5 написано по разбору исходников
движка и по нашим замерам — это мы знаем. Про пять таймеров,
ContentPaddingAddition, RandomTrailers и DisableCookies
известно меньше: имена и форматы сняты с бинаря, смысл прочитан по названиям, замером не
подтверждён. В наших конфигах этих полей нет. Мы решили лучше назвать их с оговоркой, чем
сделать вид, что список полный и всё в нём проверено.
I1–I5: грамматика тегов
Значение I1…I5 — не число, а строка из тегов вида
<тег аргумент>, идущих подряд. Движок собирает из них содержимое
датаграммы слева направо. Поддерживаются такие теги:
| Тег | Что кладёт в пакет | Сколько байт |
|---|---|---|
<b 0xHEX> | Фиксированные байты, записанные шестнадцатеричным числом. | половина длины hex |
<r N> | N случайных байт. | N |
<rc N> | N случайных печатных символов. | N |
<rd N> | N случайных цифр. | N |
<t> | Текущее время Unix, 4 байта, старший байт первым. | 4 |
<d>, <ds>, <dz N> | Сами данные, они же в base64, их длина числом. В I1–I5 бессмысленны: данных там нет, эти пакеты собираются пустыми. | — |
Пример строки: <b 0xa1b2c3><r 32><t> — три
фиксированных байта, тридцать два случайных и метка времени, всего 39 байт.
Три грабли, которые видно прямо в коде разбора:
- незакрытая угловая скобка даёт ошибку
missing enclosing >, неизвестный тег —unknown tag; - пустая строка и отсутствующее поле — это одно и то же: цепочки нет, поведение откатывается к версии 1.x;
I2–I5существуют, но используются редко: почти все конфиги, что мы видели, задают толькоI1. У нас тоже.
Что обязано совпадать с сервером
Это главный вопрос при настройке, и ответ на него не очевиден. Принимающая сторона опознаёт пакет по паре признаков сразу: размер совпал с «добивка + размер сообщения» И число в заголовке попало в нужный диапазон. Отсюда деление полей на две половины — и оно не догадка, мы проверили его прямым замером на стенде 28 июля 2026 года.
| Что разошлось у клиента и сервера | Результат |
|---|---|
I1 (разные строки тегов) и Jc/Jmin/Jmax (5/40/70 против 3/64/256) |
✅ рукопожатие прошло, трафик по туннелю пошёл |
S1: 16 против 15, всё остальное совпадает |
❌ рукопожатия нет |
H1: другой диапазон, всё остальное совпадает |
❌ рукопожатия нет |
Итог в одну строку:
S1–S4иH1–H4обязаны совпадать. Это общий алфавит. Разница в единицу — и стороны друг друга не слышат.Jc,Jmin,Jmax,I1–I5— дело клиента. Сервер эти датаграммы отбрасывает, не заглядывая внутрь: они для него просто мусор, пришедший на порт.
Практическая польза от второй строки больше, чем кажется. Раз сервер про клиентские
I ничего не знает, их можно менять на одном устройстве, ничего не трогая на
сервере и не разрывая чужие живые туннели. А вот менять S или H
на работающем сервере — операция с простоем: все подключённые клиенты отвалятся, пока
не заберут новый конфиг.
🔴 И здесь наша ошибка, ради которой стоило написать этот раздел.
Первая редакция нашего же внутреннего разбора утверждала ровно обратное: «значения
I у клиента и сервера обязаны совпадать точно». Звучало логично — раз
фиксированные байты сверяются побайтово в одном месте движка, значит и здесь тоже. Мы
поставили стенд и проверили: клиент с одной строкой тегов подключился к серверу с другой,
рукопожатие прошло, трафик пошёл. Правдоподобное объяснение и проверенный факт снова
оказались разными вещами — и цена разницы была бы высокой: при неверном прочтении
любая смена I1 требовала бы одновременной правки на всех серверах.
Пять ошибок, из-за которых нет рукопожатия
Симптом у всех пяти одинаковый и обманчивый: интерфейс поднялся, awg show
показывает пира, а строки latest handshake нет и не появляется.
- Диапазоны
H1–H4пересекаются. Тип пакета определяется попаданием числа в диапазон; если два диапазона перекрываются, часть пакетов читается как чужой тип. Диапазоны обязаны быть непересекающимися — это следует прямо из способа опознания. Jminне меньшеJmax. Промежуток, из которого выбирается длина, пустой.- Перенесли половину полей. Скопировали
JcиI1, аSиHоставили от прежнего конфига. Именно та половина, которая обязана совпадать, и не совпала. - Разные версии на сторонах. Об этом ниже: у 1.5 и 3.x разный набор полей, и лишнее поле — не предупреждение, а отказ разбирать файл.
- Не уменьшили MTU на
S4. Это единственная ошибка из пяти, при которой рукопожатие проходит — а потом тяжёлые страницы висят. Следующий раздел как раз про неё.
S4 съедает MTU
S4 — добивка каждого пакета с данными, и это значит, что каждый ваш
пакет становится на S4 байт длиннее уже после того, как MTU посчитан. Наши
живые замеры: при MTU 1420 и S4 = 15 на проводе оказывается
1495 байт, а на линиях с S4 = 23 и 27 —
1503 и 1507. Наружу при этом проходит ровно 1500 —
то есть два последних случая не пролезают.
Правило простое: из привычного MTU вычтите S4. Было 1420,
S4 = 15 — ставьте 1405. И проверьте вторую сторону: MTU
задаётся отдельно у клиента и у интерфейса на сервере, а исправление только у клиента лечит
ровно половину беды. Подробный разбор с расчётом по байтам и способом измерить свой
предел — в статье «Какой MTU поставить для
WireGuard».
Отдельная история, стоившая нам двух дней. Если после включения S4
туннель начинает пересобираться сам по себе — смотрите не в конфиг, а в версию
ядерного модуля на сервере. В сборке модуля, которая стояла у нас в начале августа,
сервер путал собственный служебный пакет с данными и начинал лишние рукопожатия. Мы
сначала обошли это укороченным PersistentKeepalive, потом починили
обновлением модуля. Конфиг был ни при чём — и это ровно тот случай, когда чинить
надо не там, где симптом.
Версии 1.5, 2.0 и 3.x
Самая частая причина «конфиг не читается» — он от другой версии. Набор полей менялся дважды, причём не только в сторону добавления:
- 1.5 — были
J1,J2,J3иItime; не былоS3,S4. - 2.0 —
J1–J3иItimeубраны как избыточные, добавленыS3,S4и сигнатурные пакетыI1–I5. - 3.x — добавлены защита заголовка, добавочная добивка содержимого, переключатели и пять таймеров из первой таблицы.
Проверено 31 августа 2026 года на нашей ноде: в бинаре
amneziawg-tools v3.1.20260812 строк J1, J2,
J3 и Itime нет вовсе. Конфиг из старого генератора не «частично
применится» — утилита ответит Line unrecognized и не станет разбирать
файл дальше. В обратную сторону так же: конфиг с S4 не примет сервер на 1.5.
Свою версию узнаёте одной командой — awg --version. Если версии
сторон разошлись, вопрос решается обновлением, а не подбором полей.
Как поставить конфиг на Android
Официальное приложение AmneziaWG для Android принимает конфиг тремя способами:
файлом .conf, архивом .zip с несколькими конфигами и
QR-кодом. QR удобнее всего, когда конфиг лежит на компьютере: код собирается одной
командой — qrencode -t ansiutf8 < tunnel.conf — и считывается
с экрана.
Что важно знать про телефон отдельно:
- MTU переносится не всегда. Если импортировали конфиг, а тяжёлые страницы висят — первым делом проверьте поле MTU в настройках туннеля, оно могло остаться пустым.
- Мусорные пакеты стоят батарейки и трафика. Большой
Jcс широким промежуткомJmin–Jmaxзаметен на мобильной сети сильнее, чем на Wi-Fi: каждое переподключение — это лишние датаграммы. Поскольку сервер их всё равно не проверяет, на телефоне их разумно держать скромными. - Одно устройство — один ключ. Один и тот же конфиг на двух телефонах сразу работать не будет: стороны переспорят друг друга за одну сессию.
Как убедиться, что всё встало
На сервере всё видно одной командой — awg show. Она печатает не только
привычные ключи и latest handshake, но и действующие значения
jc, jmin, jmax, s1–s4,
h1–h4. Это и есть способ проверить, что применилось именно то,
что вы написали в файле, а не то, что осталось от прошлого раза.
Дальше читается так:
- Рукопожатия нет вовсе, а сеть до сервера живая — первое
подозрение на расхождение
SилиH, а не на порт и не на firewall. - Рукопожатие есть, счётчик принятых байт не растёт — смотрите
маршруты и
AllowedIPs. - Рукопожатие есть, мелкое открывается, тяжёлое висит — это MTU,
почти наверняка вместе с
S4.
Со стороны человека проверять соединение стоит не по значку в приложении, а по факту: какой адрес и страну видит сайт и не утекают ли запросы имён мимо туннеля. Как это сделать за минуту — «Как проверить, работает ли VPN и нет ли утечки DNS».
Короткий вывод: S и H — общий язык двух сторон, их
переносят целиком и никогда не подправляют «чуть-чуть». Jc и I
— ваше дело, сервер о них не спрашивает. А S4 не забудьте вычесть из
MTU: это единственное поле, ошибка в котором не мешает подключиться, зато ломает
соединение позже и незаметно.