6.11. Демонстрация основных навыков работы с утилитой tcpdump(1)

Описание.  По данному выводу команды tcpdump(1) кандидат BSDA должен уметь дать ответ на основные вопросы связанные со связью по сети. Для этого кандидат должен знать обычные номера портов для распространённых TCP и UDP сервисов, разницу между TCP/IP сервером и клиентом и о «тройном рукопожатии».

Практика. tcpdump(1)

Комментарий

В Приложение B, Некоторые сведения о стеке протоколов TCP/IP рассказано многое о функционировании протоколов стека TCP/IP. В частности о процедуре открытия соединения TCP (процедуре «тройного рукопожатия») рассказано в Раздел B.1.4.3.2, «Открытие соединения TCP, тройное рукопожатие». О том какие номера портов каким протоколам соответствуют можно справиться в файле /etc/services.

6.11.1. Работа с программой tcpdump(1)

Утилита tcpdump(1) отностится к числу так называемых «снифферов» — программ предназначенных для перехвата сетевого трафика. Одним словом, tcpdump(1) предназначен для подслушивания. С одной стороны, это одно из самых мощных средств диагностики и администратор без tcpdump(1) будет лишён глаз и ушей, с другой стороны, сама возможность применения этой программы потенциально опасна.

tcpdump(1) не единственный сниффер, которым может пользоваться администратор. Кроме tcpdump(1). есть ещё замечательная программа wireshark(1) (более известная как ethereal) — сниффер с графическим интерфейсом, который может обрабатывать дампы сделаные программой tcpdump(1) и другие. Этот сниффер будет описан в Раздел 6.11.2, «Графический сниффер Wireshark/Ethereal/tEhereal». Описание работы tcpdump и ethereal можно также найти в работах Николая Малых: [url://Malyh-tcpdump-2005], [url://Malyh-ethereal-2005]

tcpdump(1) работает при помощи интерфейса bpf(4) (Berkeley Packet Filter). Если поддержку этого устройства отключить, сниффинг в BSD окажется невозможен.

[Замечание]Замечание
Права на запуск программы tcpdump(1) определяются правами доступа к устройсву bpf(4) (/dev/bpf0). Эти права можно регулировать через devfs(8). Если вы предоставляете, например, группе operator права на чтение из этого устройства, то это значит, что все члены этой группы смогут перехватывать любой трафик, в том числе трафик суперпользователя.

Если программа tcpdump(1) вызвана для прослушивания некоторого интерфейса, она переводит его в «promiscuous mode» — «неразборчивый режим». В этом режиме интерфейс ловит вообще все пакеты, которые до него добрались, а не только пакеты адресованные непосредственно ему. Таким образом, если сеть собрана не на коммураторах (switch'ах), а на репитерах (hub'ах), то tcpdump(1) позволит перехватить трафик между посторонними машинами, т.е. подслушать разговор двух сторонних машин. Сказанное не означает, что перехват трафика невозможен в сети собранной на коммутаторах (подробно об этом мы говорим в Раздел B.1.2, «Канальный уровень OSI»). Впрочем, интерфейс можно и не переводить в promiscous mode, если передать программе аргумент -p.

tcpdump(1) — утилита с интерфейсом командной строки. Несмотря на повсеместную распространённость (существуют даже порты под Windows) эта утилита не входит в стандарт POSIX и может отсутствовать или присутствовать, но не работать по причине указанной в предыдущих абзацах. Если вы являетесь сторонником графического интерфейса, вы можете найти и альтернативные программы в системе портов, например ethereal(1). Однако все они будут работать через bpf(4) (или не будут работать, если вы его исключите из ядра). Эти программы могут предоставлять больше удобств, но вряд ли окажутся более функциональными.

Итак, опции tcpdump(1) можно разделить на несколько типов:

Выбор объекта
Какой интерфейс прослушивать, читать ли данные из файла, сохранять ли их в файл.
Опции форматирования
В каком виде представить дату, выводить ли шестнадцатеричный дамп пакета и т.п.
Прочие опции
Объём захватываемой информации, привилегии, буферизация, запись в файлы в стиле logrotate и вращение записанных файлов, и др.
Условия
Т.е. какие пакеты перехватывать: можно перехватывать только пинги, или только ARP запросы, или только почтовый трафик. Например, если вы зашли по ssh(1) с машины A на машину B и изучаете на ней работу сети командой tcpdump(1) разумно исключить из рассмотрения трафик между машиной A и 22-м портом машины B.

6.11.1.1. Выбор объекта

ОпцииОписание
-i interface Какой интерфейс должен прослушиваться программой.
-w file В норме отчёт программы tcpdump(1) выводится на терминал в режиме реального времени, однако можно попросить при помощи опции -w записывать всю информацию в файл в бинарном виде, т.е. сделать dump того, что происходит на сетевом интерфейсе. В последствии эту информацию можно заново проанализировать при помощи опции -r.
-r file Эта опция применяется вместо -i и служит для того, чтобы прочитать данные из файла. Файл в бинарном формате можно создать заранее при помощи опции -w. Кроме того, есть и другие программы, которые создают файлы в формате бинарного файла tcpdump(1), например в этом формате сохраняет журнальный файл брандмауэр pf(4).
-D Перечислить доступные интерфейсы (которые можно прослушивать при помощи опции -i).
# tcpdump -D
1.rl0
2.pflog0 1
3.rl1
4.lo0
   
1 Интерфейс pflog принадлежит пакетному фильтру pf(4). (Это брандмауэр OpenBSD, который так же доступен в FreeBSD, см. Приложение C, Пакетный фильтр OpenBSD — pf(4)) Данный брандмауэр позволяет читать журнальный файл в режиме реального времени, для этого можно воспользоваться программой tcpdump(1) нацелив её на интерфейс pflog0. Сам журнальный файл ведётся в бинарном формате так, чтобы его можно было прочитать при помощи tcpdump(1) с опцией -r

6.11.1.2. Форматирование вывода

ОпцииОписание
-q Вывод информации в краткой форме. Одно из «неудобств» программы tcpdump(1) состоит в том, что она очень информативна. Из-за этого информация о перехватываемых сообщениях не влезает в строку в терминале. Данная опция призвана разрешить эту проблему.
-A
-x
-xx
-X
-XX
Эти опции включают вывод содержимого пакета. Опция -A — в формате ASCII, -x — в шестнадцатеричном виде и -X одновременно и в ASCII и в шестнадцатеричном виде. К сожалению, я ещё ни разу не видел чтобы опция -A работала. На протестированных мною версиях она была эквивалентна опции -x. Двухбуквенные опции делают то же, что и их однобуквенные аналоги, но не отбрасывают заголовки канального уровня. Для просмотра содержимого пакетов может быть так же полезна опция -s (см. далее).
-v
-vv
-vvv
Verbouse — подробный вывод информации о заголовке пакета. Чем больше букв v тем подробнее вывод.
-t
-tt
-ttt
-tttt
Разный формат вывода даты: 1) не выводит информации о времени, 2) время выводится в секундах от начала UNIX эры, 3) выводится информация о том, сколько прошло микросекунд после предыдущей строки, 4) обычный формат (час:мин:сек.микросек), но спереди добавлена текущая дата (год-месяц-число).
-f
-n
-N
-f использует числовые IP адреса вместо символьных. -n ещё строже: не только адреса, но и номера протоколов выводятся в числовом виде. Опцию -f разработчики рекомендуют для борьбы с багами в NIS серверах SUN. Считается, что они могут виснуть при попытке разрешить нелокальный адрес. Опция -N заставляет вместо полного доменного имени писать только имя хоста. Т.е. вместо www.ru просто www.
-e Выводится информация о заголовках канального уровня (MAC-адреса).

Для примера мы запустим ping(1) и будем при помощи программы tcpdump(1) ловить пары ICMP пакетов. Для этого нам понадобится опция -c обрывающая пинг после получения заданного количества пакетов и мы используем условие icmp, которое заставит tcpdump(1) отчитываться только о пакетах принадлежащих протоколу ICMP.

#tcpdump -i rl0 -c2 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on rl0, link-type EN10MB (Ethernet), capture size 96 bytes
15:51:48.309703 IP 192.168.25.158 > mccme.ru: ICMP echo request, id 64479, seq 63, length 64
15:51:48.310409 IP mccme.ru > 192.168.25.158: ICMP echo reply, id 64479, seq 63, length 64
2 packets captured
30 packets received by filter
0 packets dropped by kernel

#tcpdump -i rl0 -c2 -t icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on rl0, link-type EN10MB (Ethernet), capture size 96 bytes
IP 192.168.25.158 > mccme.ru: ICMP echo request, id 64479, seq 135, length 64
IP mccme.ru > 192.168.25.158: ICMP echo reply, id 64479, seq 135, length 64
2 packets captured
10 packets received by filter
0 packets dropped by kernel

#tcpdump -i rl0 -c2 -t -vv icmp
tcpdump: listening on rl0, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0x0, ttl 64, id 13694, offset 0, flags [none], proto: ICMP (1), length: 84) 192.168.25.158 > mccme.ru: ICMP echo request, id 64479, seq 217, length 64
IP (tos 0x0, ttl 63, id 40953, offset 0, flags [none], proto: ICMP (1), length: 84) mccme.ru > 192.168.25.158: ICMP echo reply, id 64479, seq 217, length 64
2 packets captured
8 packets received by filter
0 packets dropped by kernel

#tcpdump -i rl0 -c2 -t -e -vv icmp
tcpdump: listening on rl0, link-type EN10MB (Ethernet), capture size 96 bytes
00:50:22:b0:7f:39 (oui Unknown) > 00:10:e0:00:e9:cd (oui Unknown), ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 19710, offset 0, flags [none], proto: ICMP (1), length: 84) 192.168.25.158 > mccme.ru: ICMP echo request, id 64479, seq 5499, length 64
00:10:e0:00:e9:cd (oui Unknown) > 00:50:22:b0:7f:39 (oui Unknown), ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 46235, offset 0, flags [none], proto: ICMP (1), length: 84) mccme.ru > 192.168.25.158: ICMP echo reply, id 64479, seq 5499, length 64
2 packets captured
13 packets received by filter
0 packets dropped by kernel

#tcpdump -i rl0 -c2 -t -X -vv icmp
tcpdump: listening on rl0, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0x0, ttl 64, id 17657, offset 0, flags [none], proto: ICMP (1), length: 84) 192.168.25.158 > mccme.ru: ICMP echo request, id 64479, seq 3514, length 64
  0x0000: 4500 0054 44f9 0000 4001 b0ed c0a8 199e E..TD...@....... 1
  0x0010: 3e75 6c07 0800 a34d fbdf 0dba 447e e252 >ul....M....D~.R 2
  0x0020: 000d 3937 0809 0a0b 0c0d 0e0f 1011 1213 ..97............
  0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
  0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
  0x0050: 3435          45
IP (tos 0x0, ttl 63, id 44250, offset 0, flags [none], proto: ICMP (1), length: 84) mccme.ru > 192.168.25.158: ICMP echo reply, id 64479, seq 3514, length 64
  0x0000: 4500 0054 acda 0000 3f01 4a0c 3e75 6c07 E..T....?.J.>ul. 3
  0x0010: c0a8 199e 0000 ab4d fbdf 0dba 447e e252 .......M....D~.R
  0x0020: 000d 3937 0809 0a0b 0c0d 0e0f 1011 1213 ..97............
  0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
  0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
  0x0050: 3435          45
2 packets captured
7 packets received by filter
0 packets dropped by kernel
   
1

Здесь приведён шестнадцатеричный dump пакета IP. Начинается он с заголовка IP:

4500
4 и 5 это соответственно номер версии протокола IP (IPv4) и IHL — длина заголовка (5 32-х разрядных машинных слов = 20 байт). 00 — поле TOS (Type of service).
0054
Общая длина в байтах в данном случае 84 байта. (54 это конечно шестнадцатеричное число). В нашей распечатке налицо 82 байта, куда провалились ещё два, не знаю.
44f9
Идентификатор пакета (см. число 17657 в расшифровке строкой выше).
0000
Флаги и смещение фрагмента.
4001
40 это TTL (64 в десятичной системе). 01  — номер протокола. Номера протоколов транспортного уровня можно посмотреть в файле /etc/protocols. 1 это ICMP, 6 — TCP, 17 — UDP.
b0ed
Контрольная сумма заголовка.
c0a8 199e
IP адрес источника 192.168.25.158
2
3e75 6c07
IP адрес назначения 62.117.108.7

На этом закончились 20 байт заголовка IP, теперь пошёл пакет ICMP

0800
08 это тип сообщения ICMP (echo request), 00 — код.
3 Легко видеть, что адреса источника и назначения поменялись местами, а тип ICMP пакета изменлся с 08 на 00, (с echo request на echo reply).

6.11.1.3. Прочее

ОпцииОписание
-l Сделать буферизацию построчной. Это полезно, если вы перенаправляете вывод tcpdump(1) в pipe, например направляете его на вход команде tee(1) или awk(1). (См Раздел 7.1, «Перенаправление вывода и использование tee(1)»).
-c count Выйти из программы после получения count пакетов.
-C size Если выбрана опция -w файл не должен превысить размера size. Если объём оказывается больше, то запись производится в другой файл, имя которого определяется путём дописывания номера к имени файла. size задаётся в миллионах байт.
-W num Используется одновременно с -C. Ограничивает количество файлов числом num.
-F file Условие (см следующий раздел) читать не из командной строки, а из файла.
-s size Захватывать size байт от каждого пакета. По умолчанию перехватываются только первые 96 байт, это существенно уменьшает размер файла, котрый записывает программа. В большинстве случаев первых 96 байт достаточно для прояснения ситуации, однако, если вы хотите именно перехватить трафик целиком, т.е. заниматься сниффингом, и хотите использовать опции -x или -X, вам стоит выставить size равным MTU.
-p Отключить promiscous mode
-Z user После запуска сделать владельцем процесса пользователя user. В качестве группы будет назначена основная группа, в которую входит user.

6.11.1.4. Условия

Условия определяют то, какие пакеты будут перехвачены. Если не указано никаких условий, будут перехвачены все пакеты, если условия указаны, то только те пакеты, для которых это условие истинно.

Условие состоит из некоторого количества примитивов. Примитив состоит из идентификатора (числа или имени) перед которым идёт оператор одного из трёх типов:

тип
чем является идентификатор? Допустимые значения: host, net, port, portrange. Например, возможны следующие примитивы: host somehost, net 128.3, port 20, portrange 6000-6008
направление
куда относительно идентификатора направлен пакет? Возможные направления: src, dst, src or dst, src and dst. Например: src somehost, dst net 128.3, src or dst port ssh. Если направление не указано, подразумевается src or dst.
протокол
ограничивает пакеты некоторым протоколом. Возможные протоколы: ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, lat, sca, moprc, mopdl, iso, esis, isis, icmp, icmp6, tcp и udp. Например: ether src somehost, arp net 128.3, tcp port 21, udp portrange 7000-7009. Некоторые из этих протоколов являются синонимами, см. страницу man(1). Если протокол не указан подразумеваются все пригодные протоколы. Например: src somehost эквивалентно (ip or arp or rarp) src somehost (За исключением того, что синтаксис последнего выражения негоден.) port 53 означает (tcp or udp) port 53.

Кроме того, есть примитивы, за которыми не следует шаблона: gateway, broadcast, less, greater. Можно строить сложные условия объединяя примитивы при помощи следующих операторов: and, or, not.

Допустимые примитивы:

dst host xxx
Истина, если пакет направлен хосту xxx
src host xxx
Истина, если пакет отправлен хостом xxx
host xxx
Истина, если пакет отправлен хостом xxx или предназначен хосту xxx. Перед перечисленными примитивами могут быть упомянуты протоколы ip, ip6, arp, rarp. ip host xxx эквивалентно ether proto ip and host xxx. Замечание: «ip» — ключевое слово, поэтому мы должны защитить его обратным слешем (а в shell'е двумя бекслешами).
ether dst host xxx
Истина, если пакет предназначен хосту с канальным адресом xxx (т.е. MAC адрес xxx).
ether src host xxx
аналогично, но в обратную сторону
ether host xxx
Истина, если MAC адрес назначения или MAC адрес источника xxx.
gateway xxx
Истина, если пакет использует xxx в качестве шлюза. Т.е. если MAC адрес источника или назначения соответствует xxx, но ни IP адрес источника ни IP адрес назначения не являются xxx. xxx должен быть именем, и разрешаться машиной как в IP так и в MAC (возможно с использованием файла /etc/ethers). Эквивалентная конструкция ether host xx1 and not host xxx2, где xxx1 это аппаратный адрес хоста xxx, а xxx2 — IP адрес xxx.
dst net xxx
Истина, если IP адрес назначения принадлежит сети xxx
src host xxx
Истина, если IP адрес источника принадлежит сети xxx
net xxx
Истина если один из адресов (источника или назначения) принадлежит сети xxx.
net xxx mask yyy
То же, но позволяет задавать CIDR сети, т.е. сети не по классам A, B, C, а по безклассовой системе.
net xxx/len
То же.
dst port xxx
Порт назначения xxx. Работает с пакетами ip/tcp, ip/udp, ip6/tcp и ip6/udp. xxx можно задать числом, а можно символьно, в этом случае номер порта будет взят из файла /etc/services.
src port xxx
порт источника xxx
port xxx
один из портов (назначения или источника) xxx
dst portrange xxx-yyy
Истина, если порт назначения лежит в диапазоне между xxx yyy. xxx и yyy можно задавать как численно, так и по имени.
src portrange xxx-yyy
Аналогично
portrange xxx-yyy
Аналогично
less xxx
Истина, если размер пакета меньше xxx
greater
Истина, если размер пакета больше xxx
ip proto xxx
Истина, если пакет принадлежит протоколу xxx. Протокол может быть задан по номеру или по имени. Допустимы следующие имена: icmp, icmp6, igmp, igrp, pim, ah, esp, vrrp, udp, tcp. Замечание: идентификаторы tcp, udp и icmp являются ключевыми словами и должны защищаться обратным слешем (а в shell'е двумя бекслешами).
ip6 proto xxx
Истина, если пакет IPv6 принадлежит протоколу xxx.
ip6 protochain xxx
Истина, если пакет IPv6 содержит заголовок протокола xxx в своём заголовке. Например ip6 protochain 6 соответствует пакет IPv6 с заголовком TCP. Пакет может содержать, например, аутентификационный заголовок, маршрутизационный заголовок или дополнительный hop-by-hop заголовок.
ip protochain xxx
То же, но для IPv4
ether broadcast
Истина, если данный пакет отправлен на широковещательный канальный адрес.
ip broadcast
Истина, если пакет отправлен на широковещательный IP адрес
ether multicast
Истина, если пакет направлен на мультикастный канальный адрес. Ключевое слово ether можно опустить. Данный примитив эквивалентен ether[0] & 1 != 0.
ip multicast
Истина, если пакет направлен на мультикастный IPv4 адрес
ip6 multicast
Истина, если пакет направлен на мультикастный IPv6 адрес
ether proto xxx

Истина, если пакет принадлежит канальному протоколу xxx. Протокол может быть передан по номеру или символьно. Допустимы следующие имена: ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, netbeui. Замечание: некоторые из этих идентификаторов — ключевые слова и должны быть экранированы обратным слешем (а в shell'е двумя бекслешами).

В случае FDDI надо писать fddi proto arp, Token ring — tr proto arp, беспроводные сети IEEE 802.11 — wlan proto arp. Впрочем, fddi, wlan, tr и ether ведут себя как синонимы.

decnet src xxx, decnet dst xxx, decnet host xxx
DECNET доспупна на соответствующим образом сконфигурированной системе ULTRIX.
ip, ip6, arp, rarp, atalk, aarp, decnet, iso, stp, ipx
Аббревиатуры для выражения ether proto p, где p — один из перечисленных протоколов.
lat, moprc, mopdl
То же, но верно следующее замечание: tcpdump(1) пока не умеет разбирать данные протоколы (т.е. умеет только детектировать их).
vlan [xxx]
Естина, если пакет является пакетом IEEE 802.1Q VLAN. Если указан [xxx], проверяется так же и идентификатор VLAN. Первое ключевое слово vlan приводит к расшифровке пакета. Таким образом, условию vlan 100 && vlan 200 соответствуеют пакеты vlan 200 упакованные в пакеты vlan 100. Условию vlan && vlan 300 && ip соответствуют пакеты IPv4 упакованные в vlan 300, которые упакованы в vlan верхнего уровня.
tcp, udp, icmp
Аббревиатуры для выражения ip proto p or ip6 proto p, где p — один из перечисленных протоколов.
iso proto xxx
Истина, если пакет является пакетом OSI протокола xxx. Протокол может быть задан номером или по имени. Допустимы следующие имена: clnp, esis, isis.
clnp, esis, isis
Аббревиатуры для выражения iso proto p, где p — один из перечисленных протоколов.
l1, l2, iih, lsp, snp, csnp, psnp
Аббревиатуры для IS-IS PDU.
vpi xxx, vci xxx, lane, llc, oamf4s, oamf4e, oamf4, oam, metac, bcc, sc, ilmic, connectmsg, metaconnect
Эти правила относятся к пакетам ATM для SunATM Solaris. Поскольку я не являюсь специалистом в данной системе, я не считаю возможным переводить на русский эту часть руководства.

Программа tcpdump(1), как отмечалось выше, может использоваться пакетным фильтром (PF) OpenBSD для обработки журнальных файлов (при помощи опции -r), а так же для чтения журнала в режиме реального времени при помощи опции -i через устройство pflog (см. Раздел C.2.3.1, «Журналирование в пакетном фильтре»). Пакетный фильтр OpenBSD работает не только в OpenBSD, но и в FreeBSD. В последней системе он сперва появился как порт, а затем был добавлен в ядро начиная с версии FreeBSD 5.2.1. Теперь он портируется в ядро FreeBSD при каждом релизе.

Пакетный фильтр помещает в пакеты, которые он направляет в журнал специфическую информацию, о том, какое правило отправило пакет в журнал, какие действия предприняты с этим пакетом и проч. Для работы с этой информацией tcpdump(1) имеет специальные примитивы. Перечисленные ниже примитивы пригодны только для работы с журналом PF.

ifname xxx
Истина, если пакет прошёл через заданный интерфейс.
on xxx
Синоним ifname
rnr xxx
Истина, если пакет соответствует правилу номер xxx.
rulenum xxx
Синоним rnr
reason xxx
Истина, если пакет попал в журнал по соответствуюей причине (reason). Эта «причина» добавляется к пакету брандмауэром. Можно указывать следующие коды: match, bad-offset, fragment, short, normalize, memory.
rset xxx
Истина, если пакет попал в журнал так как соответствовал правилу из набора (anchor) с именем xxx (см. Раздел C.2.2.3, «Anchors»).
ruleset xxx
Синоним rset
srnr xxx
Истина если пакет попал в журнал от того, что соответствовал правилу номер xxx из поднабора правил (см. Раздел C.2.2.3, «Anchors»)
subrulenum xxx
Синоним srnr
action xxx
Истина, если пакетный фильтр проделал с пакетом действие xxx. Допустимые значения pass и block.

Дополнительный примитив — арифметический:

expr relop expr

Истина, если выполнено данное отношение, где relop может быть: >, <, >=, <=, =, !=, а expr — арифметическое выражение составленное из целых чисел (стандартный синтаксис языка C) и бинарных операторов: +, -, *, /, &, |, <<, >>, а так же оператора длины и специальных операторов доступа к данным пакета. Замечание: все сравнения беззнаковые, т.е. 0x80000000 и 0xffffffff больше нуля.

Для доступа к данным пакета используйте следующий синтаксис: proto [ expr : size ], proto может быть: ether, fddi, tr, wlan, ppp, slip, link, ip, arp, rarp, tcp, udp, icmp, ip6, radio и определяет уровень протокола, для операции взятия индекса. (ether, fddi, wlan, tr, ppp, slip и link ссылаются на канальный уровень, radio ссылается на radio header добавляемый в некоторые пакеты 802.11). Замечание: tcp, udp и другие протоколы верхнего уровня применимы пока только к IPv4, но не к IPv6, что должно быть исправлено в будущем.

expr — означает смещение в байтах для протокола данного уровня. size необязательная величина, означает количество захватываемых байт. По умолчанию size равен единице, можно подставить два три или четыре. Оператор len возвращает длину пакета в байтах.

Для понимания приведённых ниже примеров объясним, что делает бинарный оператор &. & — это оператор бинарного сложения. Пусть надо сложить бинарно числа 11 и 13. Для этого мы запишем их в бинарном виде, и сложим побитово. При этом сумма есть результат логической операции, в которой 0 это ложь, а 1 — истина. Т.е. 0+0=0, 0+1=1+0=0, 1+1=1.

13=1101 
11=1011 
 1001=9

Таким образом, 11&13=9.

Примеры: выражение ether[0] & 1 != 0 захватывает весь мультикастный трафик (для него есть так же примитив multicast, см выше). Пояснение: здесь проверяется на чётность первый байт заголовка канального уровня. При этом заголовок канального уровня начинается с 6 байт канального адреса назначения. Таким образом, данное условие выясняет равен ли единице восьмой бит 48-битного MAC адреса.

Выражение ip[0] & 0xf != 5 захватывает все пакеты IPv4 с опциями. Пояснение: здесь берётся первый байт пакета IPv4 и складывается с числом 0xf (в десятичной системе 15, в двоичной 1111). Если в результате сложения получится число 5 (101), то значит первый байт был xxxx1010 т.е. вторая половина первого байта была равна 5. А как мы видели в листинге выше, вторая половина первого байта отвечает за длину IPv4 заголовка в 32-х разрядных словах. Если длина заголовка 5 32-битных слов, то значит никаких дополнительных опций в нём нет, так как это наименьшая возможная длина заголовка IP. А если результат операции не равен 5, то значит он больше пяти и в нём есть какие-то дополнительные опции.

Выражение ip[6:2] & 0x1fff = 0 соответствует нефрагментированным пакетам IPv4, либо нулевому фрагменту фрагментированного пакета. Пояснение: здесь берётся два байта пакета IPv4: седьмой и восьмой (отсчёт идёт с нуля, таким образом, ip[6] это седьмой байт) и складываются с числом 0x1fff (1111111111111), таким образом из них «вырезаются» последние 13 бит, отвечающие за номер фрагмента.

Некоторые «смещения» предопределены и имеют названия. например: icmptype, icmpcode, tcpflags. Так же предопределены и значения: icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreqreply, а так же для флагов TCP: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg.

Примитивы могут объединяться при помощи следующих операторов:

! или not
Отрицание. Имеет наибольший приоритет
|| или or
Альтернатива
&& или and
Объединение

Кроме того, для указания приоритета можно использовать круглые скобки.

Если идентификатор отсутствует, подразумевается последний использованный. Так not host vs and ace эквивалентно not host vs and host ace.

6.11.1.5. Примеры

Все пакеты относящиеся к трафику с машиной sundown:

# tcpdump host sundown
   

Трафик между машиной helios и машинами hot или ace:

# tcpdump host helios and ( hot or ace )
   

Все пакеты IP идущие между ace и любым хостом кроме helios:

# tcpdump ip host ace and not helios
   

Весь ftp трафик идущий через шлюз snup:

# tcpdump 'gateway snup and (port ftp or ftp-data)'
   

Весь трафик, который не направлен в нашу локальную сеть и не выходит из неё, (т.е. транзитный трафик).

# tcpdump ip and not net localnet
   

Начальные и конечные пакеты TCP (т.е. пакеты с флагами SYN и FIN) соединений вызванных не нашими машинами:

# tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net localnet'
   

Все IPv4 пакеты протокола HTTP направленные на 80 порт или с 80-го порта. Причём только пакеты содержащие данные, не захватывая пакеты SYN, FIN или пакеты в которых есть только флаг ACK. (Такое выражение поможет перехватить веб трафик).

# tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
   

Пояснение:

Бинарные операторы << и >> — это операторы сдвига.

Пример в двоичной системеТо же в десятичной системе
1010>>1=010110>>1=5
1010>>2=001010>>2=2
1011<<3=101100011<<3=88

ip[2:2] это третий и четвёртый байт заголовка IP, т.е. длина всего пакета в байтах.

Далее, выражение ip[0]&0xf берёт первый байт заголовка IP и вырезает из него последние 4 бита (т.к. 0xf=00001111), в этих битах содержится длина заголовка IP. Полученную величину сдвигают влево на два бита, так, как длина заголовка IP задаётся в 32-битных словах, а не в байтах. Таким образом длина заголовка IP переведена в байты.

Наконец, tcp[12] берёт 13-й байт заголовка TCP. Первые его 4 бита соответствуют длине заголовка. Их вырезают выражением tcp[12]&0xf0 (т.к. 0xf0=1111000). Полученное выражение сдвигают вправо на два бита и получается длина заголовка TCP в байтах.

Из длины пакета вычитают длину заголовка IP и длину заголовка TCP, таким образом в этом правиле осуществляется проверка на то, является ли пакет пустым. А по флагам никаких проверок то и нет!

Следующее выражение соответствует пакетам длиннее 576 байт посылаемым через шлюз snup:

# tcpdump 'gateway snup and ip[2:2] > 576'
   

Следующий пример: выражение соответствует пакетам посылаемым на широковещательный или мультикастный IP, но не рассылаемым через широковещательный или мультикастный Ethernet адрес:

# tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
   

Здесь выражение ether[0]&1 вычисляет равен ли нулю восьмой бит MAC адреса назначения (что означает, что адрес не широковещательный и не мультикастный). А выражение ip[16] оперирует с первым байтом адреса назначения.

Следующий пример: выражение соответствует пакетам ICMP если это не «пинги», т.е. не echo-request и не echo-reply:

# tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
# tcpdump 'icmp[0] != 8 and icmp[0] != 0'
   

Приведённые команды эквивалентны.

6.11.2. Графический сниффер Wireshark/Ethereal/tEhereal

Описание работы wireshark(1) выходит за рамки данного труда, однако не упомянуть о них в связи с tcpdump(1) невозможно. wireshark — графический анализатор протоколов. С его помощью удобно разбирать сделанные при помощи tcpdump(1) и других анализаторов файлы, кроме того она сама позволяет прослушивать сеть и делать dump'ы в формате программы tcpdump(1).

У программы wireshark(1) несколько имён:

wireshark
Новое имя программы
ethereal
Старое имя программы. Название программы сменилось в 2006 году по лицензионным причинам. Так или иначе, программа широко известна под старым именем и информацию о ней следует искать в первую очередь под старым именем.
tethereal
Текстовый вариант программы. В этом виде её функционал сравним с функционалом tcpdump(1).

Пока данный раздел не написан я просто приведу скриншот программы wireshark(1), в которой открыт файл pflog — журнальный файл пакетного фильтра OpenBSD. (См. Приложение C, Пакетный фильтр OpenBSD — pf(4)). Дополнительную информацию об wireshark вы можете найти в работе Николая Малых: [url://Malyh-ethereal-2005].

Screenshot программы ethereal
В программе wireshark(1) (старое имя ethereal) открыт журнальный файл пакетного фильтра OpenBSD, который ведётся в формате tcpdump(1).

6.11.3. Анализатор tcpdstat

Существует не мало разнообразных анализаторов, которые выводят разнообразную статистику из файлов в формате libpcap (формат программы tcpdump(1)). Для примера приведу программу tcpdstat. Программа устанавливается из порта net/tcpdstat.

Вот пример отчёта, который генерирует данная программа:

# tcpdump -i rl1 -w dump
tcpdump: listening on rl1, link-type EN10MB (Ethernet), capture size 96 bytes
^C1458 packets captured
1461 packets received by filter
0 packets dropped by kernel
$ tcpdstat dump

DumpFile: dump
FileSize: 0.14MB
Id: 200705030906
StartTime: Thu May 3 09:06:47 2007
EndTime: Thu May 3 09:16:03 2007
TotalTime: 555.58 seconds
TotalCapSize: 0.12MB CapLen: 96 bytes
# of packets: 1458 (364.58KB)
AvgRate: 16.17Kbps stddev:52.23K

### IP flow (unique src/dst pair) Information ###
# of flows: 72 (avg. 20.25 pkts/flow)
Top 10 big flow size (bytes/total in %):
 38.8% 20.5% 19.1% 5.7% 4.5% 2.1% 1.6% 0.8% 0.4% 0.4%

### IP address Information ###
# of IPv4 addresses: 38 
Top 10 bandwidth usage (bytes/total in %):
 100.0% 41.1% 24.9% 20.6% 4.6% 2.4% 0.6% 0.6% 0.4% 0.4%
### Packet Size Distribution (including MAC headers) ###
<<<<
 [ 32- 63]:  143
 [ 64- 127]:  681
 [ 128- 255]:  149
 [ 256- 511]:  344
 [ 512- 1023]:   41
 [ 1024- 2047]:  100
>>>>


### Protocol Breakdown ###
<<<<
  protocol		packets			bytes		bytes/pkt
------------------------------------------------------------------------
[0] total    1458 (100.00%)   373331 (100.00%) 256.06
[1] ip    1430 ( 98.08%)   371651 ( 99.55%) 259.90
[2] tcp    742 ( 50.89%)   252248 ( 67.57%) 339.96
[3] http(s)   133 ( 9.12%)   151371 ( 40.55%) 1138.13
[3] http(c)   123 ( 8.44%)   11761 ( 3.15%)  95.62
[3] ssh    486 ( 33.33%)   89116 ( 23.87%) 183.37
[2] udp    140 ( 9.60%)   19795 ( 5.30%) 141.39
[3] dns    140 ( 9.60%)   19795 ( 5.30%) 141.39
[2] icmp    306 ( 20.99%)   23212 ( 6.22%)  75.86
[2] other    242 ( 16.60%)   76396 ( 20.46%) 315.69
>>>>

  

6.11.4. ngrep

Другая удобная утилита предназначенная для анализа сетевого трафика и дампов в формате libpcap — ngrep. Эта программа (устанавливается из порта net/ngrep) позволяет искать пакеты, содержимое которых соответствует заданному шаблону:

# ngrep -d rl0 -i password port 23
interface: rl0 (172.19.0.0/255.255.255.0)
filter: (ip) and ( port 23 )
match: password
############################################
T 192.168.0.1:23 -> 172.19.0.33:38250 [AP]
 Password:                 
##################exit
62 received, 0 dropped
  

В приведённом примере прослушивался интерфейс rl0. При этом в пакетах разыскивался шаблон password без учёта регистра (опция -i). Выражение port 23 это фильтр (синтаксис такой же как у tcpdump(1)). Пакеты в которых указанный шаблон не найден обозначаются в отчёте решётками. Для пакетов в которых шаблон найден выводится информация о пакете и найденная строка.

Шаблоны являются регулярными выражениями и пишутся в формате egrep(1). (см. Раздел 7.14, «Применение регулярных выражений»)


Обновлено: 12.03.2015