Тайм-менеджмент для системных администраторов
Шрифт:
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
Выполнив эту команду, мы увидим отсортированный список. Если сеть не очень загружена, выполнение команды займет какое-то время.
В локальной сети из 50 компьютеров, когда было мало пользователей, мне понадобилось около часа. Но это было уже после обнаружения компьютеров со шпионскими программами и их очистки. Перед этим на сбор ста ARP-пакетов я потратил всего несколько минут.
В вашей домашней сети с одним или двумя компьютерами на выполнение команды может уйти несколько дней. Хосты кэшируют информацию, собранную ими с помощью ARP-запросов. Поэтому, поработав некоторое время, компьютер крайне редко отправляет ARP-пакеты,[9] если единственный компьютер, с которым он общается (в локальной сети), — это ваш маршрутизатор.
Зато в сети из ста хостов подозреваемые обнаруживаются достаточно быстро.
Теперь в вашем распоряжении имеется простой инструмент обнаружения атаки червей. Он не заменит тысячедолларовую систему распознавания атак и хорошую антивирусную программу, но, безусловно, поможет вам локализовать проблему, если она возникнет. Главное — он бесплатный, а вы узнали кое-что новое о программировании оболочки.
Если вам захотелось отточить свое мастерство программиста, вот несколько небольших проектов: