Что такое tcpdump?

tcpdump — утилита командной строки для захвата и анализа сетевого трафика. Работает на основе библиотеки libpcap (Linux/macOS) или WinPcap/Npcap (Windows). Является стандартным инструментом в арсенале сетевого инженера и специалиста по ИБ.

Как работает tcpdump (libpcap)

1. Захват на уровне ядра

libpcap использует механизм BPF (Berkeley Packet Filter) — виртуальная машина в ядре ОС, которая фильтрует пакеты до передачи в пространство пользователя.

2. Promiscuous mode

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

3. Ring buffer

Пакеты помещаются в кольцевой буфер в памяти ядра, затем копируются в пространство пользователя для обработки tcpdump.

Требования: для захвата трафика обычно требуются права root (или CAP_NET_RAW на Linux). Используйте sudo tcpdump или добавьте пользователя в группу wireshark.

Установка tcpdump

Установка на разных ОС
# Ubuntu / Debian $ sudo apt update && sudo apt install -y tcpdump # RHEL / CentOS / Fedora $ sudo dnf install -y tcpdump # Arch Linux $ sudo pacman -S tcpdump # macOS (уже предустановлен, или через Homebrew) $ brew install tcpdump # Проверить версию $ tcpdump --version tcpdump version 4.99.4 libpcap version 1.10.4 (with TPACKET_V3) # Показать доступные интерфейсы $ sudo tcpdump -D 1.eth0 [Up, Running, Connected] 2.lo [Up, Running, Loopback] 3.any (Pseudo-device that captures on all interfaces) [Up, Running] 4.docker0 [Up, Running, Connected]
Разрешения без sudo: Чтобы запускать tcpdump без sudo, добавьте пользователя в группу wireshark (Debian/Ubuntu) или установите setuid-бит: sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump

Ключевые флаги и опции

Флаг Полная форма Описание Пример
-i --interface Интерфейс для захвата. any — все интерфейсы -i eth0
-n — Не разрешать IP-адреса в имена хостов (DNS lookup off) -n
-nn — Не разрешать ни хосты, ни порты (быстрее) -nn
-v --verbose Подробный вывод (TTL, ID, checksum и др.) -v
-vv — Более подробный вывод -vv
-vvv — Максимальная детализация -vvv
-w — Записать захваченные пакеты в файл .pcap -w capture.pcap
-r — Прочитать пакеты из файла .pcap -r capture.pcap
-c --count Остановиться после захвата N пакетов -c 100
-s --snapshot-length Длина захватываемых данных (snaplen). 0 = максимум -s 0
-A — Печатать пакет в ASCII (полезно для HTTP) -A
-X — Печатать пакет в HEX и ASCII -X
-e — Печатать заголовок Ethernet (MAC-адреса) -e
-t — Не печатать временну́ю метку -t
-tttt — Печатать дату и время в читаемом формате -tttt
-q — Тихий режим (краткий вывод) -q
-l — Построчная буферизация (для pipe в grep) -l | grep GET
-G — Ротация файлов каждые N секунд -G 3600
-C — Ротация файла при достижении размера N МБ -C 100
-p --no-promiscuous-mode Не переключать интерфейс в promiscuous mode -p

BPF-фильтры (Berkeley Packet Filter)

BPF-фильтры — выражения, задающие условие захвата пакетов. Фильтруются пакеты до передачи в пространство пользователя, что минимизирует нагрузку на систему. Фильтр задаётся в конце команды tcpdump (без флага).

Базовые примитивы

Примитив Описание Пример
host <IP>Любой трафик от/к хостуhost 192.168.1.1
src host <IP>Трафик от источникаsrc host 10.0.0.5
dst host <IP>Трафик к назначениюdst host 8.8.8.8
port <N>Трафик по порту (src или dst)port 80
src port <N>Трафик с порта источникаsrc port 443
dst port <N>Трафик на порт назначенияdst port 22
portrange <N>-<M>Диапазон портовportrange 8000-8080
net <IP/mask>Трафик от/к сетиnet 10.0.0.0/8
src net <сеть>Трафик из сети-источникаsrc net 192.168.0.0/16
dst net <сеть>Трафик в сеть назначенияdst net 172.16.0.0/12
tcpТолько TCP-трафикtcp
udpТолько UDP-трафикudp
icmpТолько ICMPicmp
arpТолько ARParp
ip6Только IPv6ip6
ether host <MAC>По MAC-адресуether host aa:bb:cc:dd:ee:ff
broadcastШироковещательный трафикether broadcast
multicastГрупповой трафикether multicast
len > NПакеты длиннее N байтlen > 1000

Логические операторы

ОператорСинонимыПример
and&&host 10.0.0.1 and port 80
or||port 80 or port 443
not!not port 22

TCP-флаги в BPF

Фильтрация по TCP-флагам
# Только SYN-пакеты (начало соединения) tcp[tcpflags] == tcp-syn # Или: 'tcp[13] & 2 != 0' # SYN-ACK (ответ сервера) 'tcp[13] & 18 == 18' # RST (сброс соединения) 'tcp[13] & 4 != 0' # FIN (завершение соединения) 'tcp[13] & 1 != 0' # URG | PSH (срочные данные) 'tcp[13] & 0x28 != 0' # Пакеты без флагов (NULL scan) 'tcp[13] == 0' # Все флаги установлены (XMAS scan) 'tcp[13] == 0x3f'

Практические примеры

Захват всего трафика на интерфейсе

Базовый захват
# Захват на eth0 без разрешения DNS $ sudo tcpdump -i eth0 -n # На любом интерфейсе с временными метками $ sudo tcpdump -i any -tttt -n # Первые 50 пакетов с подробным выводом $ sudo tcpdump -i eth0 -nn -v -c 50 # Полная длина пакетов (без обрезания) $ sudo tcpdump -i eth0 -nn -s 0

Захват HTTP-трафика (порт 80)

HTTP трафик
# Только HTTP (TCP 80) $ sudo tcpdump -i eth0 -nn tcp port 80 # HTTP + HTTPS $ sudo tcpdump -i eth0 -nn "tcp port 80 or tcp port 443" # Просмотр содержимого HTTP (ASCII) $ sudo tcpdump -i eth0 -nn -A port 80 # Только HTTP GET/POST запросы $ sudo tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' # Pipe в grep для поиска URL $ sudo tcpdump -i eth0 -l -A port 80 | grep -E 'GET|POST|Host:|User-Agent:' GET /api/login HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 (Linux; ...)

Захват DNS-запросов (порт 53)

DNS трафик
# Все DNS запросы и ответы $ sudo tcpdump -i eth0 -nn udp port 53 10:23:41.123456 IP 192.168.1.5.54321 > 8.8.8.8.53: 12345+ A? example.com. (29) 10:23:41.145678 IP 8.8.8.8.53 > 192.168.1.5.54321: 12345 1/0/0 A 93.184.216.34 (45) # DNS + TCP (zone transfers, большие ответы) $ sudo tcpdump -i eth0 -nn port 53 # Только DNS-запросы (от клиентов к серверу) $ sudo tcpdump -i eth0 -nn "udp dst port 53" # DNS к нестандартному резолверу (не 8.8.8.8 и не корпоративный) $ sudo tcpdump -i eth0 -nn "udp port 53 and not (dst host 8.8.8.8 or dst host 1.1.1.1)" # Обнаружение DNS tunneling (большие пакеты) $ sudo tcpdump -i eth0 -nn "udp port 53 and len > 100"

Захват ICMP (ping)

ICMP трафик
# Весь ICMP трафик $ sudo tcpdump -i eth0 -nn icmp 10:25:01.001234 IP 192.168.1.5 > 8.8.8.8: ICMP echo request, id 1234, seq 1, length 64 10:25:01.012345 IP 8.8.8.8 > 192.168.1.5: ICMP echo reply, id 1234, seq 1, length 64 # ICMP с большой нагрузкой (возможная утечка данных) $ sudo tcpdump -i eth0 -nn "icmp and len > 100" # Только echo request (тип 8) $ sudo tcpdump -i eth0 -nn "icmp[icmptype] == icmp-echo" # Только echo reply (тип 0) $ sudo tcpdump -i eth0 -nn "icmp[icmptype] == icmp-echoreply" # ICMP unreachable (ошибки доставки) $ sudo tcpdump -i eth0 -nn "icmp[icmptype] == icmp-unreach"

Трафик между двумя хостами

Фильтрация по парам хостов
# Трафик между двумя конкретными хостами $ sudo tcpdump -i eth0 -nn "host 192.168.1.5 and host 192.168.1.10" # Трафик от хоста A к хосту B (только в одну сторону) $ sudo tcpdump -i eth0 -nn "src host 192.168.1.5 and dst host 192.168.1.10" # Трафик подозрительного хоста исключая SSH (чтобы не захватывать свой сеанс) $ sudo tcpdump -i eth0 -nn "host 10.0.0.100 and not port 22" # Все соединения к/от подсети, кроме локального хоста $ sudo tcpdump -i eth0 -nn "net 10.0.0.0/24 and not host 10.0.0.1"

Сканирование портов и SYN-flood

Обнаружение сканирования
# Только SYN-пакеты (признак сканирования портов) $ sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn' # SYN без ACK (незавершённые соединения — half-open scan) $ sudo tcpdump -i eth0 -nn 'tcp[13] == 2' # RST-пакеты (порты недостижимы → закрытые порты) $ sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0' # NULL scan (все флаги = 0) $ sudo tcpdump -i eth0 -nn 'tcp[13] == 0' # XMAS scan (все флаги = 1) $ sudo tcpdump -i eth0 -nn 'tcp[13] == 0x3f'

SSH, FTP, Telnet трафик

Протоколы управления
# SSH трафик (зашифрован, но метаданные видны) $ sudo tcpdump -i eth0 -nn port 22 # Telnet (ОТКРЫТЫЙ ТЕКСТ — пароли видны!) $ sudo tcpdump -i eth0 -nn -A port 23 # FTP (логин и пароль в открытом виде!) $ sudo tcpdump -i eth0 -nn -A port 21 220 FTP server ready USER admin 331 Password required PASS secretpassword123 ← Пароль в открытом тексте!

🔴 ARP-трафик (ARP-spoofing)

ARP мониторинг
# Весь ARP трафик (с MAC-адресами) $ sudo tcpdump -i eth0 -nn -e arp 10:30:01 aa:bb:cc:11:22:33 > Broadcast, ARP, Request who-has 192.168.1.1 tell 192.168.1.5, length 28 10:30:01 dd:ee:ff:44:55:66 > aa:bb:cc:11:22:33, ARP, Reply 192.168.1.1 is-at dd:ee:ff:44:55:66 # Аномалия ARP spoofing: один IP отвечает несколькими MAC $ sudo tcpdump -i eth0 -nn -e arp | grep "Reply" 10:31:05 11:11:11:11:11:11 > ..., ARP, Reply 192.168.1.1 is-at 11:11:11:11:11:11 ← Легитимный 10:31:05 aa:aa:aa:aa:aa:aa > ..., ARP, Reply 192.168.1.1 is-at aa:aa:aa:aa:aa:aa ← ARP Spoofing!

Разбор вывода tcpdump

Анатомия строки вывода tcpdump
# Типичная строка вывода: 10:23:41.123456 IP 192.168.1.5.54321 > 8.8.8.8.443: Flags [S], seq 1234567890, win 65535, options [mss 1460,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0 Временная метка (HH:MM:SS.microseconds) Протокол (IP / ARP / IP6 / ICMP) IP источника + порт источника IP назначения + порт TCP флаги [S]=SYN [.]=ACK [P]=PSH [R]=RST [F]=FIN seq/ack номера, окно, опции длина полезных данных TIMESTAMP PROTO SRC.PORT > DST.PORT: FLAGS SEQUENCE OPTIONS LENGTH

Флаги TCP в выводе

ФлагЗначениеОписание
[S]SYNИнициация соединения
[S.]SYN-ACKПодтверждение инициации (сервер)
[.]ACKПодтверждение получения данных
[P.]PSH-ACKПередача данных (push)
[F.]FIN-ACKЗавершение соединения
[R]RSTСброс соединения
[R.]RST-ACKСброс с подтверждением

Пример: TCP-рукопожатие

3-way handshake в выводе tcpdump
$ sudo tcpdump -i eth0 -nn 'host 93.184.216.34 and tcp port 80' 10:40:01.001 IP 192.168.1.5.52345 > 93.184.216.34.80: Flags [S], seq 100, win 65535, length 0 10:40:01.050 IP 93.184.216.34.80 > 192.168.1.5.52345: Flags [S.], seq 200, ack 101, win 65535, length 0 10:40:01.051 IP 192.168.1.5.52345 > 93.184.216.34.80: Flags [.], ack 201, win 65535, length 0 ↑ SYN — клиент инициирует (шаг 1) ↑ SYN-ACK — сервер отвечает (шаг 2) ↑ ACK — клиент подтверждает (шаг 3) → соединение установлено 10:40:01.052 IP 192.168.1.5.52345 > 93.184.216.34.80: Flags [P.], seq 101:182, ack 201, length 81 ↑ PSH — данные (HTTP GET запрос) 10:40:01.120 IP 93.184.216.34.80 > 192.168.1.5.52345: Flags [P.], seq 201:2000, ack 182, length 1799 ↑ PSH — данные (HTTP ответ) 10:40:02.000 IP 93.184.216.34.80 > 192.168.1.5.52345: Flags [F.], seq 2000, ack 182, length 0 10:40:02.001 IP 192.168.1.5.52345 > 93.184.216.34.80: Flags [F.], seq 182, ack 2001, length 0 10:40:02.001 IP 93.184.216.34.80 > 192.168.1.5.52345: Flags [.], ack 183, length 0 ↑ FIN-ACK / FIN-ACK / ACK → соединение закрыто

Работа с файлами .pcap

Сохранение и чтение pcap
# Сохранить трафик в файл (-w) $ sudo tcpdump -i eth0 -nn -s 0 -w /tmp/capture.pcap tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes # Нажмите Ctrl+C для остановки ^C 47 packets captured 47 packets received by filter 0 packets dropped by kernel # Чтение из файла (-r) $ sudo tcpdump -nn -r /tmp/capture.pcap # Чтение с фильтром $ sudo tcpdump -nn -r /tmp/capture.pcap port 80 # Ротация файлов: новый файл каждые 3600 секунд $ sudo tcpdump -i eth0 -nn -s 0 -w /tmp/capture_%Y%m%d_%H%M.pcap -G 3600 # Ротация по размеру: новый файл каждые 100 МБ $ sudo tcpdump -i eth0 -nn -s 0 -C 100 -w /tmp/capture.pcap # Хранить не более 5 файлов (перезаписывать старые) $ sudo tcpdump -i eth0 -nn -s 0 -G 3600 -W 5 -w /tmp/cap_%Y%m%d_%H%M.pcap # Открыть в Wireshark (из командной строки) $ wireshark /tmp/capture.pcap & # Конвертация в текстовый формат $ tcpdump -nn -r capture.pcap -w - | tcpdump -r - -A > capture.txt

Продвинутые техники

Захват в фоне с записью в файл

Фоновый захват
# Запуск в фоне $ sudo tcpdump -i eth0 -nn -s 0 -w /var/log/traffic.pcap & [1] 12345 # Остановить по PID $ sudo kill 12345 # Через systemd unit (для постоянного мониторинга) # /etc/systemd/system/tcpdump-monitor.service [Unit] Description=TCPDump Network Monitor [Service] ExecStart=/usr/sbin/tcpdump -i eth0 -nn -s 0 -G 3600 -W 24 -w /var/log/tcpdump/cap_%Y%m%d_%H.pcap Restart=always [Install] WantedBy=multi-user.target

Комбинирование с другими инструментами

Pipes и комбинирование
# Поиск учётных данных в открытом тексте $ sudo tcpdump -i eth0 -l -A 'port 21 or port 23 or port 80' | grep -iE 'pass|user|login|password' # Статистика по IP-адресам назначения $ sudo tcpdump -i eth0 -nn -q | awk '{print $5}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -20 # Мониторинг DNS-запросов в реальном времени $ sudo tcpdump -i eth0 -l -nn udp port 53 | grep -oP "(?<=\? )[\w.-]+" # Передача через SSH на удалённый Wireshark $ ssh user@remotehost "sudo tcpdump -i eth0 -s 0 -w -" | wireshark -k -i -
Правовое предупреждение: Захват сетевого трафика без авторизации является незаконным во многих юрисдикциях. Используйте tcpdump только в сетях, которыми вы владеете или имеете явное письменное разрешение на тестирование.