Утилита Tcpdump знакома любому сетевому администратору, с ее помощью мы собираем трафик для последующего анализа. Типичная история – собираем траффик, приходящий на нужный интерфейс и затем уже анализируем его Wireshark. Подход практичный, ведь Wireshark Действительно очень мощный и полезный инструмент и о нем мы напишем еще не одну статью, но сегодня речь пойдет про Tcpdump. Не секрет, что утилита Tcpdump не интерпретирует протоколы прикладного уровня, ограничиваясь работой с транспортным уровнем. Однако, в этой статье мы рассмотрим различные варианты использования утилиты Tcpdump для более глубокой фильтрации трафика.

Итак, Tcpdump - утилита UNIX, позволяющая перехватывать и анализировать сетевой трафик, проходящий или приходящий через компьютер, на котором запущена данная программа.

Для начала узнаем, с какими интерфейсами мы можем работать с помощью команды:

tcpdump --list-interfaces

Если мы хотим что называется по старинке собирать весь трафик с интерфейса и сохранять его в файл, то можно выполнить следующее:

sudo tcpdump –i eth0 –w dump1.pcap

Но без фильтров мы рискуем получить  огромный файл, содержащий не так много полезных пакетов. Поэтому лучше все-таки отфильтровать нужные пакеты. Фильтровать мы можем по различным признакам.

Настраиваем буфер

Прежде, чем приступить к захвату пакетов предлагаю настроить буфер, используемый Tcpdump для захвата пакетов. Если на сетевой интерфейс придет слишком большое количество пакетов, превышающее размер буфера, ядро ОС будет отбрасывать "лишние" пакеты для того, чтобы освободить место для новых.

Для того, чтобы настроить размер буфера воспользуемся ключом -B. При этом размер измеряется в килобайтах.

Когда нужен ARP

Протокол ARP используется для определения MAC-адреса другого компьютера по известному IP-адресу. При использовании Tcpdump для захвата ARP пакетов, необходимо воспользоваться ключами -X для вывода содержимого пакетов в шестнадцатеричном виде, и ключом -e для декодирования Ethrenet заголовков. Можно также воспользоваться ключом -XX для просмотра заголовков.

$ sudo tcpdump -nnvvv -e -X arp

 

Фильтруем по IP

Рассмотрим наиболее распространенные фильтры. Прежде всего мы можем отфильтровать пакеты по нужным нам узлам.  

Фильтр host покажет, в каких пакетах фигурирует указанный узел:

sudo tcpdump –i eth0 host 192.168.222.161

При этом не имеет значения, этот узел является отправителем или получателем.

Если же мы хотим узнать, где этот узел фигурирует как источник, то необходимо воспользоваться фильтром src

sudo tcpdump –i eth0 src 192.168.222.161

Если нас интересует приемник, то фильтр dst:

sudo tcpdump –i eth0 dst 192.168.222.161

Таким образом, важным отличием host от src и dst является то, что этот фильтр показывает, где узел фигурирует, в то время как два оставшихся фильтра показывают, где узел присутствовал как источник и получатель соответственно.

Также, Tcpdump содержит несколько логических операторов AND, OR, NOT. С этими операторами все достаточно просто. В примере ниже мы ищем пакеты, в которых источником является узел из подсети 192.168.0.0/16 а узел назначения находится в подсетях 10.0.0.0/8 или 172.16.0.0/16. 

sudo tcpdump –i eth0 –n src net 192.168.0.0/16 and dst net 10.0.0.0/8 or 172.16.0.0/16

Порты и протоколы

В простейшем случае для фильтрации по определенному порту нам потребуется фильтр port

sudo tcpdump –i eth0 port 443

В более сложном случае нам может потребоваться диапазон портов, и тогда нам поможет фильтр portrange

sudo tcpdump –i eth0 portrange 21-23

Далее рассмотрим протоколы транспортного уровня и начнем с UDP. Здесь все достаточно просто

sudo tcpdump –i eth0 udp

Аналогично с ICMP

sudo tcpdump –i eth0 icmp

А вот с TCP все гораздо интереснее. Конечно, в простейшем случае мы можем просто сделать выборку по данному протоколу:

sudo tcpdump –i eth0 tcp

Но в реальности именно с протоколом TCP могут возникать разные интересные вещи.

В пакетах ТСР применяется следующий формат:

Очень часто возникает необходимость поиска пакетов с различными флагами. Включение определенного флага определяется соответствующим битом.

Напомним, как в TCP осуществляется трехстороннее рукопожатие, предшествующее обмену данными.

 

Так, для поиска пакетов с флагом  SYN нам необходимо указать значение поля 13 в TCP пакете равное 0х002, то есть SYN.

sudo tcpdump –i eth0 tcp[13]==2

 

Альтернативный, и возможно более удобный вариант фильтрации по флагам – это использование конструкции 'tcp[tcpflags] & (tcp-название_флага) != 0'. Например, для флага SYN:

'tcp[tcpflags] & (tcp-syn) != 0'

Аналогично с другими флагами: ACK, URG, PSH, RST, FIN. Для того, чтобы выявить какие узлы больше всего отправляют пакеты с флагом SYN, но при этом не отвечают ACK можно воспользоваться следующим скриптом:

 

while :; do

  date; 

  sudo tcpdump -i eth0 -n -c 100 \

  'tcp[tcpflags] & (tcp-syn) != 0' and \

  'tcp[tcpflags] & (tcp-ack) == 0' \

  | awk '{ print $3}' \

  | sort | uniq -c | sort | tail -5;

  echo;

  sleep 1

done

 

Захват Keep-Alive

Пакеты Keep Alive используются для поддержания соединения, но при этом в них не передаются данные. Наличие большого количества Keep Alive может быть признаком проблем с сетью.  

Такие пакеты содержат флаг ACK но при этом в них отсутствует полезная нагрузка. Отфильтровать такие пакеты можно с помощью следующего запроса:

$ sudo tcpdump -vv "tcp[tcpflags] == tcp-ack and less 1"

Прикладной уровень

Как уже говорилось ранее, Tcpdump не работает с пакетами прикладного уровня. Но это вовсе не означает, что мы не можем пытаться идентифицировать прикладные протоколы например по начальным байтам в пакетах.

В качестве примера рассмотрим поиск TLS/SSL пакетов. В случае, если используется нестандартный порт, фильтрация по порту нам не поможет. Нам необходимы признаки TLS пакетов, и здесь нам потребуется следующий фильтр:

tcpdump -ni eth0 "(tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)"

Да, содержимое пакетов мы не увидим, но по крайней мере сможем идентифицировать шифрованный трафик.

Рассмотрим еще один пример – это поиск SSH пакетов. Здесь мы ориентируемся на набор символов “SSH-” в полезной нагрузке пакета. В запросе указаны ASCII коды символов.

tcpdump 'tcp[(tcp[12] >>2):4] = 0x5353482D'

 

И в завершение давайте перехватим GET запрос. Здесь также все достаточно просто – ищем строку “GET ”.

 sudo tcpdump 'tcp[(tcp[12] >>2):4] = 0x47455420'

Заключение

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

В завершение приглашаю всех желающих на бесплатный вебинар про создание сетевых лабораторных окружений с использованием принципов IaC на примере containerlab и netlab.

Комментарии (4)


  1. northrop
    13.04.2024 18:37

    Так, для поиска пакетов с флагом  SYN нам необходимо указать значение поля 13 в TCP пакете

    Что-то непонятно, почему у поля SYN номер 13. Подсчет полей в картинке дает совсем не этот номер. Можете пояснить?


    1. wilcot
      13.04.2024 18:37
      +1

      Нужно считать по байтам:
      2(порт источника)+2(порт назначения)+4(номер последовательности)+4(номер подтверждения)+1(длина заголовка и часть резерва).


  1. nv13
    13.04.2024 18:37
    +1

    Было бы полезно упомянуть примеры трафика с виртуальными сетями, вывод дампа в файл и то, что по дефолту дампится только заголовок без пейлоада


  1. kekoz
    13.04.2024 18:37

    Не секрет, что утилита Tcpdump не интерпретирует протоколы прикладного уровня, ограничиваясь работой с транспортным уровнем.

    На картинке — “выхлоп” tcpdump -ni vmx0 udp port domain. Т.е. выделенное зелёным не является интерпретацией прикладного протокола DNS по-вашему?