В этом уроке разберем tcpdump в Linux от первого запуска до чтения вывода по полям. Будет много примеров tcpdump: как поймать конкретный хост, отфильтровать по порту, увидеть TCP-рукопожатие, поймать загадочный RST в ответе и записать дамп в файл для разбора в Wireshark. Утилита есть почти в любом дистрибутиве; если нет - ставится из пакета tcpdump (apt install tcpdump, dnf install tcpdump). На Astra Linux и RED OS все то же самое, утилита штатная. Актуально на 2026: стабильная ветка - tcpdump 4.99.x (последний релиз 4.99.6, конец 2025), ветка 5.0 еще в разработке, так что весь синтаксис ниже - это то, что у вас реально стоит в проде.
Как это работает и с чего начать в tcpdump linux
tcpdump просит ядро отдавать ему копии пакетов, проходящих через сетевой интерфейс. Технически это работает через AF_PACKET-сокет и кольцевой буфер в ядре, а отбор лишнего идет уже там, до того как пакет попадет в userspace. Поэтому почти всегда нужен root - обычный пользователь не имеет права слушать сырой трафик. Запускай через sudo.
Тонкость на 2026: вместо полного root правильнее выдать бинарю только нужные права через capabilities (CAP_NET_RAW и CAP_NET_ADMIN). Тогда tcpdump сможет ловить пакеты без полного sudo:
Код: Выделить всё
sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdumpКод: Выделить всё
sudo tcpdump -DКод: Выделить всё
sudo tcpdump -n -i eth0Хочешь поймать любой активный интерфейс сразу - используй -i any. Удобно, когда не уверен, через какой интерфейс пойдет трафик (например, трафик контейнера может уходить через veth/docker0, а не через физический eth0). Учти: на -i any пакеты идут в режиме без точной L2-привязки, и фильтры по VLAN там работают иначе - для тонкого L2-разбора лови на конкретном интерфейсе.
Вывод бесконечный, останавливается по Ctrl+C. После остановки tcpdump печатает строку статистики вида packets captured / received by filter / dropped by kernel. Колонка dropped by kernel - первое, на что смотреть: если она не ноль, ядро не успевало отдавать пакеты и часть ты потерял (значит, фильтруй жестче или пиши в файл). Чтобы взять, скажем, только первые 20 пакетов и выйти:
Код: Выделить всё
sudo tcpdump -n -i eth0 -c 20
Фильтры BPF: host, port, src и dst - сердце tcpdump
Без фильтра ты утонешь в трафике. Сила tcpdump - в фильтрах BPF (Berkeley Packet Filter). Это маленький язык выражений, который пишут прямо в конце команды. Ядро отсеивает ненужное еще до того, как пакет дойдет до утилиты, - это и быстро, и экономит ту самую колонку dropped.
Базовые кирпичики:
- host - трафик к адресу и от него: host 10.0.0.5
- src / dst - только источник или только назначение: src host 10.0.0.5
- port - по номеру порта (и TCP, и UDP): port 443
- portrange - диапазон портов: portrange 8000-8100
- net - целая подсеть: net 192.168.1.0/24
- tcp / udp / icmp - по протоколу
Код: Выделить всё
# весь обмен с конкретным IP
sudo tcpdump -n host 10.0.0.5
# только HTTPS-трафик к этому хосту
sudo tcpdump -n host 10.0.0.5 and port 443
# пакеты, ИДУЩИЕ на наш веб-сервер (мы - назначение)
sudo tcpdump -n dst host 10.0.0.5 and dst port 443
# вся подсеть, кроме SSH-шума (чтобы не видеть свою же сессию)
sudo tcpdump -n net 192.168.1.0/24 and not port 22Код: Выделить всё
sudo tcpdump -nn -i any udp port 53Важная тонкость для новичка: если в фильтре есть скобки, вертикальные черточки, амперсанд или пробелы со спецсимволами, заключай все выражение в одинарные кавычки, иначе shell его покалечит еще до запуска tcpdump.
Читаем вывод: TCP-рукопожатие, флаги и ретрансмиты
Главный навык - не запустить tcpdump, а ПРОЧИТАТЬ его вывод. Разберем строку по полям:
Код: Выделить всё
10:21:33.512345 IP 10.0.0.5.51512 > 93.184.216.34.443: Flags [S], seq 12345, win 64240, options [mss 1460,sackOK,TS val 9 ecr 0,nop,wscale 7], length 0- 10:21:33.512345 - время с микросекундами. По задержкам между строками видно тормоза (например, секунда тишины перед повтором).
- IP - протокол сетевого уровня (был бы IP6 для IPv6).
- 10.0.0.5.51512 > 93.184.216.34.443 - кто кому. Формат адрес.порт, стрелка > показывает направление. Тут наш клиент с эфемерного порта 51512 стучится на 443 (HTTPS) удаленного хоста.
- Flags [S] - флаги TCP. Это самое полезное поле.
- seq - номер последовательности (в свежих версиях по умолчанию относительный), win - размер окна приема, options - опции (mss, окно масштабирования wscale, метки времени TS), length - объем полезных данных в пакете.
- [S] - SYN, запрос на установку соединения
- [S.] - SYN+ACK, сервер согласен (точка означает выставленный бит ACK)
- [.] - чистый ACK, подтверждение
- [P.] - PSH+ACK, передача данных с просьбой не буферизовать
- [F.] - FIN+ACK, корректное закрытие половины соединения
- [R] или [R.] - RST, грубый сброс соединения
А теперь типовые диагнозы по выводу. Отбирать по флагам удобнее всего именованным синтаксисом tcp[tcpflags] - он читается человеком, в отличие от голых битовых масок.
Соединение не открывается, в ответ RST. Клиент шлет [S], а сервер тут же отвечает [R.]. Поймаем только установки и сбросы к хосту:
Код: Выделить всё
sudo tcpdump -n 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0 and host 10.0.0.5'Клиент шлет SYN, а ответа вообще нет. Видишь только повторяющиеся [S] от клиента с растущими интервалами (примерно 1с, 2с, 4с) - это ретрансмиты SYN. Пакеты уходят в пустоту: их молча дропает фаервол (drop, а не reject) или ломается маршрут. Тут смотри уже на стороне сети и правил nftables/iptables, на маршруты (ip route get <ip>) и на MTU.
Поймать все попытки открыть соединение (чистый SYN без ACK) на сервере - проверенный синтаксис:
Код: Выделить всё
sudo tcpdump -n 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'Чтобы увидеть содержимое пакетов, а не только заголовки, есть -A (печать в ASCII) и -X (hex + ASCII рядом). Для plaintext-протоколов это золото - видно сырой HTTP-запрос с методом, путем и заголовками:
Код: Выделить всё
sudo tcpdump -nn -A -i eth0 'tcp port 80'Запись в файл и разбор в Wireshark
В консоли удобно смотреть на лету, но для серьезного разбора пиши дамп в файл формата pcap:
Код: Выделить всё
sudo tcpdump -n -i eth0 -w cap.pcap 'host 10.0.0.5 and port 443'Код: Выделить всё
tcpdump -n -r cap.pcapКод: Выделить всё
sudo tcpdump -n -i eth0 -w cap.pcap -C 100 -W 5 'host 10.0.0.5'Грабли, заблуждения и нагрузка
- Забыл -n. Самая частая ошибка новичка: тормоза, лишний DNS-трафик в собственном дампе, а на сломанном резолвере - подвисание.
- Слушаешь не тот интерфейс. Трафик идет через docker0/veth или eth1, а ты сидишь на eth0 и видишь пустоту. В сомнениях бери -i any и фильтр по хосту.
- Фильтр без кавычек. Выражение со скобками, амперсандом и | shell разберет по-своему. Бери в одинарные кавычки.
- Сам себя видишь. Твоя SSH-сессия - тоже трафик. Исключай ее: and not port 22, иначе утонешь в собственном эхе и можешь устроить петлю обратной связи (вывод порождает трафик, который ты же ловишь).
- Путаешь BPF-фильтр и фильтр Wireshark. У tcpdump синтаксис захвата (capture filter, BPF): host, port, and. У Wireshark в строке поиска - другой, display-фильтр: ip.addr ==, tcp.port ==. Не мешай их.
- Нагрузка и dropped by kernel. На гигабитном линке без фильтра tcpdump способен прилично нагрузить CPU и забить диск при записи, а ядро начнет дропать пакеты (та самая статистика на выходе). Всегда сужай фильтром, ставь -c или ротацию, при записи в файл предпочитай -w (это дешевле, чем форматировать вывод на экран).
- Утечка секретов. Дамп с -A или полный pcap может содержать пароли, токены и куки из plaintext-трафика. Храни pcap-файлы как секреты, не клади в общий /tmp и удаляй после разбора.
Мини-лаба: повтори руками прямо сейчас
- Запусти sudo tcpdump -n -i any -c 20 и посмотри живой трафик. Найди в нем хотя бы одну тройку [S], [S.], [.]. На выходе глянь строку статистики - есть ли dropped by kernel.
- В одном терминале запусти sudo tcpdump -nn -i any 'tcp port 80', в другом дай curl http://example.com. Поймай рукопожатие и добавь -A, чтобы увидеть GET-запрос и заголовки.
- Постучись на заведомо закрытый порт: curl http://127.0.0.1:9999, параллельно слушая sudo tcpdump -n -i lo 'tcp[tcpflags] & tcp-rst != 0'. Найди RST в ответе.
- Запиши минутный дамп в файл с -w 'host 8.8.8.8', параллельно сделав ping 8.8.8.8, открой файл через -r, а если есть Wireshark - загляни в Statistics и Follow Stream.
- Зачем почти всегда нужен флаг -n (и -nn) и что он отключает?
- Чем отличаются фильтры host, src host и dst host?
- Какие три пакета составляют здоровое TCP-рукопожатие и как они выглядят в выводе по флагам?
- О чем говорит RST ([R.]) сразу в ответ на SYN, и чем диагностически отличается случай, когда на SYN вообще нет ответа?
tcpdump показывает реальный трафик и снимает гадание в сетевой диагностике. Рефлекс запуска: sudo tcpdump -nn -i <интерфейс> и обязательно фильтр (host, port, src/dst, tcp/udp), соединенный через and/not, в одинарных кавычках. Читай флаги: [S] и [S.] - соединение устанавливается, [R.] на SYN - порт закрыт или reject, повторяющиеся [S] без ответа - тихий drop где-то по пути. Для глубокого разбора пиши в файл через -w (с ротацией -C/-W на долгих захватах) и открывай pcap в Wireshark. Следи за dropped by kernel, фильтруй узко, убирай дампы за собой - в них бывают секреты. А когда tcpdump уперся в "что творится внутри ядра", бери eBPF-инструменты pwru и ptcpdump - это правильное продолжение на 2026.