[GH-ISSUE #3064] Десктопный клиент использует устаревший дефолт MTU=1376 для AmneziaWG вместо MTU из импортированного профиля — вызывает «чёрную дыру» PMT… #1416

Open
opened 2026-10-13 20:42:04 +00:00 by bsakaguchi · 5 comments
Owner

Originally created by @Damnboychi1 on GitHub (Aug 27, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3064

Суть проблемы
На десктопных платформах (подтверждено на Windows; судя по коду, вероятно и на Linux, и на обычной сборке macOS без network-extension) клиент AmneziaWG откатывается на захардкоженный defaultMtu = "1376" в client/core/utils/constants/protocolConstants.h, вместо того чтобы использовать значение mtu из импортированного vpn://-профиля подключения. На мобильных сборках (Android/iOS/macOS network-extension) уже стоит defaultMtu = "1280".

// client/core/utils/constants/protocolConstants.h
namespace awg
{
constexpr char defaultPort[] = "55424";
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
constexpr char defaultMtu[] = "1280";
#else
constexpr char defaultMtu[] = "1376";
#endif
Почему это важно
AmneziaWG 3.x добавляет обфускацию на каждый пакет сверх обычного WireGuard (HeaderProtectionKey, junk-пакеты, паддинг S1-S4). С учётом этого оверхеда, MTU в 1376 на туннельном интерфейсе оказывается достаточно большим, чтобы часть исходящих пакетов — заметнее всего крупные одиночные ответы вроде TLS ServerHello/Certificate или тела HTTP-ответа с картинкой — незаметно терялись где-то по пути (классическая «чёрная дыра» PMTU: ICMP "fragmentation needed" не доходит обратно до отправителя, поэтому пропавшие TCP-сегменты никогда не перепосылаются, и соединение просто виснет до таймаута).

Баг воспроизводится стабильно и легко демонстрируется: страница/домен, чей ответ в один всплеск занимает больше одного MTU-сегмента (часть сертификатов, тела картинок и т.д.), просто уходит в таймаут, а мелкие ответы (многие обычные сайты, короткие ответы вроде Google/Яндекс, адаптивно нарезанное видео) работают нормально. Мобильные клиенты этой проблемы не имеют, потому что у них дефолт уже 1280.

Подтверждённая первопричина
Проверено end-to-end на реальном сервере и реальном Windows-клиенте:

На сервере интерфейс AmneziaWG выставлен на MTU = 1280 (в серверном wg0.conf/awg0.conf).
Сгенерирован свежий vpn://-ключ для этого сервера, декодирован — подтверждено, что внутри embedded last_config JSON лежит "mtu": "1280".
Этот же ключ импортирован в Windows-клиент AmneziaVPN (также пробовали полностью удалить сервер из приложения и импортировать заново — результат тот же).
Get-NetIPInterface -InterfaceAlias "AmneziaVPN" -AddressFamily IPv4 на получившемся адаптере показывает NlMtu = 1376, а не 1280.
Захват пакетов на сервере (tcpdump на расшифрованном интерфейсе wg0) во время реального неудачного соединения показывает TCP SYN клиента с mss 1336 — это ровно то MSS, которое подразумевает MTU 1376 (1376 − 20 IP − 20 TCP = 1336), что подтверждает: реальный, живой туннельный интерфейс работает на 1376, а не на импортированных 1280.
Принудительная установка MTU командой netsh interface ipv4 set subinterface "AmneziaVPN" mtu=1280 store=persistent сразу же чинит ранее неработавшие сайты/картинки; при следующем переподключении VPN значение снова сбрасывается на 1376 (подтверждает, что клиент заново применяет свой дефолт при каждом коннекте).
Исправление
config.mtu в AwgProtocolConfig/WireGuardProtocolConfig подставляется из protocols::awg::defaultMtu / protocols::wireguard::defaultMtu только когда пустой (applyDefaultsToClientConfig, awgConfigModel.cpp:224-229 и аналогичный код в wireguardConfigModel.cpp) — то есть на недесктопных платформах он откатывается на устаревшую константу 1376 вместо того, чтобы донести реально импортированное значение. Минимальное и безопасное исправление — просто убрать разделение по платформам и везде использовать 1280, что уже совпадает с тем, что client/daemon/daemon.cpp:262-263 и так считает безопасным минимумом (if (config.m_deviceMTU < 1280) config.m_deviceMTU = 1280;):

-#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
constexpr char defaultMtu[] = "1280";
-#else
-constexpr char defaultMtu[] = "1376";
-#endif
(применяется к неймспейсам wireguard и awg в client/core/utils/constants/protocolConstants.h)

Патч приложен (amnezia-mtu-fix.patch).

Это исправление трогает только дефолт-заглушку, которая используется, когда MTU не передан/не импортирован — оно не затрагивает код-путь, который должен доносить явно импортированное значение, и туда, возможно, стоит заглянуть отдельно: в идеале явно импортированный mtu вообще не должен скатываться к платформенному дефолту.

Окружение
Клиент: AmneziaVPN Windows, протокол AmneziaWG (сервер 3.x, HeaderProtectionKey присутствует).
Сервер:self-hosted контейнер amneziawg-go, интерфейс через awg-quick.
Подтверждено через Get-NetIPInterface, netsh interface ipv4 set subinterface и серверный tcpdump на расшифрованном туннельном интерфейсе.

amnezia-mtu-fix.patch

Originally created by @Damnboychi1 on GitHub (Aug 27, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3064 Суть проблемы На десктопных платформах (подтверждено на Windows; судя по коду, вероятно и на Linux, и на обычной сборке macOS без network-extension) клиент AmneziaWG откатывается на захардкоженный defaultMtu = "1376" в client/core/utils/constants/protocolConstants.h, вместо того чтобы использовать значение mtu из импортированного vpn://-профиля подключения. На мобильных сборках (Android/iOS/macOS network-extension) уже стоит defaultMtu = "1280". // client/core/utils/constants/protocolConstants.h namespace awg { constexpr char defaultPort[] = "55424"; #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) constexpr char defaultMtu[] = "1280"; #else constexpr char defaultMtu[] = "1376"; #endif Почему это важно AmneziaWG 3.x добавляет обфускацию на каждый пакет сверх обычного WireGuard (HeaderProtectionKey, junk-пакеты, паддинг S1-S4). С учётом этого оверхеда, MTU в 1376 на туннельном интерфейсе оказывается достаточно большим, чтобы часть исходящих пакетов — заметнее всего крупные одиночные ответы вроде TLS ServerHello/Certificate или тела HTTP-ответа с картинкой — незаметно терялись где-то по пути (классическая «чёрная дыра» PMTU: ICMP "fragmentation needed" не доходит обратно до отправителя, поэтому пропавшие TCP-сегменты никогда не перепосылаются, и соединение просто виснет до таймаута). Баг воспроизводится стабильно и легко демонстрируется: страница/домен, чей ответ в один всплеск занимает больше одного MTU-сегмента (часть сертификатов, тела картинок и т.д.), просто уходит в таймаут, а мелкие ответы (многие обычные сайты, короткие ответы вроде Google/Яндекс, адаптивно нарезанное видео) работают нормально. Мобильные клиенты этой проблемы не имеют, потому что у них дефолт уже 1280. Подтверждённая первопричина Проверено end-to-end на реальном сервере и реальном Windows-клиенте: На сервере интерфейс AmneziaWG выставлен на MTU = 1280 (в серверном wg0.conf/awg0.conf). Сгенерирован свежий vpn://-ключ для этого сервера, декодирован — подтверждено, что внутри embedded last_config JSON лежит "mtu": "1280". Этот же ключ импортирован в Windows-клиент AmneziaVPN (также пробовали полностью удалить сервер из приложения и импортировать заново — результат тот же). Get-NetIPInterface -InterfaceAlias "AmneziaVPN" -AddressFamily IPv4 на получившемся адаптере показывает NlMtu = 1376, а не 1280. Захват пакетов на сервере (tcpdump на расшифрованном интерфейсе wg0) во время реального неудачного соединения показывает TCP SYN клиента с mss 1336 — это ровно то MSS, которое подразумевает MTU 1376 (1376 − 20 IP − 20 TCP = 1336), что подтверждает: реальный, живой туннельный интерфейс работает на 1376, а не на импортированных 1280. Принудительная установка MTU командой netsh interface ipv4 set subinterface "AmneziaVPN" mtu=1280 store=persistent сразу же чинит ранее неработавшие сайты/картинки; при следующем переподключении VPN значение снова сбрасывается на 1376 (подтверждает, что клиент заново применяет свой дефолт при каждом коннекте). Исправление config.mtu в AwgProtocolConfig/WireGuardProtocolConfig подставляется из protocols::awg::defaultMtu / protocols::wireguard::defaultMtu только когда пустой (applyDefaultsToClientConfig, awgConfigModel.cpp:224-229 и аналогичный код в wireguardConfigModel.cpp) — то есть на недесктопных платформах он откатывается на устаревшую константу 1376 вместо того, чтобы донести реально импортированное значение. Минимальное и безопасное исправление — просто убрать разделение по платформам и везде использовать 1280, что уже совпадает с тем, что client/daemon/daemon.cpp:262-263 и так считает безопасным минимумом (if (config.m_deviceMTU < 1280) config.m_deviceMTU = 1280;): -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) constexpr char defaultMtu[] = "1280"; -#else -constexpr char defaultMtu[] = "1376"; -#endif (применяется к неймспейсам wireguard и awg в client/core/utils/constants/protocolConstants.h) Патч приложен (amnezia-mtu-fix.patch). Это исправление трогает только дефолт-заглушку, которая используется, когда MTU не передан/не импортирован — оно не затрагивает код-путь, который должен доносить явно импортированное значение, и туда, возможно, стоит заглянуть отдельно: в идеале явно импортированный mtu вообще не должен скатываться к платформенному дефолту. Окружение Клиент: AmneziaVPN Windows, протокол AmneziaWG (сервер 3.x, HeaderProtectionKey присутствует). Сервер:self-hosted контейнер amneziawg-go, интерфейс через awg-quick. Подтверждено через Get-NetIPInterface, netsh interface ipv4 set subinterface и серверный tcpdump на расшифрованном туннельном интерфейсе. [amnezia-mtu-fix.patch](https://github.com/user-attachments/files/31509773/amnezia-mtu-fix.patch)
Author
Owner

@Vitalik93 commented on GitHub (Aug 27, 2026):

Потверждаю. После перехода на 1280 на десктопе заработало. Проверил остальные параметры протокола после переноса с телефона - все перенесено, кроме MTU, который на десктопе всегда выставляется на 1376. При очистке протокола и настройки заново опять ставится этот нерабочий параметр. Один момент - после ручной установке MTU не слетает на 1376, остаётся установленное вручную значение.

<!-- gh-comment-id:5441213833 --> @Vitalik93 commented on GitHub (Aug 27, 2026): Потверждаю. После перехода на 1280 на десктопе заработало. Проверил остальные параметры протокола после переноса с телефона - все перенесено, кроме MTU, который на десктопе всегда выставляется на 1376. При очистке протокола и настройки заново опять ставится этот нерабочий параметр. Один момент - после ручной установке MTU не слетает на 1376, остаётся установленное вручную значение.
Author
Owner

@Damnboychi1 commented on GitHub (Aug 27, 2026):

#3065

<!-- gh-comment-id:5442467724 --> @Damnboychi1 commented on GitHub (Aug 27, 2026): #3065
Author
Owner

@Damnboychi1 commented on GitHub (Aug 27, 2026):

Внимание, дополнение:
нашел причину, основной генератор AmneziaVPN при создании ключей явно не указывает параметр MTU
из за чего проставляется стандартный 1376. Из за тяжести пакетов оно режет соединение.

<!-- gh-comment-id:5444715633 --> @Damnboychi1 commented on GitHub (Aug 27, 2026): Внимание, дополнение: нашел причину, основной генератор AmneziaVPN при создании ключей явно не указывает параметр MTU из за чего проставляется стандартный 1376. Из за тяжести пакетов оно режет соединение.
Author
Owner

@TheKoTech commented on GitHub (Aug 27, 2026):

У меня такая же проблема. Установил 1280, заработало

<!-- gh-comment-id:5444742638 --> @TheKoTech commented on GitHub (Aug 27, 2026): У меня такая же проблема. Установил 1280, заработало
Author
Owner

@Damnboychi1 commented on GitHub (Aug 29, 2026):

Добавил парсинг MTU прямо из ключа. До этого всегда работала заглушка

<!-- gh-comment-id:5462023139 --> @Damnboychi1 commented on GitHub (Aug 29, 2026): Добавил парсинг MTU прямо из ключа. До этого всегда работала заглушка
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1416
No description provided.