tcpdump: 20 примеров для диагностики сайта
Логи nginx молчат, curl висит, пользователи жалуются. Единственный честный свидетель в этот момент — трафик на сетевой карте. Двадцать рабочих команд tcpdump: от «кто ко мне стучится» до ретрансмитов, TLS-алертов, NXDOMAIN и записи с ротацией. Сверено с man tcpdump и man pcap-filter на сентябрь 2026.
tcpdump — консольный анализатор сетевого трафика: он перехватывает пакеты с сетевого интерфейса, отбирает нужные по фильтру BPF и печатает их заголовки либо сохраняет в pcap-файл. Работает в Linux, macOS и BSD, требует прав root или capability cap_net_raw; на Windows его нет — там используют встроенный pktmon или Wireshark с Npcap.
Как установить tcpdump и без чего он не запустится
На серверных дистрибутивах tcpdump обычно уже стоит, в минимальных образах и контейнерах — нет. Актуальная стабильная версия на сентябрь 2026 — tcpdump 4.99.6 (30 декабря 2025) поверх libpcap 1.10.7 (5 сентября 2026); версия 5.0 в разработке.
| Система | Установка | Права на захват |
|---|---|---|
| Debian, Ubuntu | apt install tcpdump | sudo или setcap |
| RHEL, Alma, Rocky, Fedora | dnf install tcpdump | sudo или setcap |
| Alpine, контейнеры | apk add tcpdump | Контейнеру нужен CAP_NET_RAW |
| macOS | предустановлен; brew install tcpdump — свежее | sudo или доступ к /dev/bpf* |
| Windows 10/11, Server 2019+ | tcpdump нет. pktmon встроен; Wireshark + Npcap даёт tshark | Администратор |
| WSL2 | apt install tcpdump внутри WSL | Видит только виртуальный интерфейс WSL |
# Linux: захват без sudo для конкретного бинарника sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdump # Windows: встроенный pktmon, от администратора pktmon filter add -p 443 pktmon start -c --comp nics pktmon stop pktmon etl2pcap PktMon.etl --out capture.pcapng # открыть в Wireshark
Ловушка в Debian и Ubuntu: после открытия интерфейса tcpdump сбрасывает привилегии до пользователя tcpdump (поведение ключа -Z, включённое при сборке). Поэтому -w /root/dump.pcap падает с «Permission denied» даже под sudo. Пишите в /var/tmp или укажите -Z root.
Ключи tcpdump, которых хватает в 95% случаев
Базовая связка — -i any -nn: все интерфейсы, без резолва имён и портов. Остальное добавляется по задаче.
| Ключ | Что делает |
|---|---|
| -i eth0 / -i any | Интерфейс. Без ключа — первый поднятый не-loopback; any — все сразу, без promiscuous-режима |
| -D | Список интерфейсов для захвата |
| -n / -nn | Не резолвить адреса / адреса и порты. Без -n каждый пакет порождает DNS-запрос |
| -c N | Выйти после N пакетов |
| -w файл / -r файл | Записать pcap / прочитать. С -w на экран ничего не идёт, если не добавить --print |
| -s N | Snaplen, байт на пакет. По умолчанию 262144, -s 0 — то же самое; -s 128 оставит только заголовки |
| -v / -vv / -vvv | Подробнее: TTL, id, длина IP, контрольные суммы, детали DNS |
| -A / -X | Нагрузка в ASCII (HTTP) / hex + ASCII (TLS, FastCGI) |
| -tttt / -ttt | Время с датой / дельта от предыдущей строки — для замера задержек |
| -e | MAC-адреса, ethertype и полная длина кадра |
| -q | Короткие строки: без seq, ack и опций |
| -l | Построчная буферизация. Обязателен перед | grep |
| -G сек / -W N / -C МБ | Ротация по времени / лимит числа файлов / ротация по размеру |
| -Z user | Сбросить привилегии до user после открытия интерфейса |
| -S / -B КиБ | Абсолютные seq / размер буфера ядра, если есть «dropped by kernel» |
Базовые примеры: интерфейс, хост, порт, подсеть
Первые четыре команды отвечают на вопрос «что происходит на сервере прямо сейчас» и служат заготовками для остальных фильтров.
1. Найти интерфейс и убедиться, что захват работает.
sudo tcpdump -D sudo tcpdump -i any -nn -c 5 # пример вывода 1.eth0 [Up, Running, Connected] 2.any (Pseudo-device that captures on all interfaces) [Up, Running] 3.lo [Up, Running, Loopback]
Что видим: интерфейсы и их состояние. За облачным балансировщиком внешний адрес может жить не на том интерфейсе, что вы думаете, поэтому первая проба всегда с -i any, а дальше сужаем.
2. Фильтр по IP: всё, что связано с конкретным клиентом.
sudo tcpdump -i eth0 -nn host 203.0.113.7 # в обе стороны sudo tcpdump -i eth0 -nn src host 203.0.113.7 # только от него # пример вывода 12:41:03.118204 IP 203.0.113.7.51214 > 198.51.100.10.443: Flags [S], seq 3814292745, win 64240, options [mss 1460,sackOK,wscale 7], length 0 12:41:03.118251 IP 198.51.100.10.443 > 203.0.113.7.51214: Flags [S.], seq 1289473102, ack 3814292746, win 65160, options [mss 1460,sackOK,wscale 7], length 0 12:41:03.146920 IP 203.0.113.7.51214 > 198.51.100.10.443: Flags [.], ack 1, win 502, length 0
Что видим: полное рукопожатие. Флаги: S — SYN, S. — SYN-ACK (точка означает ACK), . — чистый ACK, P — PUSH, F — FIN, R — RST. Разница между первой и третьей строкой — 28,7 мс — это RTT до клиента.
3. Веб-трафик на 80 и 443, коротко.
sudo tcpdump -i eth0 -nn -q 'port 80 or port 443' # пример вывода 12:42:10.004811 IP 203.0.113.7.51220 > 198.51.100.10.443: tcp 517 12:42:10.005390 IP 198.51.100.10.443 > 203.0.113.7.51220: tcp 0 12:42:10.011702 IP 198.51.100.10.443 > 203.0.113.7.51220: tcp 1460
Что видим: с -q остаются адреса и длина нагрузки. 517 байт от клиента на 443 — типичный размер TLS ClientHello, 1460 в ответ — сервер шлёт максимальный сегмент.
4. Подсеть /24 и кто стучится чаще всех.
sudo tcpdump -i eth0 -nn net 203.0.113.0/24
sudo tcpdump -i eth0 -nn -l -c 2000 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' 2>/dev/null \
| awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -5
# пример вывода
812 203.0.113.55
97 198.51.100.23
Что видим: из 2000 входящих SYN 812 пришли с одного адреса — агрессивный бот или клиент в цикле переподключений. Ключ -l отдаёт вывод в конвейер построчно, а не порциями.
TCP-рукопожатие: SYN без ответа, RST и ретрансмиты
Три картины ниже покрывают почти все «сайт не открывается» на уровне TCP. По curl их не различить, по tcpdump — за минуту.
5. SYN приходит, SYN-ACK не уходит.
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0' # пример вывода 09:12:40.001732 IP 203.0.113.7.40122 > 198.51.100.10.8443: Flags [S], seq 2210441193, win 64240, length 0 09:12:41.020119 IP 203.0.113.7.40122 > 198.51.100.10.8443: Flags [S], seq 2210441193, win 64240, length 0 09:12:43.064205 IP 203.0.113.7.40122 > 198.51.100.10.8443: Flags [S], seq 2210441193, win 64240, length 0
Что видим: тот же SYN с тем же seq повторяется через 1 и 2 секунды, ответа [S.] нет. Это не «никто не слушает» — тогда ядро ответило бы RST, — а DROP в файрволе или переполненный SYN-backlog. Слушателя и очередь смотрим в статье про ss и состояния TCP.
6. В ответ прилетает RST.
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-rst) != 0' # пример вывода 09:15:02.410077 IP 198.51.100.10.8080 > 203.0.113.7.40130: Flags [R.], seq 0, ack 2210441194, win 0, length 0 09:15:02.410120 IP 198.51.100.10.8080 > 203.0.113.7.40131: Flags [R.], seq 0, ack 3390012011, win 0, length 0
Что видим: RST с win 0 и ack = seq клиента + 1 — ответ ядра на SYN в порт, где никто не слушает; у клиента это ERR_CONNECTION_REFUSED. RST посреди установленного соединения — другая история, разобрана в статье про ERR_CONNECTION_RESET.
7. Ретрансмиты: сервер отдаёт, клиент не подтверждает.
sudo tcpdump -i eth0 -nn -ttt -S host 203.0.113.7 and port 443 # пример вывода 00:00:00.000000 IP 198.51.100.10.443 > 203.0.113.7.51214: Flags [P.], seq 1289473103:1289474563, ack 3814293263, win 509, length 1460 00:00:00.212418 IP 198.51.100.10.443 > 203.0.113.7.51214: Flags [P.], seq 1289473103:1289474563, ack 3814293263, win 509, length 1460 00:00:00.428009 IP 198.51.100.10.443 > 203.0.113.7.51214: Flags [P.], seq 1289473103:1289474563, ack 3814293263, win 509, length 1460
Что видим: tcpdump не помечает ретрансмиты словом — их выдаёт одинаковый диапазон seq и растущие интервалы 0,2 → 0,4 с (минимальный RTO в Linux 200 мс, дальше удвоение). Если повторяются только сегменты по 1460 байт, а мелкие проходят — это проблема MTU на пути.
HTTP: запросы, коды ответов и время до ответа
Открытый HTTP на 80-м порту виден целиком, и это удобно для проверки того, что происходит между TLS-терминацией и приложением. Фильтр по нагрузке отбирает нужные пакеты ещё в ядре.
8. Только GET и HEAD, с заголовками.
sudo tcpdump -i any -nn -A 'tcp port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420' # "GET " sudo tcpdump -i any -nn -A 'tcp port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48454144' # "HEAD" # пример вывода 14:10:22.301512 IP 203.0.113.7.52310 > 198.51.100.10.80: Flags [P.], seq 1:79, ack 1, win 502, length 78: HTTP: GET /catalog/ HTTP/1.1 GET /catalog/ HTTP/1.1 Host: example.ru User-Agent: curl/8.5.0
Что видим: выражение (tcp[12:1] & 0xf0) >> 2 вычисляет длину TCP-заголовка, а следующие 4 байта сравниваются с ASCII-кодами «GET » (0x47 0x45 0x54 0x20); для POST — 0x504f5354. ACK и куски тел ответов в вывод не попадают.
9. Коды ответов: кто отдаёт 5xx.
sudo tcpdump -i any -nn -l -A 'tcp src port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48545450' | grep -a --line-buffered '^HTTP/' # пример вывода HTTP/1.1 200 OK HTTP/1.1 502 Bad Gateway HTTP/1.1 504 Gateway Time-out
Что видим: 0x48545450 — «HTTP», начало любой строки статуса. Если 502 идут с 127.0.0.1:80 на lo, а снаружи на 443 всё зелёное, виноват апстрим за nginx, а не сеть.
10. Сколько сервер думает над ответом.
sudo tcpdump -i any -nn -ttt -q 'port 80 and host 203.0.113.7' # пример вывода 00:00:00.000000 IP 203.0.113.7.52310 > 198.51.100.10.80: tcp 78 00:00:00.000041 IP 198.51.100.10.80 > 203.0.113.7.52310: tcp 0 00:00:02.814371 IP 198.51.100.10.80 > 203.0.113.7.52310: tcp 311
Что видим: ACK на запрос ушёл через 41 мкс — это ядро, сеть в порядке. Первый байт ответа — через 2,81 с, и это уже приложение: база, внешний API или очередь воркеров. Замер честнее TTFB у curl, потому что исключает сеть до клиента.
TLS: ClientHello, SNI и алерты
Содержимое HTTPS tcpdump не расшифрует и TLS-записи не декодирует, но структура рукопожатия видна по первым байтам. Этого хватает, чтобы понять, доходит ли ClientHello и чем отвечает сервер.
11. Поймать ClientHello и прочитать SNI.
# байт 0 нагрузки = 0x16 (handshake), байт 5 = 0x01 (ClientHello)
sudo tcpdump -i eth0 -nn -X 'tcp dst port 443 and tcp[((tcp[12] & 0xf0) >> 2)] = 0x16 and tcp[((tcp[12] & 0xf0) >> 2)+5] = 0x01'
# пример вывода
15:01:07.220314 IP 203.0.113.7.51230 > 198.51.100.10.443: Flags [P.], seq 1:518, ack 1, win 502, length 517
0x0040: 1603 0102 0001 0001 fc03 03a1 9c2e 4b10 ..............K.
0x00b0: 0000 0f00 0d00 000a 6578 616d 706c 652e ........example.
# то же с готовым декодером
tshark -i eth0 -Y 'tls.handshake.type == 1' -T fields -e ip.src -e tls.handshake.extensions_server_name
Что видим: 16 03 01 — TLS-запись типа handshake, затем 01 — ClientHello; в ASCII-колонке читается имя хоста из расширения SNI. Фильтр опирается на фиксированную структуру записи по RFC 5246 и работает для TLS 1.3 тоже — ClientHello там не шифруется. Для регулярного разбора удобнее tshark: он отдаёт SNI одним полем.
12. TLS alert: рукопожатие оборвалось.
sudo tcpdump -i eth0 -nn -X 'tcp port 443 and tcp[((tcp[12] & 0xf0) >> 2)] = 0x15'
# пример вывода
15:02:41.907550 IP 198.51.100.10.443 > 203.0.113.7.51233: Flags [P.], seq 1:8, ack 518, win 509, length 7
0x0034: 1503 0300 0202 28 ......(
Что видим: 0x15 — запись alert, 02 — fatal, 28 — код 40, handshake_failure. Другие частые коды: 46 certificate_unknown, 48 unknown_ca, 112 unrecognized_name — нет сертификата под запрошенный SNI. В TLS 1.2 алерты идут открыто; в TLS 1.3 после ServerHello они зашифрованы, но 7-байтовый пакет и его отправитель всё равно видны.
DNS: запросы, NXDOMAIN и время ответа резолвера
DNS tcpdump декодирует полностью: id запроса, тип записи, ответ и коды ошибок. Это самый быстрый способ понять, тормозит ли сайт из-за резолвера.
13. Все DNS-запросы с сервера и ответы на них.
sudo tcpdump -i any -nn port 53 # пример вывода 16:20:11.512345 IP 198.51.100.10.44121 > 8.8.8.8.53: 51823+ A? api.example.ru. (32) 16:20:11.531902 IP 8.8.8.8.53 > 198.51.100.10.44121: 51823 1/0/0 A 192.0.2.44 (48) 16:20:11.532210 IP 198.51.100.10.44122 > 8.8.8.8.53: 51824+ AAAA? api.example.ru. (32)
Что видим: 51823+ — id запроса и флаг рекурсии, A? — тип, в ответе 1/0/0 — число записей в секциях answer/authority/additional. Если приложение на каждый вызов API делает A и AAAA и ждёт оба — это лишние миллисекунды на каждый запрос.
14. Ловим NXDOMAIN и SERVFAIL.
sudo tcpdump -i any -nn -l 'udp src port 53' | grep -E --line-buffered 'NXDomain|ServFail|Refused' # пример вывода 16:22:03.114509 IP 8.8.8.8.53 > 198.51.100.10.44140: 51902 NXDomain 0/1/0 (98) 16:22:03.115877 IP 8.8.8.8.53 > 198.51.100.10.44141: 51903 NXDomain 0/1/0 (98)
Что видим: NXDomain с 0 ответов и одной записью SOA в authority. По id запроса находим имя — чаще всего опечатка в конфиге или домен, который перестали делегировать. ServFail — проблема резолвера или авторитетных серверов зоны.
15. Сколько отвечает резолвер.
sudo tcpdump -i any -nn -ttt port 53 # пример вывода 00:00:00.000000 IP 198.51.100.10.44150 > 10.0.0.2.53: 52011+ A? cdn.example.ru. (32) 00:00:04.998871 IP 198.51.100.10.44150 > 10.0.0.2.53: 52011+ A? cdn.example.ru. (32) 00:00:00.019402 IP 10.0.0.2.53 > 198.51.100.10.44150: 52011 2/0/0 A 192.0.2.60, A 192.0.2.61 (64)
Что видим: первый запрос без ответа, через 5 секунд (таймаут resolv.conf по умолчанию) — повтор с тем же id, ответ на него за 19 мс. Для пользователя это 5 секунд ожидания на ровном месте: первый резолвер в списке теряет пакеты.
ICMP: ping, unreachable и «fragmentation needed»
ICMP — служебные сообщения сети о том, что пошло не так. Их часто режут файрволами, и тогда TCP ломается тихо: без сообщения о нужной фрагментации соединение зависает на больших пакетах.
16. Доходит ли ping и отвечаем ли мы.
sudo tcpdump -i eth0 -nn 'icmp[icmptype] = icmp-echo or icmp[icmptype] = icmp-echoreply' # пример вывода 17:05:30.100211 IP 203.0.113.7 > 198.51.100.10: ICMP echo request, id 4211, seq 1, length 64 17:05:30.100240 IP 198.51.100.10 > 203.0.113.7: ICMP echo reply, id 4211, seq 1, length 64
Что видим: ответ через 29 мкс — сервер отвечает мгновенно. Если request есть, а reply нет — ICMP запрещён файрволом или sysctl icmp_echo_ignore_all; если нет даже request, пакеты режут до сервера.
17. Unreachable и need to frag.
sudo tcpdump -i eth0 -nn 'icmp[icmptype] = icmp-unreach' # пример вывода 17:08:12.410733 IP 10.20.0.1 > 198.51.100.10: ICMP 203.0.113.7 unreachable - need to frag (mtu 1400), length 36 17:09:40.220118 IP 192.0.2.1 > 198.51.100.10: ICMP host 192.0.2.77 unreachable - admin prohibited filter, length 36
Что видим: маршрутизатор 10.20.0.1 сообщает, что до 203.0.113.7 пролезают пакеты не больше 1400 байт, а мы шлём 1500 с флагом DF. Если такое сообщение приходит — Path MTU Discovery работает и ядро само уменьшит сегменты; если его фильтруют по пути, получаем ретрансмиты из примера 7. «Admin prohibited» — чужой файрвол явно отбросил наш пакет.
Запись дампа с ротацией и разбор в tshark
Проблема, которая случается «раз в час», ловится только записью в файл с ротацией: tcpdump пишет по кругу, а вы разбираете нужный фрагмент после инцидента.
18. Писать час по 10 минут и читать в tshark.
# новый файл каждые 600 с; вместе с -G ключ -W 6 завершит запись после 6 файлов sudo tcpdump -i eth0 -nn -s 128 -w '/var/tmp/web-%Y%m%d-%H%M.pcap' -G 600 -W 6 'port 443' # кольцевой буфер по размеру: 10 файлов по 100 МБ, старые перезаписываются sudo tcpdump -i eth0 -nn -s 128 -w /var/tmp/web.pcap -C 100 -W 10 'port 443' # пример вывода при остановке ^C48213 packets captured 48302 packets received by filter 89 packets dropped by kernel # разбор tshark -r /var/tmp/web-20260922-1410.pcap -Y 'tcp.analysis.retransmission' | wc -l tshark -r /var/tmp/web-20260922-1410.pcap -q -z io,stat,60
Что видим: 89 пакетов потеряло ядро — буфер не успевал, лечится -B 16384 и более узким фильтром. Snaplen 128 сохраняет заголовки Ethernet, IP и TCP с опциями, но обрезает тело: файлы в разы меньше и без персональных данных. tshark читает те же pcap и умеет то, чего нет в tcpdump: помечает ретрансмиты и считает статистику по интервалам.
Продвинутые фильтры: исключить лишнее, большие пакеты, PHP-FPM
Два приёма, без которых дамп на живом сервере не читается: убрать собственную SSH-сессию и смотреть локальный трафик между nginx и бэкендом отдельно.
19. Без своего SSH и только большие кадры.
sudo tcpdump -i eth0 -nn -e 'not port 22 and greater 1400' # пример вывода 18:11:05.774102 52:54:00:aa:bb:cc > c0:3f:d5:11:22:33, ethertype IPv4 (0x0800), length 1514: 198.51.100.10.443 > 203.0.113.7.51214: Flags [.], seq 1:1461, ack 1, win 509, length 1460 18:11:05.774180 52:54:00:aa:bb:cc > c0:3f:d5:11:22:33, ethertype IPv4 (0x0800), length 1514: 198.51.100.10.443 > 203.0.113.7.51214: Flags [.], seq 1461:2921, ack 1, win 509, length 1460
Что видим: кадры ровно по 1514 байт — 14 Ethernet + 20 IP + 20 TCP + 1460 данных. Если именно они не подтверждаются, а пакеты меньше 1400 проходят, диагноз — MTU. Без not port 22 дамп через SSH зациклится: каждая напечатанная строка порождает пакет, который тут же печатается.
20. Что nginx отправляет в PHP-FPM.
sudo tcpdump -i lo -nn -l -A port 9000 | grep -a --line-buffered -oE '(REQUEST_URI|SCRIPT_FILENAME|HTTP_HOST)[^ ]{1,80}'
# пример вывода
HTTP_HOSTexample.ru
SCRIPT_FILENAME/var/www/example.ru/public/index.php
REQUEST_URI/catalog/?page=3
Что видим: FastCGI передаёт параметры парами с двоичными длинами вместо разделителей, поэтому имя и значение склеены, но видно, тот ли SCRIPT_FILENAME уходит в PHP. Если PHP-FPM слушает unix-сокет (listen = /run/php/php8.3-fpm.sock), tcpdump не увидит ничего: unix-сокеты не проходят через сетевой стек. Тогда либо временно переключить на 127.0.0.1:9000, либо strace -f -e trace=network на воркер.
Какой фильтр брать под конкретный симптом
Сводная таблица: жалоба → команда → что должно быть в дампе. Номера в скобках — примеры выше.
| Симптом | Фильтр tcpdump | Что искать |
|---|---|---|
| Сайт «думает» и отваливается по таймауту | tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 | SYN есть, SYN-ACK нет → файрвол или backlog (5) |
| Connection refused | tcp[tcpflags] & tcp-rst != 0 | RST с win 0 на SYN → никто не слушает (6) |
| Открывается, но большие страницы виснут | -e greater 1400 / icmp-unreach | Повторы сегментов 1460, нет «need to frag» (7, 17, 19) |
| 502/504 у части запросов | tcp src port 80 and tcp[...:4] = 0x48545450 | Коды на lo от апстрима, паузы до ответа (9, 10) |
| Ошибка сертификата у части клиентов | tcp[...] = 0x16 и 0x15 на 443 | SNI в ClientHello, код alert (11, 12) |
| Первый запрос медленный, повторные быстрые | -ttt port 53 | Повтор запроса через 5 с, NXDomain (14, 15) |
| Подозрение на бота или DDoS | net X/24 + счётчик SYN по src | Один адрес с сотнями SYN (4) |
| Проблема повторяется раз в час | -w ... -G 600 -W 6 -s 128 | Разбор нужного файла в tshark (18) |
tcpdump, tshark, Wireshark или ss: что выбрать
Это четыре инструмента под разные вопросы. tcpdump — захват на сервере, tshark и Wireshark — разбор с полным декодированием, ss — состояние сокетов без захвата вообще.
| Критерий | tcpdump | tshark | Wireshark | ss |
|---|---|---|---|---|
| Что показывает | Пакеты, заголовки | Пакеты, полное декодирование | То же, графически | Сокеты и очереди |
| Где живёт | Любой Linux-сервер | Сервер, отдельный пакет | Рабочая станция | Любой Linux, iproute2 |
| Фильтры | BPF при захвате | BPF + display-фильтры по полям | Те же, что у tshark | Свои: state, dport, dst |
| Ретрансмиты | Глазами, по seq | tcp.analysis.retransmission | Expert Info | ss -ti: счётчик retrans |
| TLS SNI | Байтовый фильтр + -X | Отдельное поле | Декодируется | Нет |
| Нагрузка на сервер | Минимальная с -n и -w | Выше: декодирует каждый пакет | На сервере не запускают | Ничтожная |
| Windows | Нет; pktmon | Да, с Npcap | Да, с Npcap | Нет; netstat -ano |
Безопасность: что нельзя делать с дампами
Дамп трафика — это cookies, токены и персональные данные пользователей в открытом виде везде, где нет TLS. Правило одно: перехватывать только на своём сервере и хранить ровно столько, сколько нужно для разбора.
1. Снимать трафик только на серверах, которыми вы управляете, и только в рамках задачи. 2. По умолчанию резать нагрузку: для TCP-диагностики хватает -s 128, тела запросов туда не попадают. 3. Не пересылать pcap в мессенджеры и тикеты — в нём могут быть сессионные cookie и Authorization-заголовки; передавайте вывод tshark по нужным полям. 4. Удалять файлы после разбора и не оставлять tcpdump с -w работать «на всякий случай» неделями.
Чего tcpdump не покажет: доступность снаружи
tcpdump отвечает на вопрос «что сейчас происходит на сервере»: доходят ли пакеты и чем на них отвечает ядро. Он не отвечает на вопрос «виден ли сайт из Новосибирска» — там пакеты могут не доходить до вашей сетевой карты вовсе, их отбросит провайдер, магистральный маршрутизатор или фильтр у хостера.
Для второго вопроса нужен взгляд снаружи из нескольких точек. Проверка TCP-порта устанавливает соединение с внешних локаций и показывает, откуда рукопожатие проходит, а откуда нет — это пример 5 с другой стороны. HTTP-проверка получает страницу целиком и сравнивает код ответа и время с порогами, то есть закрывает примеры 9 и 10 без доступа к консоли.
Пруфен проверяет доступность порта и HTTP-ответ сайта с интервалом от 2 минут из 13 точек мониторинга — 11 в России, а также Минск и Испания — и присылает уведомление в Email, Telegram или Макс, когда сайт перестал отвечать; если ресурс так и не поднялся, подключается голосовой звонок. Результат виден по каждой точке отдельно, поэтому к консоли с tcpdump вы приходите уже зная, с какой стороны искать. Бесплатный план — 5 проверок.
Частые вопросы
Видит ли tcpdump содержимое HTTPS?
Нет. Он видит факт рукопожатия, SNI в ClientHello, размеры и тайминги записей, коды алертов в TLS 1.2 — но не URL, заголовки и тело. Расшифровать сессию можно только в Wireshark с ключами, сохранёнными на стороне клиента через SSLKEYLOGFILE; для чужих клиентов на сервере это невозможно. Для диагностики сайта обычно и не нужно: снимайте открытый HTTP на lo между nginx и приложением, как в примерах 9 и 10.
Почему tcpdump не показывает пакеты, хотя сайт работает?
По частоте: не тот интерфейс (запустите с -i any), трафик идёт через unix-сокет или внутри контейнера в другом сетевом namespace, включён -w без --print (пакеты уходят в файл, экран пуст), и наконец забытый -n — без него tcpdump тратит секунды на резолв имён и строки появляются с задержкой. Опечатка в фильтре обычно даёт ошибку синтаксиса сразу, а вот логически пустой фильтр tcpdump молча ждёт вечно.
Как захватить трафик внутри Docker-контейнера?
С хоста, не заходя в контейнер: узнайте PID через docker inspect -f '{{.State.Pid}}' имя и выполните sudo nsenter -t PID -n tcpdump -i eth0 -nn — tcpdump хоста окажется в сетевом namespace контейнера. Второй способ — захват на хосте с -i any: трафик контейнеров проходит через veth-интерфейсы и мост docker0. Если всё же ставите tcpdump в образ, контейнеру нужен --cap-add NET_RAW.
tcpdump грузит сервер?
Фильтр BPF исполняется в ядре, поэтому отбор пакетов стоит дёшево даже на гигабитном канале. Дорого то, что после: копирование каждого пакета в пользовательское пространство, резолв имён без -n, печать с -A или -v. Практика: узкий фильтр, -nn, запись через -w вместо экрана, snaplen 96–128. Если растёт «packets dropped by kernel», увеличьте буфер ключом -B — это не добавляет нагрузки, только полноты дампа.