Анализ сетевого трафика на сервере при помощи tshark

tshark

В практике системного администрирования довольно часто приходится сталкиваться со сложными ситуациями, в которых не помогают ни инструменты сбора статистики (например, netstat), ни стандартные утилиты на основе протокола ICMP (ping, traceroute и другие). В таких случаях часто используются специализированные диагностические утилиты, дающие возможность «слушать» сетевой трафик и анализировать его на уровне единиц передачи отдельных протоколов. Они называются анализаторами трафика, а на профессиональном жаргоне — снифферами. С их помощью можно, во-первых, локализовывать сетевые проблемы и более точно их диагностировать, а во-вторых — обнаруживать паразитный трафик и выявлять в сети зловредное ПО.

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

Одним из самых распространенных и популярных анализаторов трафика сегодня является Wireshark, распространяемый под лицензией GNU GPL. Существуют версии Wireshark для различных операционных систем: Linux, Windows, MacOS, FreeBSD, Solaris.

Tshark использует для захвата библиотеку libpcap, реализующую API pcap (packet capture). Эту библиотеку использует и стандартная утилита tcpdump. Файлы, созданные в tcpdump, можно передавать tshark для последующего анализа.

Несомненным преимуществом tshark по сравнению с tcpdump является более ясный и человекопонятный формат вывода. Кроме того, tshark поддерживает огромное количество сетевых протоколов (более 300, что охватывает практически все когда-либо изобретенные виды сетей).

Об особенностях работы с tshark мы подробно расскажем в этой статье.

Начало работы

Tshark включена в дистрибутивы большинства современных Linux-систем и устанавливается при помощи стандартного менеджера пакетов:

$ sudo apt-get install tshark

Завершив установку, запустим программу:

$ sudo tshark

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

Capturing on eth0
0.000000 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.120? Tell 31.186.98.1
0.322046 5a:58:74:bf:a9:9c -> Broadcast ARP Who has 31.186.98.77? Tell 31.186.98.226
0.351801 31.186.98.235 -> 188.93.16.50 SSH Encrypted response packet len=224
0.352414 188.93.16.50 -> 31.186.98.235 TCP cap > ssh [ACK] Seq=1 Ack=225 Win=331 Len=0 TSV=194287231 TSER=416767897
0.600054 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.120? Tell 31.186.98.1
0.622913 Cisco_0d:0d:96 -> PVST+ STP Conf. Root = 32768/398/00:21:1c:0d:0d:80 Cost = 0 Port = 0×8016
0.800377 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.107? Tell 31.186.98.1
1.320775 31.186.98.235 -> 188.93.16.50 SSH Encrypted response packet len=528
1.321507 188.93.16.50 -> 31.186.98.235 TCP cap > ssh [ACK] Seq=1 Ack=753 Win=331 Len=0 TSV=194287474 TSER=416768866
1.322109 5a:58:74:bf:a9:9c -> Broadcast ARP Who has 31.186.98.77? Tell 31.186.98.226
1.400654 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.107? Tell 31.186.98.1
1.589797 Cisco_0d:0d:96 -> PVST+ STP Conf. Root = 32768/401/00:21:1c:0d:0d:80 Cost = 0 Port = 0×8016
2.100769 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.107? Tell 31.186.98.1
2.322163 5a:58:74:bf:a9:9c -> Broadcast ARP Who has 31.186.98.77? Tell 31.186.98.226
2.322764 31.186.98.235 -> 188.93.16.50 SSH Encrypted response packet len=720
2.323594 188.93.16.50 -> 31.186.98.235 TCP cap > ssh [ACK] Seq=1 Ack=1473 Win=331 Len=0 TSV=194287724 TSER=416769868
2.520048 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.64? Tell 31.186.98.1
2.635370 Cisco_0d:0d:96 -> PVST+ STP Conf. Root = 32768/398/00:21:1c:0d:0d:80 Cost = 0 Port = 0×8016
3.200299 88:e0:f3:b6:47:c0 -> Broadcast ARP Who has 31.186.98.64? Tell 31.186.98.1
3.451774 31.186.98.235 -> 188.93.16.50 SSH Encrypted response packet len=528

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

Фильтры

Выбор интерфейса для захвата

Опция -i позволяет захватывать трафик только для конкретного интерфейса. Просмотреть список доступных сетевых интерфейсов можно с помощью команды:

$ sudo tshark -D

1. eth0
2. any
3. lo (Loopback)
4. nflog
5. nfqueue
6. usbmon1

После опции -i указывается любой из доступных интерфейсов:

$ sudo tshark -i eth0

С помощью дополнительных аргументов можно получать более специализированную информацию. Например, с помощью аргумента host можно осуществить захват пакетов для конкретного IP-адреса:

$ sudo tshark -i eth0 host 192.168.1.100

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

$ sudo tshark -i eth0 src host 192.168.1.100 

Команда выведет на консоль список пакетов, исходящих с адреса 192.168.1.100

$ sudo tshark -i eth0 dst host 192.168.1.100 

На консоль будет выведен список пакетов, поступающих на адрес 192.168.1.100.

Аналогичным образом можно захватывать трафик для целой подсети — для этого используется аргумент net:

$ sudo tshark -i eth0 src net 192.168.1.0/24

Можно также указать порт, на котором будут захватываться пакеты:

$ sudo tshark -i eth0 host 192.168.1.1 and port 80

Tshark позволяет захватывать пакеты в течение определенного промежутка времени:

$ sudo tshark -i eth0 -a duration:10 -w traffic.pcap

В приведенном примере была также использована опция -w. После неё указывается путь к файлу, в который будут записаны полученные данные.

Фильтры захвата

Эти фильтры используются при захвате трафика «на лету». Они перекомпилируются в набор правил для pcap, в соответствии с которыми осуществляется фильтрация пакетов. На консоль выводится лишь та информация, которая соответствует установленным с помощью фильтров критериям.

В общем виде синтаксис команды tshark с фильтрами можно представить так:

$ sudo tshark -i <интерфейс> -f <фильтр>

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

Фильтры чтения

Tshark может сохранять информацию о захваченных пакетах в файлах. Чтобы извлечь из этих файлов нужную информацию, используются фильтры чтения, называемые так же правилами (опция -R). Они могут быть использованы и при захвате пакетов «на лету». Обработка информации осуществляется не pcap, а средствами самого tshark.

Эти фильтры дают гораздо более широкие возможности для отбора и конкретизации информации.

Следует, однако, учитывать, что при анализе большого количества информации «на лету» они могут не справиться с возлагаемыми на них задачами: не успевают осуществлять фильтрацию и сбрасывают пакеты.

В общем виде синтаксис правил можно представить так:

$ sudo tshark -R "правило" -r "путь к файлу"

Рассмотрим особенности формирования правил на конкретных примерах.
Так, команда

$ sudo tshark -R "ip.addr == 192.168.0.1" -r /tmp/capture.cap

указывает, что из файла /tmp/capture.cap нужно извлечь информацию об исходящих и входящих пакетах для IP-адреса 192.168.0.1.

Следующее правило будет указывать, что из этого файла нужно извлечь информацию о входяших и исходящих пакетов для всех IP- адресов, кроме 192.168.0.1:

$ sudo tshark -R "!(ip.addr == 192.168.0.1)" -r /tmp/capture.cap 

Аналогичным образом можно задавать правила и для других протоколов и портов (фильтры eth.addr, udp.port, tcp.port):

$ sudo tshark -R  "eth.addr == 00:08:15:00:08:15" -r /tmp/capture.cap

$ sudo tshark -R "udp.port == 80" -r /tmp/capture.cap

$ sudo tshark -R "tcp.port == 80" -r /tmp/capture.cap

Правила можно также объединять при помощи логических операторов and, or и not:

$ sudo tshark -R "not arp and not (udp.port == 53)" -r /tmp/capture.cap

Приведенная команда указывает, что нужно извлечь список всех захваченных пакетов, кроме ARP и DNS (53 порт).

Дополнительные настройки

Cбор статистики

C помощью опции -z можно собирать и выводить на консоль различную статическую информацию о пакетах.

Например, команда

$ sudo tshark -z "proto,colinfo,tcp.srcport,tcp.srcport" -r /tmp/capture.cap

указывает, что из файла /tmp/capture.cap нужно извлечь информацию о порте-источнике всех пакетов.

Рассмотрим еще один пример:

$ sudo tshark -R "http.response and http.content_type contains image" \
-z "proto,colinfo,http.content_length,http.content_length" \
-z "proto,colinfo,http.content_type,http.content_type" \ -r /tmp/capture.cap

Эта команда извлечет из файла /tmp/capture.cap информацию обо всех пакетах, в которых были изображения, и выведет на консоль содержимое полей content_type и content_length:

439 12.717117 66.249.89.127 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 35
452 12.828186 66.114.48.56 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 477
479 13.046184 66.114.48.56 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 105
499 13.075361 203.190.124.6 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 35
506 13.177414 66.114.48.56 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 4039
514 13.190000 66.114.48.56 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (JPEG JFIF image) http.content_type == "image/jpeg" http.content_length == 11997
519 13.231228 66.114.48.56 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (JPEG JFIF image) http.content_type == "image/jpeg" http.content_length == 1033
523 13.273888 72.233.69.4 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (PNG) http.content_type == "image/png" http.content_length == 1974
561 728 19.096984 60.254.185.58 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 592
805 19.471444 60.254.185.58 -> 192.168.1.108 HTTP HTTP/1.1 200 OK (GIF89a) http.content_type == "image/gif" http.content_length == 259

Автоматическое сохранение в несколько файлов

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

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

$ sudo tshark -b filesize:100 -a files:20 -w temp.pcap

будет сохранять вывод в 20 файлах размером по 100 кБ каждый.

В приведенном выше примере опция -b означает, что будет задействован кольцевой буфер, а filesize устанавливает размер; опция -a указывает автоматическую остановку по достижении заданного предела, files — указывает количество файлов.

Автосохранение по истечении заданного времени

В приведенном ниже примере tshark будет сохранять захваченную информацию в несколько файлов. Новый файл будет создан автоматически при превышении размера в 10240 кБ или по истечении интервала 1 с:

$ sudo tshark -b filesize:10240 -b duration:1 -w temp.pcap 
 
Capturing on eth0 
34 
# ls -lrt 
-rw------- 1 root root 1863 Apr 10 16:13 temp_00001_20140410161312.pcap 
-rw------- 1 root root 1357 Apr 10 16:13 temp_00002_20140410161313.pcap 
-rw------- 1 root root 1476 Apr 10 16:13 temp_00003_20140410161314.pcap 
-rw------- 1 root root 1216 Apr 10 16:13 temp_00004_20140410161315.pcap

Установка размера буфера

Эта опция может быть полезной в случаях, когда приходится иметь дело с отбрасыванием пакетов. По умолчанию размер буфера составляет 1МБ; при помощи опции -B можно установить любой другой размер (в мегабайтах), по достижении которого все данные будут сбрасываться на диск:

$ sudo tshark -B 2

Отображение статистики для выбранного протокола

В tshark имеется также возможность захватывать только пакеты, передаваемые по указанному пользователем протоколу.

Вот так, например, выглядит статистика для протокола HTTP:

$ sudo tshark -q -r a.pcap -R http -z http,tree 

=================================================================== 
HTTP/Packet Counter value	 rate	 percent 
------------------------------------------------------------------- 
Total HTTP Packets 7 0.000375 
HTTP Request Packets 4 0.000214 57.14% 
GET 4 0.000214 100.00% 
HTTP Response Packets 3 0.000161 42.86% 
2xx: Success 2 0.000107 66.67% 
200 OK 2 0.000107 100.00% 
3xx: Redirection 1 0.000054 33.33% 
302 Found 1 0.000054 100.00% 
5xx: Server Error 0 0.000000 0.00% 
Other HTTP Packets 0 0.000000 0.00%

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

В этом разделе мы рассмотрим, как можно использовать tshark для решения повседневных администраторских задач.

Мониторинг http-запросов

Чтобы вывести список http-запросов к серверу, используется следующая команда:

$ sudo tshark 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<>2)) != 0)' -R 'http.request.method == "GET" || http.request.method == "HEAD"'

Вывод этой команды будет выглядеть так:

190.302141 192.168.0.199 -> 74.125.77.104 HTTP GET / HTTP/1.1
190.331454 192.168.0.199 -> 74.125.77.104 HTTP GET /intl/en_com/images/srpr/logo1w.png HTTP/1.1
190.353211 192.168.0.199 -> 74.125.77.104 HTTP GET /images/srpr/nav_logo13.png HTTP/1.1
190.400350 192.168.0.199 -> 74.125.77.100 HTTP GET /generate_204 HTTP/1.1

Следующая команда выведет на консоль список из 10 URL-адресов, с которых поступают http-запросы:

$ tshark -r sample1.cap -R http.request -T fields -e http.host -e http.request.uri |
sed -e ‘s/?.*$//’ | sed -e ‘s#^(.*)t(.*)$#http://12#’ | sort | uniq -c | sort -rn | head

Просмотр списка HTTP-заголовков

Чтобы просмотреть список http-заголовков запросов к серверу, используется команда:

$ tshark -r sample1.cap -R http.request -T fields -e http.host -e http.request.uri |
sed -e ‘s/?.*$//’ | sed -e ‘s#^(.*)t(.*)$#http://12#’ | sort | uniq -c | sort -rn | head

Соответственно, список заголовков для http-ответов можно получить так:

$ sudo tshark tcp port 80 or tcp port 443 -V -R «http.request»

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

$ sudo tshark "tcp port 80 or tcp port 443" -V -R "http.request || http.response"

Просмотр списка файлов определенного типа

С помощью tshark можно просматривать списки файлов определенного типа, передаваемых через http-протокол. Вот так, например, можно просмотреть список изображений в формате GIF:

$ sudo tshark -R "http.response and http.content_type contains image" \
-z "proto,colinfo,http.content_length,http.content_length" \
-z "proto,colinfo,http.content_type,http.content_type" \
-r /tmp/capture.tmp| grep "image/gif"| wc -l

Мониторинг запросов к MySQL

Отследить в реальном времени запросы в базе данных MySQL можно с помощью следующей команды:

$ sudo tshark -i eth0 -a duration:60 -d tcp.port==3306,mysql -T fields -e mysql.query ’port 3306′

C помощью tshark можно записывать в лог информацию обо всех запросах к MySQL. Запустим захват всего MySQL-трафика с помощью tcpdump:

$ sudo tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out

Из полученного файла c помощью tshark извлечем список запросов:

$ sudo tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out

Из этого списка удалим пустые строки и сохраним отредактированный вариант в новом файле:

$ sudo cat query_log.out | grep -v "^$" | grep -v "^commit" | grep -v "^SET autocommit" | grep -v "^rollback" > query_log_no_blank.out

Заключение

Tshark — инструмент с очень широкими возможностями, о которых вряд ли возможно подробно рассказать в рамках одной статьи. На все вопросы мы с удовольствием ответим в комментариях. Будем рады, если вы поделитесь собственным опытом диагностики сетевых проблем с помощью tshark.