В практике системного администрирования довольно часто приходится cталкиваться со сложными ситуациями, в которых не помогают ни инструменты сбора статистики (например, 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.
Читателей, которые не могут оставлять комментарии здесь, приглашаем к нам в блог.