Короткий ответ

Периодический обрыв с почти одинаковым интервалом — почти всегда таймер: NAT UDP mapping (часто 30–180 с), DPD IPsec, ping-restart OpenVPN, отсутствие PersistentKeepalive у WireGuard за NAT. Снимите временны́е метки disconnect в логе и сравните с wg show / swanctl --list-sas. Не отключайте DPD «навсегда»: при мёртвом пире SA останутся зомби. Сначала keepalive, потом разумный DPD.

Если интервал случайный и совпадает с потерями — это канал/MTU, не NAT.

Симптомы и как отличить

  • Работает 1–3 минуты, потом Disconnected, переподключение помогает.
  • WireGuard: latest handshake уезжает за 2+ минуты, ping оживает после нового handshake.
  • strongSwan: DPD: remote seems to be dead.
  • OpenVPN: Inactivity timeout, ping-restart.
  • Windows RAS: RasClient disconnect без ошибки пользователя.

Не путать с:

  • Никогда нет handshake — WG handshake.
  • Сессия жива, но «тупит» — медленно, MTU.
  • Только L2TP 789 при каждом коннекте — L2TP.

Возможные причины

  1. Клиент за NAT/CGNAT, UDP idle timeout короче, чем интервал keepalive.
  2. WireGuard без PersistentKeepalive (сервер не инициирует, маппинг умирает).
  3. IPsec DPD агрессивный (delay=5, timeout=15) на плохом Wi-Fi.
  4. OpenVPN ping 10 / ping-restart 30 при джиттере.
  5. DHCP смена WAN IP на роутере клиента.
  6. Sleep/Connected standby Windows, NIC sleep.
  7. Смена исходного порта (два клиента, один ключ).
  8. Политика firewall conntrack слишком короткий nf_conntrack_udp_timeout.

Диагностика

1. Интервал

Журнал клиента + сервера в одном часовом поясе.

journalctl -u wg-quick@wg0 -u strongswan --since '1 hour ago'
wg show
Get-WinEvent -LogName Application -ProviderName RasClient -MaxEvents 30 |
  Select-Object TimeCreated, Id, Message
Get-VpnConnection

2. NAT mapping

На клиентском роутере или на шлюзе:

tcpdump -n -i eth0 udp port 51820 or udp port 4500

Перед обрывом трафик keepalive есть? Если тишина 2 минуты — нет keepalive. Если keepalive есть, а сервер перестаёт отвечать — сервер/WAN.

3. Таймауты стека

Linux-шлюз:

sysctl net.netfilter.nf_conntrack_udp_timeout net.netfilter.nf_conntrack_udp_timeout_stream

Слишком маленькие значения на промежуточном NAT убивают VPN.

4. DPD / keepalive конфиг

OpenVPN: ping, ping-restart, keepalive в server.conf. strongSwan: dpd_delay, dpd_timeout, dpdaction. WireGuard: PersistentKeepalive = 25 на стороне за NAT.

Решение

Сценарий A. WireGuard за NAT

На клиенте:

PersistentKeepalive = 25

25 секунд — обычная практика ниже типичных NAT timeout. Серверу keepalive не обязателен, если клиент всегда инициатор.

Сценарий B. IPsec DPD

Выставьте умеренно: delay 30 с, timeout 120–150 с, dpdaction=restart для roadwarrior. На нестабильном 4G не используйте пятисекундный DPD. После изменения — новый IKE.

Сценарий C. OpenVPN

На сервере типично keepalive 10 60 (ping каждые 10, рестарт после 60 без ответа). Не делайте ping-restart 15 на спутнике. Клиент не должен задавать более жёсткий restart, чем сервер, без причины.

Сценарий D. Windows sleep

В профиле питания отключите отключение NIC при sleep для корпоративных ноутбуков на время командировок или учите пользователей reconnect. Always On VPN / автоконнект — отдельная политика, не «DPD=off».

Get-NetAdapterPowerManagement -Name 'Wi-Fi' | Format-List

Не отключайте энергосбережение глобально всем ПК без согласования.

Сценарий E. Два устройства — один ключ

Разведите пиры WireGuard / сертификаты OpenVPN / учётки. Иначе «обрыв» — это кража сессии.

Сценарий F. Короткий conntrack на офисном NAT

Если VPN-сервер за своим NAT:

sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=180

Постоянно — sysctl.d. Значение согласуйте с keepalive (keepalive < timeout).

Стенд: idle 10 минут vs постоянный ping

Два прогона обязательны. Прогон A: после Connect ничего не делайте 10 минут, смотрите wg show / RasClient. Прогон B: ping -i 30 10.8.0.1. Если A рвётся, B нет — idle NAT/DPD, не «плохой интернет». Если оба рвутся с потерями ICMP — канал, не keepalive.

На промежуточном Linux NAT:

conntrack -L -p udp --dport 51820
sysctl net.netfilter.nf_conntrack_udp_timeout_stream

Сверяйте timeout с PersistentKeepalive. Keepalive 25 с при timeout 30 с — лотерея. Keepalive 25 при timeout 180 — норма.

Для IPsec снимите dpd_delay из swanctl.conf в тикет, не держите «как в примере github». Windows IKEv2 сам шлёт keepalive по-своему; не копируйте WG-цифры в charon.

Сон ноутбука: после Resume сравните Get-Date с NTP. WireGuard отбросит старый handshake при скачке часов. Это выглядит как «VPN отвалился во сне», но корневая причина — время, не NAT. Включите w32tm / chrony до увеличения keepalive.

Как проверить, что проблема устранена

Оставьте туннель без пользовательского трафика на 15–20 минут (idle). Ping раз в минуту к 10.8.0.1 не должен требовать ручного reconnect. wg show — свежий handshake. OpenVPN лог без ping-restart. Windows: нет пачки RasClient disconnect.

ping -i 30 -c 20 10.8.0.1
wg show

Если не помогло

  • Обрыв только на больших файлах — MTU, не NAT.
  • Обрыв в одно и то же время суток — DHCP lease WAN, backup WAN failover.
  • Только IKEv2, WireGuard стабилен — DPD/NAT-T IPsec.
  • Мобильный оператор режет долгий UDP — смена порта/протокола по политике, не «ещё короче DPD».

Профилактика

  • В шаблоне WG клиента сразу PersistentKeepalive = 25.
  • Документировать DPD и keepalive.
  • Мониторинг длительности сессий (гистограмма), не только «сейчас онлайн».
  • Не шарить один клиентский ключ.

FAQ

Почему при постоянном iperf обрывов нет, а на простое есть?

NAT idle timeout. Keepalive как раз для простоя.

Безопасно ли отключить DPD?

Для двух белых IP с мониторингом — спорно, зомби SA. Для NAT roadwarrior — нет, лучше увеличить timeout.

25 секунд keepalive нагрузит канал?

Пакеты крошечные. Это не видео. На тысячах пиров считайте отдельно, для SMB-офиса незаметно.

Windows 11 сам держит IKEv2?

Mobility/MOBIKE помогает при смене сети, не при убитом NAT mapping без трафика. Проверьте, что профиль не «ручной» без reconnect.

После обрыва новый handshake, трафика нет

Тогда смотрите AllowedIPs/маршруты, статья handshake есть / LAN. Эта статья — про сам разрыв сессии.