Тайм-менеджмент для системных администраторов - [82]

Шрифт
Интервал

Итак, у вас есть источник информации. Преобразуем ее так, чтобы ею можно было воспользоваться.

Во-первых, изолируем те строки вывода, которые нас интересуют. В данном случае это строки, содержащие «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

Выполнив эту команду, мы увидим отсортированный список. Если сеть не очень загружена, выполнение команды займет какое-то время.

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

В вашей домашней сети с одним или двумя компьютерами на выполнение команды может уйти несколько дней. Хосты кэшируют информацию, собранную ими с помощью ARP-запросов. Поэтому, поработав некоторое время, компьютер крайне редко отправляет ARP-пакеты,[9] если единственный компьютер, с которым он общается (в локальной сети), — это ваш маршрутизатор.

Зато в сети из ста хостов подозреваемые обнаруживаются достаточно быстро.

Теперь в вашем распоряжении имеется простой инструмент обнаружения атаки червей. Он не заменит тысячедолларовую систему распознавания атак и хорошую антивирусную программу, но, безусловно, поможет вам локализовать проблему, если она возникнет. Главное — он бесплатный, а вы узнали кое-что новое о программировании оболочки.