Разбор VPN-трафика через tcpdump
wg show говорит, что handshake свежий, systemctl status openvpn — что сервис активен, а трафик всё равно ведёт себя странно: то ли идёт через туннель, то ли в обход, то ли не идёт вообще. Демоны врут редко, но показывают только своё состояние, а не то, что на самом деле происходит с пакетами. tcpdump смотрит глубже — прямо на интерфейс, — и превращает гадание в чтение фактов: вот пакет пришёл, вот ушёл, вот здесь он расшифрован, а здесь потерян.
Содержание
- Зачем tcpdump, если есть wg show и systemctl status
- Ловим трафик на wg0 и tun0: базовые команды
- Как отличить туннелированный трафик от обычного в дампе
- Пакеты уходят в туннель, но ответа нет — типичный сценарий
- WireGuard и OpenVPN в дампах: на что смотреть в каждом
- Захват на обеих сторонах туннеля синхронно
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем tcpdump, если есть wg show и systemctl status
Утилиты состояния VPN отвечают на вопрос «жив ли туннель», но не на вопрос «идёт ли через него мой трафик». Между этими вопросами — пропасть, в которой живёт добрая половина VPN-проблем: split tunneling настроен не так, приложение ходит напрямую в обход туннеля, DNS резолвится не через тот интерфейс, или пакеты доходят до сервера, но не возвращаются обратно.
tcpdump — стандартная утилита захвата пакетов, есть почти в любом Linux-дистрибутиве (sudo apt install tcpdump на Debian/Ubuntu, sudo dnf install tcpdump на RHEL-семействе). Она не интерпретирует состояние протокола, а просто показывает, что реально проходит через сетевой интерфейс, байт за байтом. Для диагностики VPN это ключевое отличие: wg show может сообщать «handshake 5 секунд назад», пока внутри туннеля не проходит ни одного пакета с данными — а tcpdump -i wg0 покажет это сразу, потому что там просто ничего не появится.
Работать с tcpdump нужно от root или через sudo:
sudo tcpdump -i wg0 -nn
Флаг -nn отключает резолвинг имён хостов и портов (без него tcpdump делает обратный DNS-запрос на каждый IP и подставляет имена сервисов вместо номеров портов) — для диагностики это лишний шум и задержка, лучше видеть голые цифры.
Ловим трафик на wg0 и tun0: базовые команды
WireGuard создаёт интерфейс wg0 (имя настраивается, но по умолчанию именно такое), OpenVPN — tun0 для routed-режима или tap0 для мостового. Список всех интерфейсов на сервере:
ip -brief link show
Базовый захват на интерфейсе туннеля:
sudo tcpdump -i wg0 -nn
# или
sudo tcpdump -i tun0 -nn
Запустите эту команду и с другого терминала пропингуйте что-нибудь через туннель (ping -c 3 8.8.8.8 с клиента) — в выводе появятся строки вида:
14:22:01.104532 IP 10.0.0.2 > 8.8.8.8: ICMP echo request, id 5123, seq 1, length 64
14:22:01.128991 IP 8.8.8.8 > 10.0.0.2: ICMP echo reply, id 5123, seq 1, length 64
Это уже расшифрованный пакет — на интерфейсе wg0/tun0 ядро отдаёт tcpdump данные после снятия шифрования (на выходе) или до его наложения (на входе). Полезные флаги для точечной диагностики:
sudo tcpdump -i wg0 -nn -c 20 # остановиться после 20 пакетов
sudo tcpdump -i wg0 -nn icmp # только ICMP (пинги)
sudo tcpdump -i wg0 -nn host 8.8.8.8 # только трафик к/от конкретного адреса
sudo tcpdump -i wg0 -nn -v # подробнее: TTL, флаги, длина
sudo tcpdump -i wg0 -nn -w /tmp/wg0.pcap # сохранить дамп в файл для Wireshark
Если на wg0 или tun0 вообще ничего не появляется, пока вы генерируете трафик на клиенте — это уже диагноз: проблема раньше интерфейса туннеля — в маршрутизации на клиенте, в firewall, который режет трафик молча, или сам туннель не поднят.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак отличить туннелированный трафик от обычного в дампе
Главный трюк разбора VPN-трафика — смотреть на двух интерфейсах одновременно: на интерфейсе туннеля (wg0/tun0) и на внешнем интерфейсе, через который туннель выходит наружу (обычно eth0, ens3 или похожее имя). Откройте два терминала (или два окна tmux/screen) и запустите в них разные захваты:
# терминал 1 — что видно "снаружи", на внешнем интерфейсе
sudo tcpdump -i eth0 -nn udp port 51820
# терминал 2 — что видно "внутри" туннеля
sudo tcpdump -i wg0 -nn
На eth0 вы увидите только зашифрованные UDP-пакеты между внешними IP клиента и сервера, без опознаваемой структуры внутри (для WireGuard это сделано специально, чтобы дамп выглядел как случайный шум и не давал DPI зацепок). На wg0 в этот же момент появятся уже расшифрованные IP-пакеты с внутренними адресами туннеля и реальным содержимым — ICMP, TCP SYN, DNS-запросы. Разница между этими двумя дампами и есть визуальное доказательство того, что шифрование и расшифровка реально происходят.
Быстро понять, какой интерфейс операционная система выберет для конкретного адреса, можно ещё до захвата пакетов:
ip route get 8.8.8.8
Если в выводе wg0 или tun0 — трафик к этому адресу пойдёт через туннель; если eth0/wlan0 — в обход. Это самый быстрый способ поймать сломанный split tunneling: приложение «должно» ходить через VPN, а ip route get честно показывает, что маршрут ведёт мимо.
Для WireGuard есть ещё один диагностический приём: посмотреть на первый байт полезной нагрузки UDP-пакета на внешнем интерфейсе через -X (вывод в hex и ASCII):
sudo tcpdump -i eth0 -nn -X udp port 51820 -c 5
Протокол WireGuard кодирует тип сообщения первым байтом полезной нагрузки: 01 — инициация handshake, 02 — ответ на handshake, 03 — cookie reply, 04 — пакет с данными. Если в первые секунды видны 01 и 02, а дальше идут пакеты с 04 — handshake состоялся, туннель в рабочем режиме. Если после 01 ответ 02 не появляется — сервер не смог ответить на инициацию: неверный публичный ключ, недоступен endpoint или блокирует firewall.
Пакеты уходят в туннель, но ответа нет — типичный сценарий
Самая частая жалоба звучит так: «клиент подключён, но интернета нет» или «пингую внутренний сервер — тишина». tcpdump разбирает это по шагам, если запускать захват сразу с двух сторон туннеля.
На клиенте запустите ping и захват на интерфейсе туннеля одновременно:
sudo tcpdump -i wg0 -nn icmp &
ping -c 5 10.0.0.1
Если ICMP echo request виден в дампе клиента — пакет ушёл в туннель штатно. Дальше переходите на сервер и смотрите тот же интерфейс:
sudo tcpdump -i wg0 -nn icmp
Возможны три картины:
- Пакет виден на сервере, ответа нет. Проблема после расшифровки — не включён
net.ipv4.ip_forward, нет правила NAT/MASQUERADE, либо firewall режет исходящий трафик на внешнем интерфейсе. Проверьте счётчики:sudo iptables -t nat -L POSTROUTING -n -vилиsudo nft list ruleset | grep masquerade— растут ли они при повторном пинге. - Пакет не дошёл до
wg0/tun0, хотя наeth0сервера виден зашифрованный UDP от клиента. Расшифровка не удалась или пакет отброшен на уровне туннеля — неверныйAllowedIPs(у WireGuard пакет с несовпадающим внутренним IP отбрасывается молча, без записи в лог), рассинхронизация ключей, либо у OpenVPN не прошла аутентификация сертификата. - Пакет не появился даже на
eth0сервера. Проблема раньше уровня VPN — не доходит физически: неверный маршрут у клиента, firewall провайдера, NAT перед сервером блокирует нужный порт.
Отдельно проверьте фрагментацию — частая причина «туннель работает, но сайты грузятся через раз». Признак в дампе — повторные пересылки одного TCP-сегмента или ICMP-пакеты типа 3 code 4 (fragmentation needed but DF set):
sudo tcpdump -i wg0 -nn -v icmp
Если такие сообщения регулярно появляются — снаружи туннеля MTU меньше, чем ожидает внутренний трафик (типично при вложенных туннелях, PPPoE у провайдера или мобильных сетях). Стоит проверить MTU интерфейса и при необходимости снизить его в конфиге (например, MTU = 1420 вместо стандартных 1500) — точное значение зависит от конкретной сети, универсального числа нет.
WireGuard и OpenVPN в дампах: на что смотреть в каждом
Оба протокола инкапсулируют трафик, но выглядят в tcpdump по-разному — и это стоит знать заранее, чтобы не искать несуществующие признаки.
| WireGuard (wg0) | OpenVPN (tun0/tap0) | |
|---|---|---|
| Транспорт по умолчанию | UDP, порт 51820 | UDP 1194 или TCP (часто маскируют под 443) |
| Структура на внешнем интерфейсе | Фиксированный формат, тип сообщения в первом байте (01–04) | Опкод и session ID в заголовке пакета; в TCP-режиме поверх видна структура TCP-потока |
| Видимость handshake в дампе | Два коротких UDP-пакета (инициация/ответ) перед потоком данных | TLS-подобный обмен при первом подключении, если не включён tls-crypt |
| Похож на что «снаружи» | Случайный шум, специально без сигнатур | В UDP-режиме тоже маскируется под шум; в TCP-режиме на порт 443 похож на HTTPS-сессию |
| Интерфейс для захвата | wg0 (имя можно менять в конфиге) | tun0 (routed) или tap0 (bridged) |
Если вы не знаете заранее, каким протоколом и портом пользуется OpenVPN-сервер, быстрее всего выяснить это через tcpdump на этапе подключения клиента:
sudo tcpdump -i eth0 -nn udp port 1194 or tcp port 443
Пакет сработает по одному из этих правил в момент, когда клиент инициирует соединение — так вы сразу увидите, какой транспорт реально используется, не заглядывая в конфиг.
Важный нюанс: если на сервере включён tls-crypt (в современных конфигах OpenVPN это дефолт для безопасности), даже начальный handshake уже зашифрован дополнительным статическим ключом — в дампе не будет узнаваемого TLS ClientHello, только непрозрачные блоки данных, как и у WireGuard. Это защита от DPI, а не повод для тревоги.
Захват на обеих сторонах туннеля синхронно
Разбор проблем «на стыке» — трафик доходит до одной стороны, но не появляется на другой — требует параллельного захвата на клиенте и сервере с сопоставлением. Порядок действий:
- Убедитесь, что время на обеих машинах синхронизировано через NTP (
chronyc trackingилиtimedatectl) — без этого сопоставлять пакеты по времени будет неудобно. - На клиенте и на сервере одновременно запустите захват с сохранением в файл:
# на клиенте
sudo tcpdump -i wg0 -nn -w /tmp/client-wg0.pcap &
sudo tcpdump -i eth0 -nn udp port 51820 -w /tmp/client-eth0.pcap &
# на сервере
sudo tcpdump -i wg0 -nn -w /tmp/server-wg0.pcap &
sudo tcpdump -i eth0 -nn udp port 51820 -w /tmp/server-eth0.pcap &
- Воспроизведите проблему (пинг, запрос к сервису) и остановите захваты (
sudo kill %1 %2илиCtrl+Cв каждом терминале). - Скопируйте файлы на рабочую машину (
scp user@server:/tmp/server-*.pcap .) и откройте в Wireshark — там удобно сравнивать временные метки, фильтровать поip.addrилиudp.port, и визуально видеть, на каком именно этапе пакет пропадает.
Такой параллельный захват — надёжный способ доказать (себе, коллеге или в тикете провайдеру), на чьей стороне обрывается цепочка: если пакет виден в client-wg0.pcap, но его нет ни в server-eth0.pcap, ни тем более в server-wg0.pcap — проблема на пути между машинами, а не в конфигурации VPN. Для таких экспериментов удобно держать тестовый стенд на отдельном VPS — так вы не рискуете рабочим сервером, перезапуская сетевые правила во время диагностики.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли увидеть расшифрованный трафик на внешнем интерфейсе (eth0)?
Нет, и не должно быть — если на eth0 виден расшифрованный трафик, значит шифрование не работает вообще, это критическая проблема безопасности, а не диагностический успех. Расшифрованные пакеты видны только на интерфейсе туннеля (wg0/tun0), куда их отдаёт ядро уже после снятия шифрования.
Нужны ли root-права для tcpdump?
Да, захват сырых пакетов требует прав уровня ядра — запускайте через sudo или добавьте себе capability cap_net_raw (sudo setcap cap_net_raw,cap_net_admin=eip $(which tcpdump)), если не хотите каждый раз использовать sudo.
Как понять, что трафик вообще не заходит в туннель, даже не запуская tcpdump?
Команда ip route get <адрес> покажет, какой интерфейс операционная система выберет для этого адреса — если это не wg0/tun0, трафик пойдёт мимо туннеля независимо от того, что показывает wg show.
Захват пакетов замедляет VPN или роняет соединения?
На типичных нагрузках VPS — нет, tcpdump сам по себе даёт минимальный оверхед. Заметное замедление возможно только при очень высокой интенсивности трафика и записи полного дампа без фильтров на диск с низкой скоростью записи.
Чем отличается захват на wg0 от захвата на tun0 по сути данных?
Ничем принципиальным — оба интерфейса отдают tcpdump уже декапсулированные IP-пакеты. Разница только в деталях протокола на внешнем интерфейсе: формат UDP-сообщений WireGuard и опкоды/session ID у OpenVPN.
Как оплатить VPS для тестового стенда из России?
В MAATRIX — картой российского банка, через СБП или криптовалютой, без иностранной карты и посредников.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →