Learning Platform
Глоссарий Troubleshooting
Урок 16.05 · 24 мин
Начальный
tcpdumpWiresharkPacket CaptureTroubleshooting

tcpdump и Wireshark — захват и анализ трафика

Когда стандартные инструменты (ping, curl, dig, ss) не дают ответа на «почему сеть не работает», остаётся один последний инструмент — захват самого трафика. Вы буквально смотрите на байты, которые летят по сети, и понимаете, что не так. Это уровень нинзя сетевой диагностики, и в этом уроке разберём два главных инструмента: tcpdump (CLI) и Wireshark (GUI).

tcpdump запускается на удалённом сервере по SSH и пишет в pcap-файл. Wireshark открывает pcap локально и даёт интерактивный анализ с фильтрами, графиками, расшифровкой протоколов. Вместе они — стандарт de facto в network troubleshooting.


tcpdump — minimum viable example

tcpdump слушает сетевой интерфейс и выводит каждый пакет. Это требует root-прав (raw sockets).

# Самый базовый запуск (выведет всё на eth0):
sudo tcpdump -i eth0
# tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
# listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
# 14:30:45.123456 IP 10.0.0.42.45678 > 142.250.74.110.443: Flags [S], seq 12345, win 65535, length 0
# 14:30:45.156789 IP 142.250.74.110.443 > 10.0.0.42.45678: Flags [S.], seq 67890, ack 12346, win 65535, length 0
# 14:30:45.156823 IP 10.0.0.42.45678 > 142.250.74.110.443: Flags [.], ack 67891, win 65535, length 0
# 14:30:45.157234 IP 10.0.0.42.45678 > 142.250.74.110.443: Flags [P.], seq 12346:12400, ack 67891, win 65535, length 54
# ...

# Остановить -- Ctrl+C

Разберём output (один пакет):

14:30:45.123456 IP 10.0.0.42.45678 > 142.250.74.110.443: Flags [S], seq 12345, win 65535, length 0
  • 14:30:45.123456 — timestamp с микросекундами.
  • IP — IPv4 (или IP6).
  • 10.0.0.42.45678 — source IP.port.
  • > — направление.
  • 142.250.74.110.443 — destination IP.port (443 = HTTPS).
  • Flags [S] — TCP flags. S = SYN. Это первый пакет TCP-handshake.
  • seq 12345 — sequence number.
  • win 65535 — receive window.
  • length 0 — payload длина (SYN не несёт data).

TCP flags:

  • S = SYN (handshake initiation)
  • A или . = ACK
  • F = FIN (closing)
  • R = RST (reset)
  • P = PSH (push — сигнал передать сразу)
  • U = URG (urgent)

[S.] = [SYN+ACK]. [F.] = [FIN+ACK]. И т.д.

Так что в нашем примере:

  1. Flags [S] — клиент шлёт SYN на сервер.
  2. Flags [S.] — сервер отвечает SYN-ACK.
  3. Flags [.] — клиент шлёт ACK. TCP handshake завершён.
  4. Flags [P.] length 54 — клиент шлёт первые 54 байта данных (TLS Client Hello).

Видно весь handshake глазами.


Фильтры — основа эффективного capture

tcpdump без фильтров — это потоп пакетов. Эффективно использовать — значит фильтровать по конкретным критериям. Это BPF (Berkeley Packet Filter) синтаксис.

По хосту

# Все пакеты к/от конкретного IP:
sudo tcpdump -i eth0 host 142.250.74.110

# Только исходящие:
sudo tcpdump -i eth0 src host 10.0.0.42

# Только входящие:
sudo tcpdump -i eth0 dst host 10.0.0.42

# По имени (резолвится в IP при запуске):
sudo tcpdump -i eth0 host github.com

По порту

# Весь HTTP-трафик:
sudo tcpdump -i eth0 port 80

# Только HTTPS:
sudo tcpdump -i eth0 port 443

# DNS-запросы:
sudo tcpdump -i eth0 port 53

# Диапазон портов:
sudo tcpdump -i eth0 portrange 8000-9000

По протоколу

# Только TCP:
sudo tcpdump -i eth0 tcp

# Только UDP:
sudo tcpdump -i eth0 udp

# Только ICMP (ping):
sudo tcpdump -i eth0 icmp

# ARP:
sudo tcpdump -i eth0 arp

Комбинации

# HTTPS-трафик к конкретному серверу:
sudo tcpdump -i eth0 'host 142.250.74.110 and port 443'

# DNS и HTTPS:
sudo tcpdump -i eth0 'port 53 or port 443'

# Не SSH (чтобы не засорять output при SSH-сессии):
sudo tcpdump -i eth0 'not port 22'

# TCP с конкретного source:
sudo tcpdump -i eth0 'src host 10.0.0.42 and tcp'

# Только SYN (открытие соединения):
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack = 0'

Подсети

# Все в подсети:
sudo tcpdump -i eth0 net 10.0.0.0/24

# От любого внешнего к нам:
sudo tcpdump -i eth0 'src net not 10.0.0.0/8 and dst host 10.0.0.42'

Полезные флаги tcpdump

# -n -- не резолвить имена в IP (быстрее, без зависимости от DNS):
sudo tcpdump -n -i eth0

# -nn -- не резолвить порты (видеть номера, а не "https"/"ssh"):
sudo tcpdump -nn -i eth0

# -v / -vv / -vvv -- verbose level. Больше деталей.
sudo tcpdump -nn -v -i eth0

# -X -- hex и ASCII dump каждого пакета:
sudo tcpdump -nn -X -i eth0 'port 80'

# -A -- ASCII только (для plain-text протоколов):
sudo tcpdump -nn -A -i eth0 'port 80'

# -s 0 -- захватывать весь пакет (по умолчанию иногда обрезают):
sudo tcpdump -s 0 -i eth0

# -c N -- остановиться после N пакетов:
sudo tcpdump -nn -c 100 -i eth0

# -i any -- слушать все интерфейсы сразу:
sudo tcpdump -nn -i any

# -w file.pcap -- писать в файл, не в stdout:
sudo tcpdump -nn -i eth0 -w /tmp/capture.pcap

# -r file.pcap -- читать из файла:
tcpdump -nn -r /tmp/capture.pcap

# -D -- список доступных интерфейсов:
sudo tcpdump -D

Реальный пример: дебажим HTTP

Сценарий: API на порту 8080 не отвечает на запросы. Хотим увидеть, доходят ли SYN до сервера, что отвечает.

# На сервере (по SSH):
sudo tcpdump -nn -i any 'tcp and port 8080' -w /tmp/api-debug.pcap

# В другом терминале на клиенте:
curl http://server-ip:8080/

# В первом терминале -- Ctrl+C через несколько секунд

# Прочитать pcap:
tcpdump -nn -r /tmp/api-debug.pcap

Если pcap пустой — SYN от клиента не доходит. Скорее всего firewall или сетевая проблема.

Если SYN видны, но нет SYN-ACK — сервер получает, но не отвечает. Возможно, нет процесса на порту 8080 (lsof -iTCP:8080) или firewall блокирует на уровне OS (iptables).

Если есть SYN-ACK-ACK (handshake), но потом RST — приложение упало после accept-а.

# Только SYN-пакеты (открытие соединений):
tcpdump -nn -r /tmp/api-debug.pcap 'tcp[tcpflags] & tcp-syn != 0'

# Только RST (resets -- сервер отказывается):
tcpdump -nn -r /tmp/api-debug.pcap 'tcp[tcpflags] & tcp-rst != 0'

Wireshark — то же самое, но GUI

Wireshark — графический интерфейс к libpcap (то же, что использует tcpdump). Может работать в двух режимах:

  1. Live capture — читать пакеты в реальном времени с интерфейса.
  2. Offline analysis — открывать pcap-файлы.

Второй — стандарт workflow: на удалённом сервере запустить tcpdump -w capture.pcap, скачать файл локально и открыть в Wireshark.

# Захват на сервере:
sudo tcpdump -i eth0 -w /tmp/capture.pcap

# Скопировать локально:
scp server:/tmp/capture.pcap .

# Открыть:
wireshark capture.pcap

В Wireshark вы видите:

  • Список пакетов — каждый с timestamp, source, destination, protocol, info.
  • Детали выбранного пакета — разбор по слоям (Ethernet, IP, TCP, application).
  • Hex dump — сырые байты.
  • Фильтры в верхней панели.

Wireshark display filters

Фильтры Wireshark отличаются от tcpdump (BPF). Богаче, поддерживают application protocols.

# По адресу:
ip.addr == 10.0.0.42
ip.src == 10.0.0.42
ip.dst == 142.250.74.110

# По порту:
tcp.port == 443
tcp.dstport == 80

# По протоколу:
http
dns
tls
icmp
arp

# По содержимому HTTP:
http.request.method == "POST"
http.response.code == 500
http.host == "api.example.com"
http.user_agent contains "curl"

# По содержимому DNS:
dns.qry.name == "google.com"
dns.flags.response == 1

# TLS handshake типы:
tls.handshake.type == 1  # Client Hello
tls.handshake.type == 2  # Server Hello

# Комбинации:
ip.addr == 10.0.0.42 and tcp.port == 443
http.request.method == "POST" and http.host contains "api"

После применения фильтра — список пакетов сужается. Очень удобно искать конкретные события (например, все DNS-запросы на bank.com или все HTTP 5xx).


Follow TCP Stream — собрать поток

Один из самых полезных features Wireshark — Follow > TCP Stream (правый клик на пакете). Это покажет весь обмен данными между двумя сторонами как контигуальный текст, как будто вы смотрите на чат.

Для plain-text HTTP это будет:

GET /api/users HTTP/1.1
Host: api.example.com
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 123

{"users": [...]}

Сразу видно: вы запросили, сервер ответил. Это аналог curl -v, но «после факта», для уже прошедших запросов.

Для TLS-трафика — увы, только зашифрованные байты. Если у вас есть session keys (например, через SSLKEYLOGFILE env-переменную в браузере), Wireshark может расшифровать — но это редкий сценарий.


TLS-трафик — что видно

Даже без расшифровки TLS Wireshark показывает много полезного:

TLS Client Hello (тип 1):
  SNI: api.example.com  # !!! Открытый текст, виден всем
  Versions: TLS 1.2, TLS 1.3
  Cipher Suites: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, ...
  ALPN: h2, http/1.1

TLS Server Hello (тип 2):
  Version: TLS 1.3
  Cipher: TLS_AES_128_GCM_SHA256
  ALPN: h2

TLS Certificate (тип 11):
  Subject: CN=*.example.com
  Issuer: CN=Let's Encrypt R3
  Valid until: 2026-08-15

Это очень полезно для troubleshooting TLS:

  • Wrong cert. Видно subject — сразу понятно, на правильный ли домен.
  • Old TLS version. Видны versions — если только TLS 1.0, надо обновлять.
  • No ALPN. HTTP/2 не работает потому что ALPN не negotiated.
  • Cipher mismatch. Клиент предлагает только AEAD ciphers, сервер только non-AEAD — handshake failed.

Capture filters vs Display filters

Важно понимать разницу:

  • Capture filters (tcpdump, или Wireshark на capture): применяются ДО записи. Только matching пакеты пишутся в pcap. Использует BPF-синтаксис (host, port, net, tcp/udp). Это уменьшает размер pcap.
  • Display filters (Wireshark, не tcpdump): применяются ПОСЛЕ записи, для отображения. Можно фильтровать по чему угодно (HTTP-заголовкам, TLS-полям). Использует Wireshark-синтаксис (http.host, tls.handshake.type).

Стратегия:

# Захватываем с capture filter, чтобы файл был не миллионы пакетов:
sudo tcpdump -nn -i eth0 'host api.example.com' -w /tmp/api.pcap

# В Wireshark открываем и применяем display filter для precise search:
# Filter: http.response.code >= 400

Найти медленные запросы

В Wireshark есть встроенная аналитика — Statistics > Conversations показывает все TCP-соединения, время, объём, latency.

Через tcpdump можно тоже — но сложнее:

# Захват с timestamps:
sudo tcpdump -tttt -i eth0 'host api.example.com' -w /tmp/api.pcap

# Поиск самых медленных GET-ответов:
tcpdump -nn -r /tmp/api.pcap 'tcp[tcpflags] & tcp-push != 0' | head

# Wireshark:
# Statistics -> HTTP -> Requests
# или: tcp.analysis.flags == 1  # ретрансмиты
# или: tcp.analysis.duplicate_ack

Безопасность и приватность capture

tcpdump и Wireshark показывают сырой трафик. Если этот трафик содержит чувствительные данные (пароли в plain HTTP, токены в headers), они окажутся в pcap-файле и в любом, кто его получит.

Best practices:

  1. Не сохраняйте pcap-файлы с production-трафиком в shared storage.
  2. Удаляйте после анализа. shred -u file.pcap.
  3. Анонимизируйте перед отправкой support. Tools: tcprewrite, tcpprep, pcap-rewrite.
  4. Используйте capture filters. not port 22 (не захватывать вашу SSH-сессию — хотя она и зашифрована).
  5. На corporate-серверах — только с разрешения security.

Анализ DNS в Wireshark

Wireshark — идеален для DNS-проблем:

# В фильтре:
dns

# Видно:
14:30:45.123  Standard query 0x1234 A google.com
14:30:45.156  Standard query response 0x1234 A google.com A 142.250.74.110

Дальше можно:

  • Видеть, какие DNS-запросы делает ваше приложение.
  • Считать latency DNS.
  • Найти, какие имена не разрешаются (видны Server failure ответы).
  • Видеть, какой именно resolver используется (по IP в IP-заголовке).
# Через tcpdump:
sudo tcpdump -nn -i any 'port 53' -A
# или для прицельного debug:
sudo tcpdump -nn -i any 'port 53 and udp' -w /tmp/dns.pcap

Попробуй сам

Серия экспериментов:

# 1. Захватить весь handshake одного HTTPS-запроса:
sudo tcpdump -nn -i any 'host api.github.com and port 443' -w /tmp/github.pcap &
sleep 1
curl https://api.github.com/users/torvalds
sleep 1
sudo killall tcpdump  # остановить

# Прочитать:
tcpdump -nn -r /tmp/github.pcap | head -30
# Видим: DNS resolve, SYN, SYN-ACK, ACK, TLS Client Hello, Server Hello, ...

# 2. Захват DNS-резолва:
sudo tcpdump -nn -A -i any 'port 53' &
sleep 1
dig google.com
sleep 1
sudo killall tcpdump
# Видны DNS query и response в текстовом виде

# 3. Захват ARP (только в LAN):
sudo tcpdump -nn -i en0 arp
# В другом терминале:
ping 192.168.1.100  # пингуйте IP, которого нет в ARP-таблице
# Видно: ARP Request "Who has 192.168.1.100?"

# 4. Захват только SYN-пакетов (для детекции SYN flood или сканирования):
sudo tcpdump -nn -i any 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack = 0' -c 20
# Это все начала TCP-соединений

# 5. Захват для последующего Wireshark:
sudo tcpdump -nn -i any 'host github.com' -w /tmp/wireshark-test.pcap -G 10  # 10 секунд
# Скачайте Wireshark и откройте файл:
# brew install --cask wireshark  # на macOS
# wireshark /tmp/wireshark-test.pcap

Из Wireshark поэкспериментируйте с display filters:

# В фильтр-баре:
http.request.method == "GET"
http.response.code >= 400
tls.handshake.type == 1
dns.qry.name contains "google"
tcp.analysis.retransmission
tcp.flags.syn == 1 and tcp.flags.ack == 0

Используйте Statistics меню для built-in analytics: conversations, endpoints, HTTP stats.


tcpdump BPF-фильтры: precision capture без 50GB pcap-файлов
Проверка знанийKnowledge check
Junior спрашивает: 'Я запустил tcpdump -i eth0 на production-сервере, и за 10 минут pcap-файл стал 50GB. Это нормально? Как ловить только нужные пакеты?'
ОтветAnswer
Это нормальный объём для активного production-сервера и в то же время неподходящий подход. 50GB за 10 минут -- это около 5GB/мин или ~85MB/sec -- характеристики реального production-трафика на средне-нагруженном сервере. Захват ВСЕГО трафика в pcap-файл -- почти всегда неправильное решение. Главная проблема -- размер. Объёмные pcap-файлы трудно открыть в Wireshark (он попытается загрузить всё в память), невозможно отправить в support, проблематично хранить. Решение -- использовать capture filters при tcpdump. Это BPF-фильтр, применяемый ядром ДО того, как пакеты пишутся в файл. Нерелевантные пакеты дропаются и не попадают в pcap. Это в ОТЛИЧИЕ от display filters в Wireshark, которые применяются после захвата. Стратегии сужения захвата: Первая -- фильтр по host. Если диагностируете проблему с конкретным клиентом или сервером: -i eth0 'host 1.2.3.4'. Сразу убирает 99% шума. Вторая -- по port. Если проблема с конкретным сервисом: 'tcp port 443'. Тоже мощное сужение. Третья -- комбинации: 'host api.example.com and port 443 and tcp'. Четвёртая -- по протоколу: только DNS (port 53), только ICMP, только ARP -- в зависимости от типа проблемы. Пятая -- по типу пакета. Только handshake: 'tcp[tcpflags] & tcp-syn != 0'. Только resets: 'tcp[tcpflags] & tcp-rst != 0'. Это для специфических проблем. Шестая -- лимит времени и размера. -G 60 -W 5 -- разбивать на файлы по 60 секунд, держать только 5 последних (циркулярный буфер). Удобно для 'захват в фоне до момента проблемы'. Седьмая -- -s N -- snap length, длина snapshot пакета. -s 96 захватывает только первые 96 байт каждого пакета (хватает на L2/L3/L4 заголовки и начало L7). Это уменьшает pcap в десятки раз, но теряет application payload. В общем правило: tcpdump без фильтра -- только когда не знаете, что ищете, и на короткое время (-c 100 или -G 10).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. В tcpdump output вы видите 'Flags [S]', потом 'Flags [S.]', потом 'Flags [.]'. Что это значит?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5