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