MAATRIX / Блог / Wireshark: анализ VPN-соединения

Wireshark: анализ VPN-соединения

MAATRIX

Когда VPN «иногда рвётся» или «не подключается через раз», логи сервиса часто говорят слишком мало: wg show покажет только время последнего handshake, а лог OpenVPN — общую фразу вроде TLS handshake failed без деталей, что именно пошло не так на уровне пакетов. Wireshark закрывает этот пробел — вы видите, дошёл ли пакет инициализации до сервера, ответил ли он, на каком именно шаге TLS-рукопожатия оборвался диалог, и не режет ли трафик MTU или NAT где-то посередине. Разберём, как снять дамп на сервере и клиенте, что означают типы пакетов WireGuard и OpenVPN, и как по конкретным паттернам в Wireshark отличить проблему сети от проблемы конфигурации.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Как снять дамп трафика правильно

Первая ошибка — открывать Wireshark прямо на рабочей станции и надеяться поймать проблему «как-нибудь». Для диагностики VPN нужен дамп с обеих сторон одновременно: на клиенте и на сервере, синхронизированный по времени, иначе сопоставить пакеты будет сложно.

На сервере (Linux) снимайте трафик через tcpdump, а не сам Wireshark — GUI на сервере обычно нет, да и незачем его туда ставить:

# WireGuard, порт 51820 — замените на свой, если меняли ListenPort
sudo tcpdump -i any -w /tmp/wg-server.pcap udp port 51820

# OpenVPN, порт 1194/udp (или tcp, если у вас proto tcp)
sudo tcpdump -i any -w /tmp/ovpn-server.pcap udp port 1194

Если сервер за NAT или интерфейсов несколько, -i any избавляет от угадывания, через какой из них реально идёт трафик. После того как проблема воспроизвелась (клиент не подключился или разорвал сессию), остановите захват Ctrl+C и скачайте файл:

scp root@server_ip:/tmp/wg-server.pcap ./

На клиенте параллельно снимайте тем же способом (в Windows — сразу в Wireshark, кнопка «Start capturing», с фильтром захвата udp port 51820 в поле Capture Filter). Важно: часы на клиенте и сервере должны быть синхронизированы через NTP, иначе при сопоставлении меток времени вы будете сравнивать несопоставимое — если время «плывёт», сверка по номерам пакетов и содержимому важнее, чем по таймстампам.

Отдельный нюанс: если VPN туннелируется через дополнительный слой (например, обфускация, как в AmneziaWG), дамп покажет мусорные с виду пакеты — это ожидаемо, штатный дешифратор WireGuard их не распознает.

Анатомия WireGuard handshake в дампе

WireGuard построен на протоколе Noise, и структура его пакетов жёстко типизирована — первый байт UDP-полезной нагрузки задаёт тип сообщения. В Wireshark (начиная с версии 3.x есть встроенный диссектор wg) это видно в колонке Protocol и в дереве пакета:

Тип (байт 0)Название в WiresharkЧто означает
1Handshake Initiationклиент начинает рукопожатие
2Handshake Responseсервер (или пир) отвечает
3Cookie Replyзащита от DoS — сервер просит повторить с cookie
4Transport Dataзашифрованные полезные данные (уже после handshake)

Отфильтруйте дамп: udp.port == 51820. Если диссектор не подхватился автоматически, примените фильтр вручную: Decode As → протокол WireGuard для этого порта. Здоровый цикл выглядит так: пакет типа 1 от клиента → пакет типа 2 от сервера в течение долей секунды → далее пакеты типа 4 в обе стороны каждые несколько секунд (или чаще, если есть трафик).

По умолчанию Wireshark видит только тип пакета и заголовки — само содержимое handshake (публичные ключи, timestamp) зашифровано по Noise_IK и не читается без приватных ключей. Если нужно заглянуть глубже (например, для отладки собственного форка WireGuard), можно добавить приватный ключ через Edit → Preferences → Protocols → WireGuard, но для типовой диагностики обрывов это обычно не требуется — достаточно видеть сам факт обмена пакетами и их тайминг.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Разбор обрыва: WireGuard handshake без ответа

Самый частый паттерн в дампе при «не могу подключиться»: клиент раз в 5 секунд отправляет Handshake Initiation, а Handshake Response от сервера не приходит вообще. Это видно сразу — в списке пакетов только тип 1, тип 2 отсутствует.

Дальше вопрос — дошёл ли пакет вообще до сервера. Сверьте два дампа:

  • Если пакет есть в дампе клиента, но отсутствует в дампе сервера — проблема на пути: файрвол провайдера, промежуточный NAT, блокировка порта. Проверьте на сервере sudo iptables -L -n | grep 51820 и sudo ss -ulnp | grep 51820 — сокет вообще слушает?
  • Если пакет есть в обоих дампах, но сервер не шлёт Handshake Response — проблема в самом WireGuard: неверный публичный ключ пира, конфликт AllowedIPs, служба не читает актуальный конфиг. Смотрите sudo wg show и journalctl -u wg-quick@wg0 -n 50.
  • Если после Handshake Response трафика (тип 4) почти нет или он есть в одну сторону — это уже не проблема handshake, а маршрутизация или AllowedIPs после установки туннеля. Этот сценарий подробно разобран в статье WireGuard: handshake есть, а трафика нет.

Отдельно обратите внимание на Cookie Reply (тип 3) — если он появляется массово, сервер заподозрил флуд handshake-запросами (например, при переборе ключей или DDoS) и включил защитный механизм под нагрузкой. Разовый cookie reply — норма, постоянный поток — повод посмотреть на dmesg и нагрузку сервера.

Периодичность повторов инициации тоже информативна: WireGuard по спецификации повторяет Handshake Initiation каждые 5 секунд, если не получил ответ, и полностью сбрасывает попытку через ~90 секунд без успешного рукопожатия. Если в дампе видно, что интервал между попытками сильно больше — это, скорее всего, не сам WireGuard, а обёртка вокруг него (systemd-таймер, скрипт reconnect) со своей логикой.

Анатомия TLS-сессии OpenVPN в дампе

OpenVPN устроен сложнее: поверх UDP или TCP он гоняет собственный control-channel протокол, а внутри него — стандартный TLS-хендшейк для аутентификации и обмена ключами. В Wireshark это два слоя диссекторов: openvpn снаружи и tls внутри, если у вас включён обычный tls-auth, а не tls-crypt.

Фильтр для старта: udp.port == 1194 (или tcp.port == 1194 для TCP-режима). Если используется tls-crypt (по умолчанию в свежих конфигах), control-channel пакеты шифруются статическим ключом ещё до TLS — Wireshark в этом случае покажет только протокол OpenVPN без вложенного TLS, содержимое будет нечитаемым до тех пор, пока не начнётся туннелирование обычного трафика. Это нормально и не баг — так и задумано для защиты от активного зондирования (DPI).

Если у вас классический tls-auth (HMAC-подпись без шифрования control-channel), внутри пакетов будет виден стандартный TLS handshake, и Wireshark честно покажет знакомые по HTTPS стадии:

Client Hello        → клиент предлагает версию TLS и шифры
Server Hello         → сервер выбирает параметры
Certificate           → сервер (и клиент, если cert-auth) показывает сертификат
Certificate Verify    → доказательство владения приватным ключом
Change Cipher Spec    → переход на шифрованный канал
Finished              → подтверждение обеих сторон

Полезный фильтр для быстрого поиска именно TLS-сообщений внутри OpenVPN: tls.handshake.type. Он покажет только строки хендшейка, отсеяв keepalive-пакеты и служебный шум — так easier увидеть, на каком именно сообщении обрыв.

Разбор обрыва: TLS handshake failed в дампе

Когда лог сервера пишет TLS_ERROR: BIO read tls_read_plaintext error или клиент получает TLS handshake failed, дамп обычно показывает один из трёх паттернов:

1. Client Hello уходит, ответа нет вообще. В дампе клиента виден исходящий пакет, в дампе сервера он либо отсутствует (блокировка на пути — файрвол, DPI, провайдер режет нестандартный UDP-трафик), либо есть, но сервер не отвечает (служба не запущена, слушает не тот интерфейс, порт закрыт iptables). Проверьте sudo ss -ulnp | grep openvpn и статус systemctl status openvpn-server@server.

2. Обмен идёт, но обрывается на Certificate. Это почти всегда рассинхронизация сертификатов: у клиента устаревший ca.crt, истёк срок клиентского сертификата, либо сервер и клиент используют разные CA после переустановки Easy-RSA. В Wireshark в пакете Certificate можно раскрыть дерево и увидеть serial number и срок действия сертификата, который реально ушёл в эфир — сверьте с тем, что вы ожидали выпустить. Подробный разбор причин именно этой ошибки — в статье OpenVPN: TLS handshake failed — решение.

3. Хендшейк проходит полностью, но соединение рвётся через несколько секунд/минут после Finished. Это уже не TLS-проблема, а обрыв на уровне данных: несовпадение tls-auth/tls-crypt ключей между дублирующимися клиентскими конфигами (сервер видит два клиента с одним common name и разрывает старую сессию), либо MTU — крупные пакеты после установления сессии режутся где-то в пути, и клиент считает это обрывом связи.

MTU, фрагментация и NAT-таймауты — что смотреть отдельно

Часть обрывов, которые выглядят как проблема VPN-протокола, на самом деле следствие сети между клиентом и сервером. Дамп в Wireshark помогает и здесь.

Проверка фрагментации ICMP (актуально и для WireGuard, и для OpenVPN, оба страдают от заниженного MTU на пути):

# С клиента: пинг с флагом "не фрагментировать" и постепенным уменьшением размера
ping -M do -s 1472 8.8.8.8   # Linux, для интерфейса с MTU 1500
ping -f -l 1472 8.8.8.8      # Windows, аналогичный флаг

Если пинг такого размера не проходит, а меньший (например, -s 1400) проходит — где-то на пути MTU меньше ожидаемого, и туннель будет рвать крупные пакеты или сессии с большим объёмом данных (загрузка файлов, видеозвонки). В Wireshark ищите в дампе фрагментированные IP-пакеты фильтром ip.flags.mf == 1 || ip.frag_offset > 0 — их наличие в UDP-трафике VPN уже сигнал, что стоит опустить MTU интерфейса (MTU = 1420 для WireGuard как безопасный старт, tun-mtu 1400 для OpenVPN).

Второй частый источник «случайных» обрывов — таймаут NAT-трансляции на роутере клиента или у провайдера. Если между Transport Data/keepalive-пакетами в дампе клиента виден разрыв дольше, чем настроенный интервал (PersistentKeepalive в WireGuard, keepalive в OpenVPN), а следующий пакет от сервера клиент уже не получает — вероятно, NAT-таблица роутера очистила запись о сессии раньше, чем ожидалось. Решение — уменьшить интервал keepalive (PersistentKeepalive = 25 вместо дефолтных значений, keepalive 10 60 в OpenVPN), это подробно разбирается в статье про обрывы соединения WireGuard.

Быстрый чек-лист по дампу перед тем, как копать глубже

Прежде чем разбирать каждый пакет вручную, пройдите по верхнеуровневым признакам — они сразу указывают направление поиска:

  • Есть Initiation/Client Hello от клиента, ничего в ответ на сервере → сеть/файрвол, не сам VPN-сервис.
  • Есть обмен в обе стороны, но handshake не завершается → конфигурация (ключи, сертификаты, версии протокола).
  • Handshake завершён, трафик идёт, потом резко обрывается → keepalive/NAT-таймаут или MTU на крупных пакетах.
  • Трафик идёт стабильно с одного направления, но не с другого → маршрутизация/AllowedIPs после установления туннеля, не сам handshake.
  • Постоянные Cookie Reply или повторные Client Hello с одинаковым содержимым → нагрузка на сервер или активное вмешательство DPI на пути.

Если сомневаетесь, снимайте дамп сразу на обеих сторонах в момент воспроизведения проблемы — постфактум по логам такие вещи почти невозможно восстановить, а свежий .pcap разбирается за несколько минут.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Можно ли расшифровать сам трафик WireGuard или OpenVPN в Wireshark, а не только служебные пакеты?

Для WireGuard — да, если добавить приватный ключ через Preferences → Protocols → WireGuard, диссектор умеет расшифровывать Transport Data пакеты по Noise-протоколу. Для OpenVPN расшифровка возможна только при определённых режимах (без Perfect Forward Secrecy и с доступом к приватному ключу сессии), на практике для диагностики обрывов это обычно не требуется — важнее сам факт обмена пакетами и их тайминг.

Wireshark не распознаёт пакеты WireGuard/OpenVPN, показывает просто UDP.

Примените Decode As (правый клик по пакету → Decode As) и выберите нужный протокол для этого порта вручную — автоопределение иногда не срабатывает, если порт нестандартный или трафик обёрнут в обфускацию вроде AmneziaWG.

Дамп на клиенте показывает исходящие пакеты, а на сервере их нет вообще — куда смотреть дальше?

Проверяйте цепочку по порядку: локальный файрвол клиента → NAT/файрвол домашнего роутера → фильтрация у провайдера (актуально при обходе блокировок) → security group/firewall самого VPS → iptables/nftables на сервере. Дамп tcpdump прямо на внешнем интерфейсе сервера — самая надёжная точка проверки: если пакета там нет, дело не в VPN-сервисе.

Сколько нужно захватывать трафика, чтобы поймать редкий обрыв?

Ограничивайте файл по размеру, а не только по времени, иначе дамп разрастётся до нечитаемых объёмов: tcpdump -i any -w cap.pcap -C 100 -W 5 udp port 51820 — ротация по 100 МБ, хранить последние 5 файлов. Для действительно редких обрывов (раз в сутки и реже) удобнее временно включить более подробное логирование самого VPN-сервиса параллельно с фоновым tcpdump, чтобы сопоставить время события с логом.

Нужно ли ставить Wireshark на сам сервер?

Нет и не стоит — GUI-приложение на продакшн-сервере лишняя поверхность атаки и лишние зависимости. Снимайте дамп через tcpdump (он есть почти везде по умолчанию или ставится одним пакетом), скачивайте .pcap на рабочую машину и уже там открывайте в Wireshark.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →