OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

WireGuard для «роумящих» клиентов: persistent-keepalive и смена IP

Мобильные и «роумящие» WireGuard‑клиенты часто меняют IP: LTE→Wi‑Fi, CGNAT, спящий режим. Из‑за этого рвутся соединения и ломается доступ к сервисам. В статье — как работает роуминг, где ставить persistent‑keepalive, готовые пресеты MTU, нюансы с DNS и сменой IP сервера, плюс чек‑лист диагностики.
WireGuard для «роумящих» клиентов: persistent-keepalive и смена IP

Если у вас есть мобильные или «роумящие» клиенты WireGuard — сотрудники с ноутбуками, смартфоны, IoT‑терминалы — вы точно сталкивались с потерями туннеля при смене сети и IP. Пользователь переходит с LTE на Wi‑Fi, едет между сотами, засыпает телефон, а потом «встает» другой публичный адрес и порт. Правильная настройка роуминга, persistent-keepalive и MTU снимает большую часть этих проблем и делает VPN предсказуемым.

Как WireGuard переживает смену IP (роуминг)

WireGuard не держит «сессию» в классическом понимании. У каждого пира есть ключи и «Endpoint», а актуальный внешний адрес и порт обновляются автоматически по факту получения валидно подписанного пакета. Это и называется роуминг: клиент может менять исходный IP/порт, и сервер примет новое значение, как только прилетит любой зашифрованный пакет от того же пира.

Отсюда ключевые следствия:

  • Если клиент за NAT/CGNAT, ему нужно периодически отправлять пакеты наружу, чтобы не протухало UDP‑соответствие на промежуточном устройстве. Для этого служит PersistentKeepalive.
  • Роуминг срабатывает только при наличии трафика. Если клиент «молчит», сервер не узнает, что у него поменялся IP/порт, и будет продолжать слать пакеты в пустоту.
  • При резкой смене сети (например, Wi‑Fi→LTE) полезно мгновенно инициировать рукопожатие. На iOS/Android это делает официальный клиент сам, на Linux можно дернуть конфиг через wg setconf или просто дождаться keepalive/трафика.

Таймеры и жизненный цикл рукопожатия

В норме у пира каждые 2 минуты происходит рекей (переустановка ключей), а в простое соединение «усыпается». Когда приходит пользовательский пакет (или keepalive), «Endpoint» обновляется, а туннель «просыпается». Если трафика нет, записи в карте пиров «стареют», и без keepalive роумящий клиент рискует потерять маршрут в ответ.

Простое правило: пир за NAT должен периодически сам стучаться на публичную сторону. Поэтому PersistentKeepalive настраивают на стороне того устройства, которое находится за NAT/CGNAT или часто меняет исходный IP.

Когда и где ставить PersistentKeepalive

PersistentKeepalive — это параметр в блоке [Peer], говорящий локальному устройству «шлём пустой пакет раз в N секунд, даже если нет пользовательского трафика». Ставится там, где мы хотим отправлять keepalive наружу. Для схемы «мобильный клиент → публичный сервер» — в конфиге клиента. Для «офисный роутер за провайдерским NAT → публичный хаб» — в конфиге роутера. Если обе стороны за NAT и инициировать соединение может только одна сторона — keepalive нужен именно на «внутренней» стороне.

Рекомендованное значение

Классическая рекомендация — PersistentKeepalive = 25. Это значение достаточно частое, чтобы не истекал UDP‑таймаут у большинства NAT (обычно 30–120 секунд), и при этом не слишком «прожорливое» для батареи смартфонов. Если наблюдаются обрывы при «молчаливых» клиентах, можно снизить до 20–15, но помните о компромиссе с энергопотреблением.

Сложные NAT и корпоративные сети

В сетях с агрессивными таймаутами и фильтрацией UDP может понадобиться:

  • уменьшить интервал до 15 секунд,
  • разрешить исходящий UDP на конкретный порт со стороны клиента,
  • при невозможности UDP — рассмотреть альтернативные транспортные решения (внутри разрешённой политики). WireGuard по дизайну работает поверх UDP.

Роуминг мобильного клиента WireGuard между Wi‑Fi и LTE через NAT/CGNAT

MTU для роумящих клиентов

Неправильный MTU проявляется как «залипающие» соединения, особенно в мобильных сетях и при переходе IPv4↔IPv6. У WireGuard есть собственные накладные расходы: поверх UDP добавляется шифрование, и эффективная полезная нагрузка уменьшается. Общепринятые пресеты:

  • Базовая Ethernet‑сеть с MTU 1500: ставьте MTU = 1420 на интерфейсе WireGuard.
  • PPPoE с MTU 1492: используйте MTU ≈ 1412.
  • Мобильные/IPv6‑трассы с «хрупким» PMTUD: иногда помогает консервативный MTU = 1280.

Лучше проверять фактический путь:

  • Linux IPv4: подбирайте максимальный размер с ping -M do и постепенно увеличивайте -s к удалённому адресу за туннелем.
  • IPv6: используйте tracepath или аналогичный инструмент для оценки пути.

Если туннель работает, но часть сайтов/сервисов «подвисает» на крупных ответах, первым делом снижайте MTU на 20–40 байт и проверяйте снова. Для роумящих клиентов универсальным компромиссом часто оказывается 1420, а при регулярных обрывах — 1380–1400.

Подбор MTU для WireGuard: ping -M do и tracepath

Пример конфигурации: сервер и роумящий клиент

Сервер: публичный адрес, статический порт

Поднять публичную сторону WireGuard проще всего на VDS со стабильным адресом и открытым UDP‑портом.

# /etc/wireguard/wg0.conf
[Interface]
Address = 10.6.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
# По желанию: MTU (чаще достаточно на клиентах)
# MTU = 1420

# Пир: роумящий клиент за NAT
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
PresharedKey = OPTIONAL_PRESHARED_KEY
AllowedIPs = 10.6.0.2/32
# На сервере чаще НЕ ставим PersistentKeepalive, он должен идти от клиента

Клиент: ноутбук/смартфон, роумит между сетями

# /etc/wireguard/wg0.conf (wg-quick на Linux/macOS)
[Interface]
Address = 10.6.0.2/32
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 9.9.9.9
MTU = 1420

[Peer]
PublicKey = SERVER_PUBLIC_KEY
PresharedKey = OPTIONAL_PRESHARED_KEY
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25

Пояснения:

  • Endpoint можно указывать доменным именем — это удобно, когда у сервера возможна смена IP. Если нужен удобочитаемый адрес, используйте регистрацию доменов и настройте A/AAAA‑записи.
  • AllowedIPs определяет маршрутизацию через туннель. Для «полного туннеля» используем 0.0.0.0/0, ::/0; для «сплит‑туннеля» — только нужные подсети.
  • PersistentKeepalive установлен у клиента, потому что именно он находится за NAT и меняет исходный адрес.

Смена IP у клиента: что произойдёт

Как только роумящий клиент отправит очередной пользовательский или keepalive‑пакет с нового адреса/порта, сервер обновит «Endpoint» и продолжит общение уже на новый источник. Пользователь обычно этого не замечает. Проблемы начинаются, если:

  • клиент долго молчит, а NAT уже забыл соответствие;
  • в новой сети блокируют исходящий UDP или порт сервера;
  • сломался PMTUD, и крупные пакеты не проходят (см. MTU).

Решения: уменьшить интервал keepalive, использовать «надежный» порт, уменьшить MTU, включить в клиенте режим автоконнекта при сетевых событиях (в мобильных клиентах это штатная опция).

Смена IP у сервера: не забываем про DNS и re-resolve

Если меняется публичный адрес сервера, а у клиентов в Endpoint указан домен, его нужно переобновить на стороне WireGuard. Большинство десктоп‑клиентов и mobile‑приложений re‑resolve делают при старте/переключении сети. На Linux сервере/клиенте, с wg-quick, можно принудительно «перечитать» конфигурацию или переустановить Endpoint тем же доменным именем, чтобы прошёл новый DNS‑резолв.

# Принудительно перечитать конфиг (короткий даун/ап)
sudo wg-quick down wg0
sudo wg-quick up wg0

# Или атомично синхронизировать конфиг (без даунтайма интерфейса)
sudo wg setconf wg0 /etc/wireguard/wg0.conf

Альтернативно можно периодически запускать задачу, которая переустанавливает Endpoint через wg set с тем же доменным именем, вынуждая re‑resolve в userspace. Это полезно, если сервер иногда получает новый IP от провайдера.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Тонкости AllowedIPs и маршрутизации для роуминга

Частая ошибка — слишком широкие или, наоборот, конфликтующие маршруты. Для точечного доступа к нескольким внутренним подсетям указывайте их явно, избегая пересечений с локальными сетями клиента (например, домашняя 192.168.0.0/24). Если «локалка» клиента совпадает с корпоративной, у роумящего клиента возникнет асимметричная маршрутизация и часть трафика уйдет мимо туннеля.

Советы:

  • всегда проверяйте таблицу маршрутов у клиента после поднятия VPN;
  • для сплит‑туннеля не используйте дефолт, добавляйте только нужные префиксы;
  • если нужен полный туннель, резолв DNS лучше отдавать через VPN, чтобы избежать утечек.

Диагностика: что смотреть при обрывах у «роумящих»

  1. Статус WireGuard. На обеих сторонах: wg show. Обратите внимание на latest handshake, счётчики трафика, текущий endpoint. Если рукопожатий давно не было и трафик не растёт, проблема либо в UDP/маршрутизации, либо в MTU.
  2. Проверка UDP и порта. На сервере: ss -ulpn | grep 51820 — слушает ли порт. tcpdump -n -i eth0 udp port 51820 — прилетает ли что‑то от клиента после смены сети.
  3. MTU. Если мелкие запросы проходят, а крупные — нет, снижайте MTU на интерфейсе WireGuard у клиента и повторяйте тесты.
  4. Keepalive. Для клиентов за NAT/CGNAT проверьте, что PersistentKeepalive выставлен и не слишком большой (25 — хорошая отправная точка).
  5. DNS re-resolve. При смене IP сервера убедитесь, что клиенты пере‑резолвили домен. На Linux помогайте себе wg setconf или перезапуском интерфейса.

Особенности мобильных клиентов

Официальные приложения на iOS/Android умеют «подхватывать» сетевые события и триггерить повторное рукопожатие. Но энергосбережение ОС может откладывать фоновые задачи. Если пользователи жалуются на «долгий выход из сна», попробуйте снизить PersistentKeepalive до 20–15, а также убедитесь, что приложению выданы права на работу в фоне и отключены жесткие оптимизации батареи.

Несколько аплинков на сервере

Если у сервера два провайдера и исходящий адрес может меняться, убедитесь, что:

  • маскарад/маршрутизация обратного трафика идут через интерфейс, где сервер получил входящие пакеты по UDP 51820;
  • политики фильтрации не меняют исходящий порт неожиданно;
  • по возможности используйте стабильный публичный адрес и фиксированный ListenPort.

Если требуются проксирование или балансировка UDP для WireGuard, посмотрите материал про балансировку TCP/UDP в Nginx Stream. Для межофисных тоннелей пригодится статья WireGuard site‑to‑site на VDS.

Частые вопросы

  • Нужно ли ставить keepalive на обеих сторонах? Обычно нет. Достаточно на стороне клиента за NAT. Дублировать смысла мало, только увеличите фоновый трафик.
  • Какое значение выбрать? Начинайте с 25 секунд, корректируйте по логам и отзывам пользователей.
  • Что с MTU по умолчанию? Для Ethernet часто работает 1420. Если есть жалобы — снижайте до 1400 или 1380. В крайних случаях 1280.
  • Почему сервер не видит клиента после смены сети? Клиент не отправил ни одного пакета (нет keepalive), блокируется UDP, или потерян маршрут/неверный MTU.

Чек‑лист внедрения роуминга WireGuard

  • У клиента за NAT включен PersistentKeepalive = 25.
  • На клиенте задан адекватный MTU (стартуйте с 1420, затем корректируйте тестами).
  • Сервер слушает стабильный ListenPort, проброшен на внешнем маршрутизаторе (если нужен). UDP не фильтруется.
  • В AllowedIPs нет конфликтующих подсетей с локальными сетями клиента.
  • Endpoint задан доменным именем, а клиенты умеют re‑resolve (при необходимости — скрипт/таймер с wg setconf).
  • Логи и wg show мониторятся: отслеживаете «latest handshake», «transfer» и «endpoint» при сетевых сменах.

Настроив эти элементы, вы получите отказоустойчивый роуминг WireGuard‑клиентов без «магии»: сервер автоматически примет новый адрес клиента, NAT не успеет «забыть» соответствие благодаря PersistentKeepalive, а правильно подобранный MTU избавит от подвисаний на крупных ответах. В итоге мобильные пользователи перестанут «ронять» VPN при каждом переходе между сетями.

Поделиться статьей

Вам будет интересно

systemd-run: ограничиваем CPU и RAM для одноразовых задач и интерактивных команд OpenAI Статья написана AI (GPT 5)

systemd-run: ограничиваем CPU и RAM для одноразовых задач и интерактивных команд

Как быстро ограничить CPU и память для разовых команд без unit-файлов: используем systemd-run, transient units в режимах --service ...
OpenSearch на VDS: практический гид по памяти JVM heap, ISM-политикам и снапшотам OpenAI Статья написана AI (GPT 5)

OpenSearch на VDS: практический гид по памяти JVM heap, ISM-политикам и снапшотам

Поднимем OpenSearch на VDS: настроим JVM heap без сюрпризов с GC, спроектируем ISM с rollover и удалением, организуем регулярные s ...
ACME DNS‑01 через RFC2136: свой DNS‑API без облаков OpenAI Статья написана AI (GPT 5)

ACME DNS‑01 через RFC2136: свой DNS‑API без облаков

DNS‑01 решает выпуск wildcard и закрытых сервисов, но нужен API к авторитетному DNS. Покажу, как поднять свой «API» на RFC2136: BI ...