Тайм-менеджмент для системных администраторов - Томас Лимончелли
Шрифт:
Интервал:
Закладка:
Вот команда, получившаяся у меня в итоге (прошу прощения за испорченный сюрприз):
$ sudo tcpdump — l -n агр | grep 'агр who-has' |
head -100 | awk '{ print $NF }' |sort | uniq — с | sort — n
Она такая длинная, что не помещается в одной строке этой книги, поэтому я разбил ее на две строки, а символом переноса служит обратный слэш. Вам не нужно набирать обратный слэш при вводе команды.[7] Не следует и нажимать клавишу Enter в этом месте.
Вывод команды выглядит так:
tcpdump: verbose output suppressed, use — v or — vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes
1 192.168.1.104
2 192.168.1.231
5 192.168.1.251
7 192.168.1.11
7 192.168.1.148
7 192.168.1.230
8 192.168.1.254
11 192.168.1.56
21 192.168.1.91
30 192.168.1.111
101 packets captured
3079 packets received by filter
0 packets dropped by kernel
Не обращайте внимание на две первые и три последние строки. В остальных строках указано количество пакетов и IP-адрес. Этот эксперимент показал, что хост 192.168.1.111 отправил 30 ARP-пакетов, а хост 192.168.104 — только один пакет. Большинство машин редко отправляли пакеты за исследуемый период, но два хоста отправили в 4–6 раз больше пакетов, чем остальные. Это свидетельствовало о проблеме. Быстрое сканирование антивирусной программой — и оба хоста стали как новенькие.
А теперь расскажу, как я строил эту командную строку. Я начал с команды:
$ sudo tcpdump — l -n arp
Здесь sudo означает, что следующая команда должна быть выполнена с правами пользователя root. Весьма вероятно, что она запросит пароль. Если в вашей среде нет sudo, вы можете воспользоваться аналогичной командой или выполнить эту последовательность от имени пользователя root.[8] Будьте внимательны. Человеку свойственно ошибаться, но настоящий храбрец не боится работать от имени root.
Команда tcpdump прослушивает Ethernet. Флаг -1 нужен, если мы собираемся направить вывод другой программе. Дело в том, что, в отличие от других команд, tcpdump выполняет буферизацию выходных данных для ускорения работы. Однако при направлении вывода в канал нам это не нужно. Флаг — n отключает поиск в DNS для каждого найденного IP-адреса. Параметр arр означает, что команда tcpdump должна отслеживать только ARP-пакеты.
(Если вас беспокоит этическая сторона вопроса, то должен сообщить вам хорошую новость. Если вы отфильтруете все, кроме ARP-пакетов, то на выходе будет очень мало частной информации.)
Выполните эту команду на своем компьютере. Вообще, если вы будете проверять на практике все, о чем здесь прочитаете, вы многому научитесь. Эта команда не удаляет никакие данные. Но должен вас предупредить, что отслеживание пакетов может быть незаконным. Делайте это, только если у вас есть соответствующее разрешение.
Когда я запускаю эту команду, вывод выглядит так:
$ sudo tcpdump — n -l агр
tcpdump: verbose output suppressed, use — v or — vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes
19:10:48,212755 arp who-has 192.168.1.110 (85:70:48:a0:00:10) tell 192.168.1.10
19:10:48,743185 arp who-has 192.168.1.96 tell 192.168.1.92
19:10:48,743189 arp reply 192.168.1.2 is-at 00:0e:e7:7a:b2:24 19:10:48.
743198 arp who-has 192.168.1.96 tell 192.168.1.111
^C
Чтобы прекратить вывод, я нажимаю клавиши CtrL–C Иначе он будет продолжаться вечно.
Если вы получили сообщение об ошибке доступа, скорее всего, вы запустили команду не как суперпользователь. Команда tcpdump может быть выполнена только пользователем root. Вы ведь не хотите, чтобы вашу сеть прослушивал кто попало, правда?
После заголовка идут строки вида «arp who-has X tell Y». Здесь Y — это хост, который задал вопрос. Вопрос имел примерно такое содержание: «Уважаемый хост с IP-адресом Х, не сообщите ли вы свой Ethernet (МАС) — адрес?» Вопрос отправляется широковещательным пакетом, поэтому мы видим все ARP-запросы в нашей локальной сети. Однако мы видим не так уж много ответов, поскольку они отправляются в виде однонаправленных пакетов, а мы находимся на концентраторе. В данном случае виден только один ответ, потому что мы находимся на одном концентраторе с тем компьютером (а, может, это компьютер, выполняющий команду, — этого я вам не скажу). Тем не менее, все хорошо; ведь нам нужны только те, кто задает вопросы.
Итак, у вас есть источник информации. Преобразуем ее так, чтобы ею можно было воспользоваться.
Во-первых, изолируем те строки вывода, которые нас интересуют. В данном случае это строки, содержащие «arp who-has»:
$ sudo tcpdump — l -n arp | egrep 'arp who-has'
Мы можем запустить эту команду и убедиться, что она ведет себя, как ожидалось. Единственная проблема в том, что команда работает безостановочно, пока мы не нажмем CtrL–C. Мы хотим получить достаточное количество строк и затем обработать их. Ограничимся первой сотней строк:
$ sudo tcpdump — l -n arp | grep 'arp who-has' | head -100
Снова запустим команду и убедимся, что все хорошо. Во время тестирования этой команды у меня не хватило терпения, и я изменил 100 на 10.
Это дало мне уверенность, что команда работает правильно, и в окончательном варианте я поставил 100. Вы, конечно, заметите в выводе кучу заголовков. Они направляются в поток stderr (прямо на экран) и не передаются в команду gгер.
Итак, у нас есть сто строк с интересующими нас данными. Настало время статистических подсчетов. Какие хосты генерируют больше всего ARP-пакетов? Нам нужно выделить IP-адреса всех хостов, сгенерировавших ARP-пакет, и как-то подсчитать их количество. Начнем с выделения IP-адресов. Это шестое поле каждой строки, и мы можем воспользоваться следующей командой:
awk '{ print $6 }'
Этот маленький фрагмент кода awk является прекрасной идиомой для выделения конкретного поля из каждой строки текста.
Должен сознаться, что мне было лень подсчитывать, в каком поле находятся данные, которые я хотел выделить. Было похоже, что это пятое поле, и я сначала пробовал указать $5. Не сработало, тогда я указал $6. Конечно! Мне следовало помнить, что в awk поля нумеруются с единицы, а не с нуля. Преимущество тестирования командной строки на каждом шаге в том и заключается, что мы достаточно рано обнаруживаем такие мелкие ошибки. Представьте, что было бы, если бы я написал всю командную строку сразу, а затем стал бы искать эту ошибку!
Я ленив и нетерпелив. Мне не хотелось каждый раз ждать, пока будут собраны все сто ARP-пакетов. Поэтому я сохранил их один раз и затем использовал эти результаты.
Я сохранил результаты во временном файле:
$ sudo tcpdump — l -n arp | grep 'arp wno-has' | head -100 >/tmp/x
Затем я применил свой код awk к этому временному файлу:
$ cat /tip/x | awk '{ print $5 }'
tell
tell
tell
tell
Оказывается, мне нужно не пятое поле. Попробуем шестое:
$ cat /tmp/х | awk '{ print $6 }'
192.168.1.110
192.168.1.10
192.168.1.92
…
Да, так лучше.
Как бы то ни было, впоследствии я понял, что можно ублажать свою лень другим способом. Конструкция $NF обозначает последнее поле и позволяет мне вообще ничего не подсчитывать:
$ cat /tmp/x | awk '{ print $HF }'
192.168.1.110
192.168.1.10
192.168.1.92
А почему не $LF? Ну, это было бы слишком просто. А если серьезно, NF означает «number of fields» (количество полей). То есть $NF обозначает NF-e поле слева. Но все это неважно. Просто запомните, что, если вам нужно последнее поле в строке, вы можете добавить $NF в awk:
$ sudo tcpdump — l -n arp | egrep 'arp who-has'
| head -100 | awk '{ print $NF }'
Итак, на выходе мы получаем список IP-адресов. Проверьте это.
(Именно так! Проверьте. Я подожду.)
Теперь мы хотим подсчитать, сколько раз каждый IP-адрес появляется в нашем списке. Есть одна идиома, которую я всегда применяю именно для этой цели:
sort | uniq — с
Она сортирует данные, а затем выполняет команду uniq, которая исключает повторения из отсортированного списка. (То есть технически она устраняет повторения соседних строк, а сортировка списка гарантирует, что одинаковые строки будут соседствовать.) Флаг — с включает подсчет повторений и вставляет это число в начало каждой строки. Результат выглядит так:
…
11 192.168.1.111
7 192.168.1.230
30 192.168.1.254
8 192.168.1.56
21 192.168.1.91
…
Мы почти у цели! Мы знаем, сколько ARP-пакетов отправил каждый хост. Последнее, что мы должны сделать, — это отсортировать список, чтобы выявить самые «общительные» хосты. Для этого добавляем в конец канала конструкцию | sort — n, которая выполнит сортировку по номеру:
$ sudo tcpdump — l -n arp | egrep 'arp who-has' | head -100
| awk '{ print $NF }' | sort | uniq — с | sort — n
Выполнив эту команду, мы увидим отсортированный список. Если сеть не очень загружена, выполнение команды займет какое-то время.